~turminal/aoc2022

9e263d5090f476228b05f95b4f593a84a57a9e29 — Bor Grošelj Simić 1 year, 10 months ago 4fb85e6
day 3
3 files changed, 83 insertions(+), 0 deletions(-)

A 3/lex.mll
A 3/t1.ml
A 3/t2.ml
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"