Skip to content

Commit c45019c

Browse files
committed
2025 Day 10.1 & Day 11
1 parent 9a47894 commit c45019c

File tree

4 files changed

+176
-5
lines changed

4 files changed

+176
-5
lines changed

2025/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ inputs
33
flamegraph.svg
44
stacks.folded
55
perf.data
6+
perf.data.old

2025/days/Day10.ml

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,86 @@
11
open Utils
22

3-
let day10 input =
4-
("TODO", "TODO")
3+
let parse_int_list s = String.split_on_char ',' s |> List.map int_of_string
4+
let parse_lights s =
5+
String.fold_right (fun c a -> match c with
6+
| '#' -> 2 * a + 1
7+
| '.' -> 2 * a
8+
| _ -> a) s 0
9+
let parse_buttons s =
10+
String.split_on_char ' ' (trim_end_nl s)
11+
|> List.map (fun s ->
12+
parse_int_list (String.sub s 1 (String.length s - 2))
13+
|> List.fold_left (fun a d -> a + Int.shift_left 1 d) 0)
14+
15+
let parse input =
16+
let input = trim_end_nl input in
17+
String.split_on_char '\n' input
18+
|> List.map (fun l ->
19+
let a, b = string_split_once " " l in
20+
let b, c = string_split_once "{" b in
21+
let c = String.sub c 0 (String.length c - 1) in
22+
23+
String.length a - 2,
24+
parse_lights a,
25+
parse_buttons b |> Array.of_list,
26+
parse_int_list c |> Array.of_list)
27+
28+
type 'a control = Continue of 'a | Stop of 'a
29+
30+
let select i a =
31+
let rec aux i o =
32+
if i = 0 then []
33+
else if Int.logand i 1 = 1 then a.(o) :: aux (Int.shift_right i 1) (o + 1)
34+
else aux (Int.shift_right i 1) (o + 1) in
35+
aux i 0
36+
37+
let bin_of_int n =
38+
if n = 0 then "0" else
39+
let rec aux n = if n = 0 then "" else aux (n / 2) ^ if n mod 2 = 0 then "0" else "1" in
40+
aux n
41+
42+
let turn_on (n, lights, buttons, _) =
43+
let k = Array.length buttons in
44+
let m = Int.shift_left 1 k in
45+
range 0 (m - 1)
46+
|> List.filter (fun i -> List.fold_left Int.logxor 0 (select i buttons) = lights)
47+
|> List.map Ocaml_intrinsics.Int.count_set_bits
48+
|> List.fold_left min (k + 1)
549

50+
let fold_bin f acc bin =
51+
let rec aux off bin acc =
52+
if bin = 0 then acc
53+
else
54+
let skip = Ocaml_intrinsics.Int.count_trailing_zeros bin in
55+
aux (off + skip + 1) (Int.shift_right bin (skip + 1)) (f acc (off + skip))
56+
in aux 0 bin acc
657

58+
let string_of_button b = "(" ^ (fold_bin (fun a i -> string_of_int i :: a) [] b |> String.concat ",") ^ ")"
59+
let string_of_buttons bs = String.concat " " @@ List.map string_of_button @@ Array.to_list bs
60+
let string_of_joltages jolts = "{" ^ (String.concat " " @@ List.map string_of_int @@ Array.to_list jolts) ^ "}"
61+
62+
let push_button b jolts =
63+
fold_bin (fun _ i -> jolts.(i) <- jolts.(i) - 1) () b
64+
65+
let can_press b jolts = fold_bin (fun f i -> f && jolts.(i) >= 1) true b
66+
67+
let min_joltage (_, _, buttons, joltage) =
68+
let k = Array.length buttons in
69+
let constraints = Array.mapi
70+
(fun i j ->
71+
range 0 (k - 1)
72+
|> List.filter (fun l -> Int.logand buttons.(l) (Int.shift_left 1 i) = 1),
73+
j
74+
) joltage in
75+
failwith ""
76+
77+
let solve_part1 machines =
78+
List.map turn_on machines |> List.fold_left (+) 0
79+
let solve_part2 machines =
80+
List.map min_joltage machines |> List.fold_left (+) 0
81+
82+
let day10 input =
83+
let machines = parse input in
84+
let part1 = solve_part1 machines in
85+
let part2 = solve_part2 machines in
86+
(string_of_int part1, string_of_int part2)

2025/days/Day11.ml

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,96 @@
11
open Utils
22

3-
let day11 input =
4-
("TODO", "TODO")
3+
type graph = { edges: int list array; flipped: int list array }
4+
type checkpoint = { node: int; ancestors: bool array }
5+
6+
let you = 0
7+
let out = 1
8+
let svr = 2
9+
let dac = 3
10+
let fft = 4
11+
12+
let flip_edges edges =
13+
let n = Array.length edges in
14+
let flipped = Array.make n [] in
15+
16+
Array.iteri (fun i -> List.iter (fun j -> flipped.(j) <- i :: flipped.(j))) edges;
17+
18+
flipped
19+
20+
let parse input =
21+
let input = trim_end_nl input in
22+
let name_tbl = Hashtbl.create 100 in
23+
let id_of_name name = match Hashtbl.find_opt name_tbl name with
24+
| Some id -> id
25+
| None -> (let id = Hashtbl.length name_tbl in Hashtbl.add name_tbl name id; id)
26+
in
27+
28+
ignore @@ id_of_name "you";
29+
ignore @@ id_of_name "out";
30+
ignore @@ id_of_name "svr";
31+
ignore @@ id_of_name "dac";
32+
ignore @@ id_of_name "fft";
33+
34+
let edges = String.split_on_char '\n' input
35+
|> List.map (fun l ->
36+
let self, b = string_split_once ": " l in
37+
let outputs = String.split_on_char ' ' b in
38+
id_of_name self, List.map id_of_name outputs) in
39+
let graph = Array.make (Hashtbl.length name_tbl) [] in
40+
41+
List.iter (fun (self, outputs) ->
42+
graph.(self) <- outputs @ graph.(self)
43+
) edges;
44+
45+
{ edges = graph; flipped = flip_edges graph }
46+
47+
let children edges node =
48+
let n = Array.length edges in
49+
let visited = Array.make n false in
550

51+
visited.(node) <- true;
652

53+
let rec explore i = List.iter (fun n ->
54+
if not visited.(n) then begin
55+
visited.(n) <- true;
56+
explore n
57+
end) edges.(i)
58+
in
59+
60+
explore node;
61+
62+
visited
63+
64+
let checkpoint_of graph node = { node = node; ancestors = children graph.flipped node }
65+
66+
let count_paths graph goal from =
67+
let n = Array.length graph.edges in
68+
let memo = Array.make n (-1) in
69+
70+
let rec aux i =
71+
if memo.(i) <> -1 then memo.(i)
72+
else begin
73+
let res =
74+
if i = goal.node then 1
75+
else if not goal.ancestors.(i) then 0
76+
else List.map aux graph.edges.(i) |> List.fold_left (+) 0
77+
in
78+
memo.(i) <- res;
79+
res
80+
end
81+
in
82+
aux from
83+
84+
let solve_part1 graph = count_paths graph (checkpoint_of graph out) you
85+
let solve_part2 graph =
86+
let checkpoints = Array.map (checkpoint_of graph) [|fft; dac; out|] in
87+
88+
Array.sort (fun i j -> if j.ancestors.(i.node) then -1 else 1) checkpoints;
89+
90+
Array.fold_left (fun (n, from) goal -> n * (count_paths graph goal from), goal.node) (1, svr) checkpoints |> fst
91+
92+
let day11 input =
93+
let graph = parse input in
94+
let part1 = solve_part1 graph in
95+
let part2 = solve_part2 graph in
96+
(string_of_int part1, string_of_int part2)

2025/lib/Aoc.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ let days =
5454
(8, Day08.day08);
5555
(9, Day09.day09);
5656
(* (10, Day10.day10); *)
57-
(* (11, Day11.day11); *)
57+
(11, Day11.day11);
5858
(* (12, Day12.day12); *)
5959
]
6060

0 commit comments

Comments
 (0)