I have been refactoring my OCaml resolution for Challenge Euler drawback 54, which is about evaluating poker fingers.
Whereas I am largely glad with my second iteration of the refactor, I stumbled upon two options in Haskell.
I used to be stunned by the brevity, and though I am not acquainted with Haskell, I discovered that the each options make the most of the “guard” syntax.
That is my present model in OCaml:
Varieties & Utilities
open Core sort worth = N of int | J | Q | Okay | A [@@deriving eq, ord] sort go well with = char sort card = worth * go well with sort rank = HighCard | OnePair | TwoPair | ThreeOfAKind | Straight | Flush | FullHouse | FourOfAKind | StraightFlush (* incorporates royal flush *) [@@deriving ord] sort rating = rank * worth checklist [@@deriving ord] let get_suit : card -> go well with = snd let get_value : card -> worth = fst let eval_value = perform | N n -> n | J -> 11 | Q -> 12 | Okay -> 13 | A -> 14 let get_eval (card : card) = eval_value (get_value card) let rev_sort l cmp = Record.kind l (enjoyable a b -> -(cmp a b))
let check_straight hand = let sorted = Record.dedup_and_sort compare_int (Record.map hand get_eval) in if Record.size sorted <> 5 then false else if Record.equal ( = ) sorted [2; 3; 4; 5; 14] then true else Record.last_exn sorted - Record.hd_exn sorted = 4 let check_flush hand = ( hand |> Record.map ~f:get_suit |> Record.remove_consecutive_duplicates ~equal:equal_char |> Record.size ) = 1 let get_kind (n : int) ?(besides : worth choice = None) (hand : card checklist) = let values = Record.map hand get_value in Record.discover values (enjoyable v -> match besides with | Some v' when equal_value v v' -> false | _ -> Record.rely values (equal_value v) = n )
let get_score hand = let values = rev_sort (Record.map hand get_value) compare_value in let is_straight = check_straight hand in let is_flush = check_flush hand in if is_straight && is_flush then (StraightFlush, values) else match get_kind Four hand with | Some v -> (FourOfAKind, v :: values) | None -> start let three_of_a_kind = get_kind Three hand in let pair = get_kind 2 hand in match three_of_a_kind, pair with | Some v1, Some v2 -> (FullHouse, [v1; v2]) | _ when is_flush -> (Flush, values) | _ when is_straight -> (Straight, values) | Some v, None -> (ThreeOfAKind, v :: values) | None, Some v -> start match get_kind 2 ~besides:(Some v) hand with | Some v' -> (TwoPair, (rev_sort [v; v'] compare_value) @ values) | None -> (OnePair, v :: values) finish | None, None -> (HighCard, values) finish let get_winner hand1 hand2 = match compare_score (get_score hand1) (get_score hand2) with | 1 -> 1 | 0 -> 0 | -1 -> 2 | _ -> failwith "Unattainable"
Deal with Enter
let parse str = let worth = match str. with | 'T' -> N 10 | 'J' -> J | 'Q' -> Q | 'Okay' -> Okay | 'A' -> A | c -> N (Char.get_digit_exn c) in let go well with = str. in (worth, go well with) let () = let wins = In_channel.read_lines "./054-poker.txt" |> Record.map ~f:(enjoyable line -> let playing cards = line |> String.break up ~on:' ' |> Record.map ~f:parse in let hand1, hand2 = Record.split_n playing cards 5 in get_winner hand1 hand2 ) |> Record.rely ~f:(( = ) 1) in printf "Participant 1 received %d timesn" wins
It depends on JaneStreet’s Core and the ppx_deriving.
ppx_deriving is used to generate
I feel it corresponds with
deriving (Eq, Ord) of Haskell.
I am not involved with efficiency right here, because it runs actually quick: 2.5 s for one million strains of enter.
Nevertheless, the code is about 3~Four instances longer than the Haskell counterparts.
Since Haskell appears to be usually extra concise than OCaml, I do not anticipate it to get as brief.
But I nonetheless marvel if it will possibly get extra concise, with out sacrificing efficiency and/or readability, particularly the
get_score methodology of my code.
Is there a technique to simplify the
get_score, probably by modifying the info buildings I outlined?
This can be a hyperlink to my code, and I compiled with:
ocamlfind ocamlopt -o 054-poker-hands.out -linkpkg -package core,stdio,ppx_deriving.std -thread 054-poker-hands.ml