算数にチャレンジ

30分プログラム、その437。算数にチャレンジしてみた - こげこげ堂はてな支舗より。

1〜512の数の書かれたカードが1枚ずつ、左から小さい順に、「1,2,3,4,・・・,511,512」と並んでいます。いま、次のような作業を行うことにします。

ア. 前から奇数番目のカードをすべて取り除く
イ. 前から偶数番目のカードをすべて取り除く

まず、この作業を、ア→イ→ア→イ→・・・の順に、カードが残り1枚になるまで繰り返して行うことにします。

このとき、最後に残るカードに書かれた数字を答えてください。

使い方

*Main> solveOdd [1..512]
171

ソースコード

type Card = Int

evenFilter :: [Card] -> [Card]
oddFilter :: [Card] -> [Card]

evenFilter xs =
    map fst $ filter (\(_,i) -> i `mod` 2 == 0) $ zip xs [1..]
oddFilter xs =
    map fst $ filter (\(_,i) -> i `mod` 2 == 1) $ zip xs [1..]


solveEven  :: [Card] -> Card
solveOdd   :: [Card] -> Card

solveEven [x] = x
solveEven xs  = solveOdd $ evenFilter xs
solveOdd [x]  = x
solveOdd xs   = solveEven $ oddFilter xs