A 3/lex.mll => 3/lex.mll +14 -0
@@ 0,0 1,14 @@
+{
+type token =
+ | Str of string
+ | Eof
+}
+
+rule token = parse
+ | ['a'-'z''A'-'Z']+ '\n' as str {
+ Str (
+ String.length str - 1
+ |> String.sub str 0
+ )
+ }
+ | eof { Eof }
A 3/t1.ml => 3/t1.ml +33 -0
@@ 0,0 1,33 @@
+open Lex
+
+module S = Set.Make(Char)
+
+let rec f lexbuf =
+ match Lex.token lexbuf with
+ | Eof -> []
+ | Str s -> s :: f lexbuf
+
+let setify s = String.fold_right S.add s S.empty
+
+let diff s =
+ let half = String.length s / 2 in
+ let l, r = setify (String.sub s 0 half), setify (String.sub s half half) in
+ S.choose (S.inter l r)
+
+let score c =
+ let (start, offset) =
+ match c with
+ | 'a'..'z' -> ('a', 0)
+ | 'A'..'Z' -> ('A', 26)
+ | _ -> invalid_arg "score"
+ in
+ Char.code c - Char.code start + 1 + offset
+
+let () =
+ stdin
+ |> Lexing.from_channel
+ |> f
+ |> List.map diff
+ |> List.map score
+ |> List.fold_left (+) 0
+ |> Printf.printf "%d\n"
A 3/t2.ml => 3/t2.ml +36 -0
@@ 0,0 1,36 @@
+open Lex
+
+module S = Set.Make(Char)
+
+let rec f lexbuf =
+ match Lex.token lexbuf with
+ | Eof -> []
+ | Str s -> s :: f lexbuf
+
+let setify s = String.fold_right S.add s S.empty
+
+let rec find_badges = function
+ | [] -> []
+ | a :: b :: c :: l ->
+ let a, b, c = setify a, setify b, setify c in
+ let d = S.inter (S.inter a b) c in
+ S.choose d :: find_badges l
+ | _ -> invalid_arg "find_badges"
+
+let score c =
+ let (start, offset) =
+ match c with
+ | 'a'..'z' -> ('a', 0)
+ | 'A'..'Z' -> ('A', 26)
+ | _ -> invalid_arg "score"
+ in
+ Char.code c - Char.code start + 1 + offset
+
+let () =
+ stdin
+ |> Lexing.from_channel
+ |> f
+ |> find_badges
+ |> List.map score
+ |> List.fold_left (+) 0
+ |> Printf.printf "%d\n"