このページについて
このページは、paiza ラーニング内に開設されているコンテンツ「レベルアップ問題集」で取り扱われているプログラミング課題について、独自の見解を述べたものです。
見解については、paizaラーニングの規約に基づき、許可されている範囲でのみ公開していますが、その内容については paiza とは一切関係なく、また paiza の立場を反映したものではありませんのでご注意ください。
挑戦する課題
レベルアップ問題集の日付セットから「年月日の順序 (paizaランク C 相当) 」を取り上げます。
以下は、問題公開 Web ページからの引用です。
問題
3つの数値A, B, Cが”/”で区切りで与えられます。
A, B, Cがそれぞれ年、月、日のいずれに対応しているかの並び順を出力してください。
年、月、日は次のすべての条件を満たす文字列のことです。
- 年は4つの数字からなる
- 月は2つの数字からなり、”01″から”12″の12種類のいずれかである
- 日は2つの数字からなり、”01″から”31″の31種類のいずれかである
入力される値
以下の形式で、数値A, B, Cが与えらます。
1 |
A/B/C |
期待する出力
A, B, Cのそれぞれについて、年に対応するなら”YYYY”、月に対応するなら”MM”、日に対応するなら”DD”を”/”区切りで1行に出力してください。
ただし、正しい並びが存在しない場合は、”no answer”と出力し、
2つ以上の並びが考えられる場合は、”many answers”と出力してください。
条件
すべてのテストケースにおいて、以下の条件を満たします。
- A, B, Cはそれぞれ長さが2か4の数字だけからなります。
考え方
まず日付について、与えられた条件をもとに整理する必要がある。
- 年については
- 「4桁の数字」としかないため、 0000 や 9999 が入力されても問題ないものとする。
- 月については
- 01 から 12 までとあるので、 00 や 13 以上の数値が入力されることはない。
- 日については
- 01 から 31 までとあるので、 00 や 32 以上の数値が入力されることはない。
- 2月の扱いや閏年の扱いについては言及がないため、 02/28 のような入力があったとしてエラーとする必要はない。
これらの条件から、次の手順で条件判定を行なう。
- 2桁となる2組の数値いずれもが 1...12 の範囲に収まる場合、月日の区別はつかないため "many answers" となる。
- 2桁となる2組の数値のうち、最小値が
、もしくは最小値が
13 以上、あるいは最大値が
31 となる場合、日付として成立しないため
"no answer" となる。
- 0月1日や1月0日のような日付は存在しない。
- 13月13日のような日付は存在しない。
- 12月32日のような日付も存在しない。
- これらの条件にパスした場合、
- 数値が4桁であれば、それは西暦に相当するため "YYYY" とする
- 数値に変換し、それが 13...31 であれば、それは日付に相当するため "DD" とする
- それ以外であれば、それは月に相当するため "MM" とする
実際は、これらを逐次出力し、スラッシュで区切る必要があるが、行末処理が煩雑になるため、一度 String の空配列( [String])を作っておき、出現順に "YYYY", "MM", "DD" を追加する。たとえば、入力が 18/10/1993 であれば、 ["DD", "MM", "YYYY"] という配列とする。
最後に、この配列に対して joined(separator: "/") を使い連結させ表示させることで、用件を満たす。
解答例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// 入力文字列をスラッシュで区切る。YYYY は 0000 の可能性もあるので文字列のまま let sa = readLine()!.split(separator: "/").map{ String($0) } // 答を入れる文字列の配列 var ans = [String]() // MM/DDに該当する部分(つまり、文字長が2)の部分を抜き出し、Int にする let d = sa.filter { $0.count == 2 }.map { Int($0)! } if 1...12 ~= d.max()! { // MM or DD いずれも 1...12 の範囲だと、月日の区別がつかない print("many answers") } else if d.min()! == 0 || d.min()! > 12 || d.max()! > 31 { // MM or DD のいずれかが 0 もしくは 31 より大きいことはありえない print("no answer") } else { for s in sa { switch s { case let y where y.count == 4: // 文字長が 4 の場合 ans.append("YYYY") case let m where 13...31 ~= Int(m)!: // 与えられた数値が 13...31 の範囲であれば日付 ans.append("DD") default: // それ以外であれば月 ans.append("MM") } } // ["MM", "YYYY", "DD"] のような形式で代入されているので、スラッシュ区切りで出力 print(ans.joined(separator: "/")) } |