Go で ABC126 B - YYMM or MMYY を解いてみました。
問題
問題文
長さ 4 の数字列 S が与えられます。あなたは、この数字列が以下のフォーマットのどちらであるか気になっています。
- YYMM フォーマット: 西暦年の下 2 桁と、月を 2 桁で表したもの (例えば 1 月なら 01) をこの順に並べたもの
- MMYY フォーマット: 月を 2 桁で表したもの (例えば 1 月なら 01) と、西暦年の下 2 桁をこの順に並べたもの
与えられた数字列のフォーマットとして考えられるものが YYMM フォーマットのみである場合 YYMM を、 MMYY フォーマットのみである場合 MMYY を、 YYMM フォーマット と MMYY フォーマットのどちらの可能性もある場合 AMBIGUOUS を、 どちらの可能性もない場合 NA を出力してください。
制約
S は長さ 4 の数字列
( https://atcoder.jp/contests/abc126/tasks/abc126_b より引用)
考え方
問題文にあるとおりの条件式を書いて判定するだけですが、コンテスト本番で2回WAを出してしまいました(条件式の構成は苦手です)。
上位2桁と下位2にわけて考えると、まず、それぞれの2桁がYYになりうるか、MMになりうるか、を判定する必要があります。
- YYについては、2桁のすべての組み合わせ、
00
から99
まで、YY として正しいYY表記である。 - MM については文字列ではなく数値として解釈した場合に、 $ 1 \le MM \le 12 $ を満たしているときのみ正しいMM表記であり、満たさない場合、つまり 0 および $ 13 \le M $ の場合には MM 表記としては不正。
よって、 2つの2桁について、MM の場合のみ判定すればOKです。
さらに、最終的な答えを出すには YYMM
表記なのか MMYY
表記なのか、 どちらにもなりうる(AMBIGUOUS
)のか、どちらもありえないのか(NA
) の4パターンで判定する必要があります。
愚直に上位2桁がMMになりうるかを見て、下位2桁がMMになりうるか/そうでないか、……とやると、次のようなコードになります。
func main() {
defer stdout.Flush()
S := readInt()
H := S / 100
L := S % 100
if mm(H) {
if mm(L) {
println("AMBIGUOUS")
} else {
println("MMYY")
}
} else {
if mm(L) {
println("YYMM")
} else {
println("NA")
}
}
}
func mm(a int) bool {
if 1 <= a && a <= 12 {
return true
}
return false
}
ですが、ここでは次のコードのように、「どちらにもなりうる(AMBIGUOUS
)」のパターン、つまり上位下位どちらもMMになりうる場合をまず判定してしまうことで、ネストが減って少しだけ見通しがよくなります(条件判定部分のみ抜粋)。
if mm(H) && mm(L) {
println("AMBIGUOUS")
return
}
if mm(L) {
println("YYMM")
return
}
if mm(H) {
println("MMYY")
return
}
println("NA")
提出コード
コンテストでは次のようなコードを書きました(抜粋)。全体はこちら
(コンテストでは↑のようなことをちゃんと考えて書けばよかったんですが、適当に書いた結果 1WA, サンプルを誤読して、 「00 だと YY 判定NG」と、ホントかよと思いつつ勘違いしてしまい1WAを食らってしまいました。提出コードには、その試行錯誤した痕跡が見られます。)
func main() {
defer stdout.Flush()
S := readInt()
x := S / 100
y := S % 100
//eprintln(x, y)
if mm(x) && yy(y) && yy(x) && mm(y) {
println("AMBIGUOUS")
return
}
if yy(x) && mm(y) {
println("YYMM")
return
}
if mm(x) && yy(y) {
println("MMYY")
return
}
println("NA")
}
func mm(a int) bool {
if 1 <= a && a <= 12 {
return true
}
return false
}
func yy(a int) bool {
return true
}