day 17 yo

master
Dustin Swan 3 years ago
parent 731d7aff61
commit 5bab305b71

@ -0,0 +1,94 @@
(* Common util. Should probably put this in a module or something.. *)
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 l = String.of_seq (List.to_seq l)
let (<<) f g x = f(g(x))
let (>>) f g x = g(f(x))
let rec uniq = function (* dedups a list *)
| [] -> []
| x :: xs ->
if List.mem x xs
then uniq xs
else x :: (uniq xs)
(* --- *)
let string_of_cube (x, y, z) = Printf.sprintf "(%i, %i, %i) " x y z
let print_cube = print_string << string_of_cube
let print_cubes cubes = (List.map print_cube cubes; print_newline ())
let read_grid lines = (* string list to active cube list *)
List.mapi (fun x line ->
List.mapi (fun y cell ->
if cell = '#' then Some (x, y, 0) else None
) (explode line)
) lines
|> List.concat
|> List.filter Option.is_some
|> List.map Option.get
let neighbor_d = [-1; 0; 1]
let find_neighbors (x, y, z) = (* find all of the neighboring cubes *)
List.map (fun dx ->
List.map (fun dy ->
List.map (fun dz ->
(x + dx, y + dy, z + dz)
) neighbor_d
) neighbor_d
) neighbor_d
|> List.concat |> List.concat (* flatten *)
|> List.filter (fun (x', y', z') -> not (x = x' && y = y' && z = z')) (* remove the point itself *)
let update position cubes = (* returns true if this position should be active *)
let neighbors = find_neighbors position in
let active_neighbors = List.filter (fun x -> List.mem x cubes) neighbors in
let num_active_neighbors = List.length active_neighbors in
let active = List.mem position cubes in
let active' = num_active_neighbors = 3 || (active && num_active_neighbors = 2) in
num_active_neighbors = 3 || (active && num_active_neighbors = 2)
let cycle cubes =
let neighbors = List.map find_neighbors cubes |> List.concat in
let uniq_neighbors = uniq neighbors in
let cubes' = List.map (fun n -> (n, update n cubes)) uniq_neighbors in
(* List.filter (fun (c, active) -> active) cubes' (* only return the active ones *) *)
List.filter_map (fun (c, active) -> if active then Some c else None) cubes' (* only return the active ones *)
let rec go cubes = function (* cycle n times *)
| 0 -> cubes
| n -> go (cycle cubes) (n - 1)
let () =
let test = [
".#.";
"..#";
"###";
] in
let start = [
"...###.#";
"#.#.##..";
".##.##..";
"..##...#";
".###.##.";
".#..##..";
".....###";
".####..#";
] in
let cubes = read_grid start in
print_string "starting coordinates\n";
print_cubes cubes;
print_newline ();
let n = 6 in
let cubes' = go cubes n in
Printf.printf "after %i cycle(s)\n" n;
print_cubes cubes';
Printf.printf "count: %i\n" (List.length cubes');

@ -0,0 +1,99 @@
(* Common util. Should probably put this in a module or something.. *)
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 l = String.of_seq (List.to_seq l)
let (<<) f g x = f(g(x))
let (>>) f g x = g(f(x))
let rec uniq = function (* dedups a list *)
| [] -> []
| x :: xs ->
if List.mem x xs
then uniq xs
else x :: (uniq xs)
(* --- *)
let string_of_cube (x, y, z, w) = Printf.sprintf "(%i, %i, %i, %i) " x y z w
let print_cube = print_string << string_of_cube
let print_cubes cubes = (List.map print_cube cubes; print_newline ())
let read_grid lines = (* string list to active cube list *)
List.mapi (fun x line ->
List.mapi (fun y cell ->
if cell = '#' then Some (x, y, 0, 0) else None
) (explode line)
) lines
|> List.concat
|> List.filter Option.is_some
|> List.map Option.get
let neighbor_d = [-1; 0; 1]
(* donno how to do this nicely.. *)
let find_neighbors (x, y, z, w) = (* find all of the neighboring cubes *)
List.map (fun dx ->
List.map (fun dy ->
List.map (fun dz ->
List.map (fun dw ->
(x + dx, y + dy, z + dz, w + dw)
) neighbor_d
) neighbor_d
) neighbor_d
) neighbor_d
|> List.concat |> List.concat |> List.concat (* flatten *)
|> List.filter (fun (x', y', z', w') -> not (x = x' && y = y' && z = z' && w = w')) (* remove the point itself *)
let update position cubes = (* returns true if this position should be active *)
let neighbors = find_neighbors position in
let active_neighbors = List.filter (fun x -> List.mem x cubes) neighbors in
let num_active_neighbors = List.length active_neighbors in
let active = List.mem position cubes in
let active' = num_active_neighbors = 3 || (active && num_active_neighbors = 2) in
num_active_neighbors = 3 || (active && num_active_neighbors = 2)
let cycle cubes =
let neighbors = List.map find_neighbors cubes |> List.concat in
let uniq_neighbors = uniq neighbors in
let cubes' = List.map (fun n -> (n, update n cubes)) uniq_neighbors in
List.filter_map (fun (c, active) -> if active then Some c else None) cubes' (* only return the active ones *)
let rec go cubes n = (* cycle n times *)
Printf.printf "GO! %i\n" n;
match n with
| 0 -> cubes
| n -> go (cycle cubes) (n - 1)
let () =
let test = [
".#.";
"..#";
"###";
] in
let start = [
"...###.#";
"#.#.##..";
".##.##..";
"..##...#";
".###.##.";
".#..##..";
".....###";
".####..#";
] in
let cubes = read_grid start in
print_string "starting coordinates\n";
print_cubes cubes;
print_newline ();
let n = 6 in
let cubes' = go cubes n in
Printf.printf "after %i cycle(s)\n" n;
print_cubes cubes';
let count = List.length cubes' in
Printf.printf "count: %i\n" count;
Loading…
Cancel
Save