RosettaCodeData/Task/Textonyms/OCaml/textonyms.ml

44 lines
1.2 KiB
OCaml

module IntMap = Map.Make(Int)
let seq_lines ch =
let rec repeat () =
match input_line ch with
| s -> Seq.Cons (s, repeat)
| exception End_of_file -> Nil
in repeat
(* simply use bijective numeration in base 8 for keys *)
let key_of_char = function
| 'a' .. 'c' -> Some 1
| 'd' .. 'f' -> Some 2
| 'g' .. 'i' -> Some 3
| 'j' .. 'l' -> Some 4
| 'm' .. 'o' -> Some 5
| 'p' .. 's' -> Some 6
| 't' .. 'v' -> Some 7
| 'w' .. 'z' -> Some 8
| _ -> None
let keys_of_word =
let next k c =
Option.bind (key_of_char c) (fun d -> Option.map (fun k -> k lsl 3 + d) k)
in String.fold_left next (Some 0)
let update m k =
IntMap.update k (function Some n -> Some (succ n) | None -> Some 1) m
let map_from ch =
seq_lines ch |> Seq.filter_map keys_of_word |> Seq.fold_left update IntMap.empty
let count _ n (words, keys, txtns) =
words + n, succ keys, if n > 1 then succ txtns else txtns
let show src (words, keys, txtns) = Printf.printf "\
There are %u words in %s which can be represented by the digit key mapping.\n\
They require %u digit combinations to represent them.\n\
%u digit combinations represent Textonyms.\n" words src keys txtns
let () =
show "stdin" (IntMap.fold count (map_from stdin) (0, 0, 0))