ひさしぶりのAtCoderの振り返りです。
前回が345なので、4回ぶりの記事になります。
今回の結果
A,B,C 3完でした。かなり久しぶりの3完です。
各問題の振り返り
A - Zero Sum Game
問題を見た瞬間、これA問題に持ってきていいレベルじゃなくない?と一瞬焦りました。
しかし、よく問題を読むと、各ゲームでは勝者の持ち点が1増え、敗者の持ち点が1減ります
と書いてあることから、全プレイヤーの総得点は0になることがわかります。
ここから、N-1
までのプレイヤーの総得点を計算して、正負を逆転すると答えになることがわかります。
main :: IO ()
main = do
_ <- readLn @Int
ns <- readInputInts
print $ -1 * L.sum ns
B - Commencement
問題文から、ある一定回数現れる文字の種類が2つある or 存在しない
ことを確認すれば良さそうだなとなります。
これを元により具体的な解法を考えると以下の様です。
- 文字列をsortしてグルーピングし、グループごとに配列の長さを求める。これが各文字の出現回数の配列になる
- 1.で求めた配列をまたsortしてグルーピングし、長さを求める。これが出現回数毎の文字の種類になる.
- 最後に配列の値が全て2になっていることを確認する(出現回数が0の文字については、そもそも配列に含まれないので考慮する必要がない)
これをコードに起こすと以下の通りになります。
main :: IO ()
main = do
ss <- getLine
putStrLn $ if (all ((== 2) . length) . L.group . L.sort . L.map length . L.group . L.sort) ss || null ss then "Yes" else "No"
余談ですが、ここはall
にしないといけないのですが誤ってany
にして2ペナをくらってしまいました。any
だと"いずれかひとつの要素がTrueになるとTrueを返す"ので答えが違ってしまいます。なのに普通にall
にしたと勘違いしてしまいました。凡ミス。。
C - Airport Code
ある3文字が部分文字列(連続しなくて良い)に含まれてることを確認すればよいので、一つずつelemIndex
でindexを取得しdrop
で落とせばよいです。
3文字なので、計算量も高々O(3*n)
でしかないのでACできると判断しました。(n
は探索対象の文字数)
実装は問題なかったのですが、drop
する時に失敗して、drop (i + j) s
にしてしまったせいで1ペナをくらってしまいました。
drop
は指定した要素数を除外するのにたいして、elemIndex
で取得するのは0はじまりの配列の位置なので、2文字目以降でdrop
する時はelemIndex
の結果に1を足さなければなりません。
また、2文字目の探索(elemIndex
)では、1文字目の位置をdrop
した後の点が始点になっているので
3文字目の探索の時に
(1文字目のelemIndexの結果 + 1) + (2文字目のelemIndexの結果 + 1)
をdrop
しなければいけませんでした。
drop
する時はミスりがちなところなので気をつけないとですね。
main :: IO ()
main = do
s <- getLine
t <- L.map toLower <$> getLine
let l = L.elemIndex (head t) s
let m = (\i -> L.elemIndex (t !! 1) (L.drop (i + 1) s)) =<< l
let res = maybe False (\(i, j) -> (t !! 2 == 'x') || L.elem (t !! 2) (L.drop ((i + j) + 2) s)) $ liftM2 (,) l m
putStrLn $ if res then "Yes" else "No"
全体を振り返って
今回割と調子良かったので、次回もこれくらい解けるといいなと感じました。
あとは、もう少しarrayを使うのに慣れたいと思っています。使える様になると色々応用が効きそうなので。