(* Common util. Should probably put this in a module or something.. *) let get_one_line file = try Some (input_line file) with End_of_file -> None let get_lines file = let rec input lines = match get_one_line file with Some line -> input (line :: lines) | None -> List.rev lines in input [] let read_file file = let channel = open_in(file) in get_lines channel let explode s = (* convert a string to a list of chars *) let rec exp i l = if i < 0 then l else exp (i - 1) (s.[i] :: l) in exp (String.length s - 1) [] let implode cl = String.concat "" (List.map (String.make 1) cl) let (<<) f g x = f(g(x)) (* how is 'compose' not in the standard library.. *) let (>>) f g x = g(f(x)) let string_of_char = String.make 1 (* --- *) let fix_lines glue_char lines = (* puts each group on 1 line *) let glue s = if String.equal s "" then "\n" else glue_char in (* which char to concat the lines *) let fix_line acc cur = acc ^ (glue cur) ^ cur in List.fold_left fix_line "" lines let dedup = explode >> (* string -> char list *) List.fold_left (fun acc x -> if String.contains acc x then acc else acc ^ (string_of_char x)) "" let intersection group = (* find the chars common to all individuals in a group *) List.fold_left (^) "" group (* *all* of the chars among individuals *) |> dedup (* deduped *) |> explode (* string to char list *) |> List.filter (fun c -> List.for_all (fun g -> String.contains g c) group) (* check each char among each individual for membership *) |> implode (* turn it back into a string *) let () = let file = read_file "day6.txt" in let any_sum = file |> fix_lines "" (* put each group on one line *) |> String.split_on_char '\n' (* convert to list *) |> List.map dedup (* remove dups *) |> List.map String.length (* make list of lengths *) |> List.fold_left (+) 0 (* sum list *) in let all_sum = file |> fix_lines " " (* keep spaces between individuals *) |> String.split_on_char '\n' |> List.map String.trim |> List.map (String.split_on_char ' ') (* each line now is a list of groups *) |> List.map intersection (* list of strings with intersecting chars *) |> List.map String.length (* list of lengths *) |> List.fold_left (+) 0 (* sum list *) in Printf.printf "any_sum %i\n" any_sum; Printf.printf "all_sum %i\n" all_sum;