読者です 読者をやめる 読者になる 読者になる

やたーDiceをOCamlで書いたよー

Programming Algorithm JOI OCaml

長年JOIer達の間で「どうやればきれいに解けるのか」「無理」という会話がなされてきたDiceをOCamlで解いた。

よっしゃ結構きれいや!と思ってドヤ顔をしつつ他のC++のソースとか参照してたら別にきれいでもない上にこっちのほうが長かったので死にたい。
でもすごく短かいソースは「これ書いててバグらなかったんですね…(困惑)」みたいな感じなのでべつにいいです。
実際書いてる途中で何度も型検査に助けられたので、一発で通る率は圧倒的にC++とかよりOCamlのほうが高いと思います。

問題文はこちら。
AIZU ONLINE JUDGE
AOJはOCamlに対応しろ!

type direction = North  | East | South | West | Right | Left;;
type dice = { top:int; east:int; north:int; west:int; south:int; bottom:int; };;

let solve n =
        let rec read n l = 
                if n > 0 then
                        let convert = function
                                | "North" -> North
                                | "East" -> East
                                | "South" -> South
                                | "West" -> West
                                | "Right" -> Right
                                | "Left" -> Left
                                | _ -> raise Not_found
                        in read (n - 1) ((Scanf.scanf "%s\n" convert)::l)
                else l
        and make_dice () = {
                top = 1; bottom = 6;
                east = 3; west = 4;
                south = 2; north = 5;}
        in let solve_impl n =
                let turn_dice d dir = match dir with
                | North -> {d with
                        top = d.south; south = d.bottom;
                        bottom = d.north; north = d.top;}
                | East -> {d with
                        top = d.west; west = d.bottom;
                        bottom = d.east; east = d.top;}
                | West -> {d with
                        top = d.east; east = d.bottom;
                        bottom = d.west; west = d.top;}
                | South -> {d with
                        top = d.north; north = d.bottom;
                        bottom = d.south; south = d.top;}
                | Right -> {d with
                        east = d.north; north = d.west;
                        west = d.south; south = d.east;}
                | Left -> {d with
                        east = d.south; south = d.west;
                        west = d.north; north = d.east;}
                in let directions = read n []
                and f dir (dic, score) =
                        let next_dice = (turn_dice dic dir)
                        in (next_dice, score + next_dice.top)
                in snd (List.fold_right f directions ((make_dice ()), 1))
        in Printf.printf "%d\n" (solve_impl n)

in let rec next () =
        Scanf.scanf "%d\n" (fun n -> if n > 0 then (solve n(*; next ()*)))
in next ();;