今年のオイラー書き初め。
今回の三問はわりとすんなり解けた印象がある。
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.SplitsplitOnを使うのが簡単そうだったけど、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

Copyright© 2011-2021 Shunsuke Otani All Right Reserved .