~turminal/aoc2022

8889c19dda8e162b5648676ead8cd718cdea968d — Bor Grošelj Simić 1 year, 8 months ago 18b1f6c master
day 9
3 files changed, 111 insertions(+), 0 deletions(-)

A 9/lex.mll
A 9/t1.ml
A 9/t2.ml
A 9/lex.mll => 9/lex.mll +11 -0
@@ 0,0 1,11 @@
{
type token =
	| Line of char * int
	| Eof

let i = int_of_string
}

rule token = parse
  | (['A'-'Z'] as c) ' ' (['0'-'9']+ as s) '\n' { Line (c, i s) }
	| eof { Eof }

A 9/t1.ml => 9/t1.ml +49 -0
@@ 0,0 1,49 @@
let rec f lexbuf =
	match Lex.token lexbuf with
	| Eof -> []
	| Line (c, i) ->
			let dir =
				match c with
				| 'L' -> (-1, 0)
				| 'R' -> (1, 0)
				| 'U' -> (0, 1)
				| 'D' -> (0, -1)
				| _ -> failwith "wut"
			in
			(dir, i) :: f lexbuf

module PairSet = Set.Make(
	struct
		type t = int * int
		let compare = compare
	end
)

let move' (x, y) (dx, dy) = x + dx, y + dy

let move_follow ((x, y) as tail) (x', y') =
	let d =
		match x'- x, y' - y with
		| dx, dy when abs dx = 2 -> dx / 2, dy
		| dx, dy when abs dy = 2 -> dx, dy / 2
		| _ -> 0, 0
	in
	move' tail d

let move_tail set tail head =
	let newtail = move_follow tail head in
	(PairSet.add newtail set, newtail, head)

let rec move ((set, tail, head) as state) (d, n) =
	match n with
	| 0 -> state
	| n -> move (move_tail set tail (move' head d)) (d, n - 1)

let () =
	stdin
		|> Lexing.from_channel
		|> f
		|> List.fold_left move (PairSet.singleton (0, 0), (0, 0), (0, 0))
		|> fun (x, _, _) -> x
		|> PairSet.cardinal
		|> Printf.printf "%d\n"

A 9/t2.ml => 9/t2.ml +51 -0
@@ 0,0 1,51 @@
let rec f lexbuf =
	match Lex.token lexbuf with
	| Eof -> []
	| Line (c, i) ->
			let dir =
				match c with
				| 'L' -> (-1, 0)
				| 'R' -> (1, 0)
				| 'U' -> (0, 1)
				| 'D' -> (0, -1)
				| _ -> failwith "wut"
			in
			(dir, i) :: f lexbuf

module PairSet = Set.Make(
	struct
		type t = int * int
		let compare = compare
	end
)

let move' (x, y) (dx, dy) = x + dx, y + dy

let move_follow (x', y') ((x, y) as tail) =
	let d =
		match x' - x, y' - y with
		| dx, dy when abs dx = 2 -> dx / 2, dy
		| dx, dy when abs dy = 2 -> dx, dy / 2
		| _ -> 0, 0
	in
	let tail = move' tail d in
	tail, tail

let move_tail set tail head =
	let last, tail = List.fold_left_map move_follow head tail in
	(PairSet.add last set, tail, head)

let rec move ((set, tail, head) as state) (d, n) =
	match n with
	| 0 -> state
	| n -> move (move_tail set tail (move' head d)) (d, n - 1)

let () =
	let init = List.init 8 (fun _ -> (0, 0)) in
	stdin
		|> Lexing.from_channel
		|> f
		|> List.fold_left move (PairSet.singleton (0, 0), init, (0, 0))
		|> fun (x, _, _) -> x
		|> PairSet.cardinal
		|> Printf.printf "%d\n"