今年のオイラー書き初め。
今回の三問はわりとすんなり解けた印象がある。
今回の三問はわりとすんなり解けた印象がある。
Problem 52. Permuted multiples(置換倍数)
…むむっ。問題を素直にコードに落とし込んだだけだけど解けてしまった。
特に工夫の余地も無いように思うが、こんなんで良かっただろうか…?
Problem 53. Combinatoric selections(組み合わせ選択)
こちらも深く考えずそのまんま解いた。fact関数は↓こういう書き方が定番な気がするけど、
foldl
でワンライナーで書けそうだったのでやってみたくらいか。fact :: (Eq a, Num a) => a -> a fact 0 = 1 fact n = n * (fact $ n - 1)
Problem 54. Poker hands(ポーカーハンド)
前2問に比べると考えないといけない事は多いか。文字列からポーカーの役を作る、プレイヤー1と2の役の勝敗をつける、という処理が必要。
うーむ、頑張って作り込んでみたけど、もう少し簡潔にできる所もあるかなぁ。
ファイルから読み込んだ
"8C TS KC 9H 4S 7D 2S 5D 3S AC"
といった文字列をスペース毎に区切る処理はData.List.Splitの
splitOn
を使うのが簡単そうだったけど、Data.Listパッケージだけで自作してみた。A(1)がK(13)より大きく、2が一番小さいという比較判定にする必要があるので、
newtype Rank
を作ってOrd
を自前実装してみた。Enum
も自前実装すればisConsecutive
の判定が綺麗に書けるかな、とも思ったけど、そうでも無さそうだったのでやめた。
実装するとしたら↓こんな感じになるか。
instance Enum Rank where succ (Rank 13) = Rank 1 succ (Rank 1) = error "bad argument" succ (Rank n) = Rank $ succ n pred (Rank 1) = Rank 13 pred (Rank 2) = error "bad argument" pred (Rank n) = Rank $ pred n toEnum n = Rank n fromEnum (Rank n) = nこれだと
isConsecutive
は↓こんな感じになるけど、結局1を特別扱いしていて
Enum
自前実装のありがたみがそんなに無いように思う。isConsecutive ranks = all (\(x, y) -> if y == Rank 1 then False else x == succ y) $ zip ranks $ tail ranks