From fdf0a294627532461869b1fc6e85b5e643d2190f Mon Sep 17 00:00:00 2001 From: rhiannon morris Date: Sun, 18 Dec 2022 13:48:52 +0100 Subject: [PATCH] the failures --- abandoned/aoc.bqn | 35 +++++ abandoned/day12.m | 230 ++++++++++++++++++++++++++++++ abandoned/day15.m | 334 ++++++++++++++++++++++++++++++++++++++++++++ abandoned/day16.2.m | 163 +++++++++++++++++++++ abandoned/day17.m | 95 +++++++++++++ 5 files changed, 857 insertions(+) create mode 100644 abandoned/aoc.bqn create mode 100644 abandoned/day12.m create mode 100644 abandoned/day15.m create mode 100644 abandoned/day16.2.m create mode 100644 abandoned/day17.m diff --git a/abandoned/aoc.bqn b/abandoned/aoc.bqn new file mode 100644 index 0000000..d27ac16 --- /dev/null +++ b/abandoned/aoc.bqn @@ -0,0 +1,35 @@ +# no +# Day11 ⇐ { +# input ← >{·‿s‿o‿p‿t‿f: +# ⟨⥊•BQN '‿'⍟(','⊸=)¨ 18↓s +# •BQN∘(«23↓o)⎊⊢ ('+'=⊑23↓o)◶×‿+ ⊢ +# •BQN 21↓p, •BQN 29↓t, •BQN 30↓f⟩ +# }∘(6⊸↑)¨ 7 Chunk •FLines 𝕩 +# start ← >⋈⟜0¨⊏˘input ⋄ info ← 1↓˘input ⋄ mod ← ×´1⊑˘info +# Go ← {n‿d𝕊𝕩: +# Turn ← {i𝕊m: +# x‿n ← i⊏m ⋄ O‿p‿t‿f ← i⊏info +# y ← (0⊸=p⊸|)⊸⊔ mod| ⌊d÷˜ O x +# l‿r ← ⊑⎊⟨⟩⟜y¨↕2 +# (∾⟜l)⌾(f‿0⊸⊑) (∾⟜r)⌾(t‿0⊸⊑) ⟨⟨⟩,n+≠x⟩⌾(i⊸⊏) m +# } +# Round ← {𝕩 Turn´ ⌽↕≠𝕩} +# ×´2↑∨1⊏˘ Round⍟n 𝕩 +# } +# 20‿3 Go start +# # ⟨10⋆5,1⟩ Go start +# } + +Day12 ⇐ { + map ← >•FLines 𝕩 + # start‿end ← {⊑(𝕩⊸= /○⥊ ↕∘≢)map}¨ "SE" + start‿end ← "SE"⊐˜⥊map + map {'S':0; 'E':25; 𝕩-'a'}¨↩ + i_h ← ⥊ (↕∘≢∾¨⊢) map + Adj ← {∞⍟¬ (1=+´2↑r)∧∧´1≥(r←|𝕨-𝕩)} + a ← Adj⌜˜ i_h + a {0⍟(=´𝕩)𝕨}¨⟜(↕≢)↩ + a +} +•Show Day12 ⊑•args + diff --git a/abandoned/day12.m b/abandoned/day12.m new file mode 100644 index 0000000..dc3728b --- /dev/null +++ b/abandoned/day12.m @@ -0,0 +1,230 @@ +:- module day12. +:- interface. +:- import_module basics. + +:- pred run(part::in, lines::in, answer::out) is cc_multi. + +:- implementation. +:- import_module int. +:- import_module char. +:- import_module string. +:- import_module list. +:- import_module array2d. + +:- type point == {int, int}. + +:- type grid ---> g(array :: array2d(char), start :: point, end :: point). + +:- pred grid(lines::in, grid::out) is semidet. +grid(Lines, g(Arr, {SX, SY}, {EX, EY})) :- + Arr = from_lists(map(to_char_list, Lines)), + find(Arr, 'S', SX, SY), + find(Arr, 'E', EX, EY). + +:- pred find_from(array2d(T)::in, T::in, int::in, int::in, int::out, int::out) + is semidet. +find_from(Arr, A, X1, Y1, X2, Y2) :- + bounds(Arr, W, H), + Y1 < H, + (if X1 < W then + B = Arr^elem(X1, Y1), + (if A = B then X2 = X1, Y2 = Y1 + else find_from(Arr, A, X1+1, Y1, X2, Y2)) + else + find_from(Arr, A, 0, Y1+1, X2, Y2)). + +:- pred find(array2d(T)::in, T::in, int::out, int::out) is semidet. +find(Arr, A, X, Y) :- find_from(Arr, A, 0, 0, X, Y). + +:- func get(grid, point) = char. +get(G, {X, Y}) = G^array^elem(X, Y). + +:- func height(char) = int. +height(C) = I :- + if C = 'S' then I = 0 + else if C = 'E' then I = 25 + else I = to_int(C) - to_int('a'). + +:- func height(grid, point) = int. +height(G, P) = height(get(G, P)). + +:- pred adj_point(point::in, point::out) is multi. +adj_point({X, Y}, {X+1, Y}). +adj_point({X, Y}, {X-1, Y}). +adj_point({X, Y}, {X, Y+1}). +adj_point({X, Y}, {X, Y-1}). + +:- pred adj(grid::in, point::in, point::out) is nondet. +adj(G, P, Q) :- + adj_point(P, Q), in_bounds(G, Q), + abs(height(G, P) - height(G, Q)) =< 1. + +:- pred in_bounds(grid::in, point::in) is semidet. +in_bounds(G, {X, Y}) :- + bounds(G^array, W, H), + 0 =< X, X < W, + 0 =< Y, Y < H. + +:- pred index(grid::in, point::out) is nondet. +index(G, {I, J}) :- + bounds(G^array, W, H), + nondet_int_in_range(0, W-1, I), + nondet_int_in_range(0, H-1, J). + + +:- type path == list(point). + +:- type distance ---> i(int); inf. + +:- import_module solutions. + +:- import_module map. +:- type pm == map(point, point). + +:- type nq ---> nq(pq, dm). +:- type dm == map(point, distance). +:- type pq == list({point, distance}). + +:- pred remove_min(point::out, distance::out, pq::in, pq::out) is semidet. +remove_min(X, D, [{X0, D0} | PQ0], PQ) :- + if + remove_min(X1, D1, PQ0, PQ1), + D1 @< D0 + then + X = X1, D = D1, + PQ = [{X0, D0} | PQ1] + else + X = X0, D = D0, + PQ = PQ0. + +:- pred seen(nq::in, point::in) is semidet. +seen(nq(_, S), X) :- contains(S, X). + +:- pred next(point::out, distance::out, nq::in, nq::out) is semidet. +next(X, D, nq(!.Q, !.S), nq(!:Q, !:S)) :- + remove_min(X, D, !Q), set(X, D, !S). + +:- pred set_distance_pq(point::in, distance::in, pq::in, pq::out) is det. +set_distance_pq(_, _, [], []). +set_distance_pq(X, D, [{Y, E} | Xs], Zs) :- + if X = Y then + Zs = [{X, D} | Xs] + else + set_distance_pq(X, D, Xs, Xs2), + Zs = [{Y, E} | Xs2]. + +:- pred set_distance(point::in, distance::in, nq::in, nq::out) is det. +set_distance(X, D, nq(!.Q, !.S), nq(!:Q, !:S)) :- + set_distance_pq(X, D, !Q), + (if contains(!.S, X) then det_update(X, D, !S) else true). + +:- func get_distance(point, pq, dm) = distance. +:- mode get_distance(in, in, in) = out is semidet. +get_distance(X, [], S) = search(S, X). +get_distance(X, [{Y, D} | Xs], S) = D1 :- + if X = Y then D1 = D else D1 = get_distance(X, Xs, S). + +:- func get_distance(point, nq) = distance. +:- mode get_distance(in, in) = out is semidet. +get_distance(X, nq(Q, S)) = get_distance(X, Q, S). + + +:- pred insert_init(point::in, point::in, pq::in, pq::out) is det. +insert_init(From, X, !Queue) :- + (if X = From then D = i(0) else D = inf), + cons({X, D}, !Queue). + +:- pred init_queue(grid::in, point::in, nq::out) is det. +init_queue(G, From, nq(Q, init)) :- + aggregate(index(G), insert_init(From), [], Q). + + +:- pred get_path_rev(pm::in, point::in, point::in, path::out) is det. +get_path_rev(Map, From, To, Path) :- + if From = To then + Path = [] + else if search(Map, To, Prev) then + get_path_rev(Map, From, Prev, Tail), + Path = [To | Tail] + else + To = {X, Y}, + die("no predecessor for {%d, %d}", [i(X), i(Y)]). + +:- pred get_path(pm::in, point::in, point::in, path::out) is det. +get_path(Map, From, To, reverse(Path)) :- get_path_rev(Map, From, To, Path). + +:- func incr(distance) = distance. +incr(inf) = inf. +incr(i(N)) = i(N + 1). + +:- pred neighbours(grid::in, point::in, nq::in, point::out) is nondet. +neighbours(G, Point, Queue, N) :- + adj(G, Point, N), + not seen(Queue, N). + +:- pred path(grid::in, point::in, point::in, path::out, + nq::in, nq::out, pm::in, pm::out) is semidet. +path(G, From, To, Path, !Queue, !Prev) :- + next(Point, Distance, !Queue), + Distance = inf => die("ow"), + Neighs = solutions(neighbours(G, Point, !.Queue)), + foldl2(pred(Neigh::in, % 🐴 + !.Queue::in, !:Queue::out, + !.Prev::in, !:Prev::out) is det :- ( + Alt = incr(Distance), + (if Alt @< get_distance(Neigh, !.Queue) then + set_distance(Neigh, Alt, !Queue), + set(Neigh, Point, !Prev) + else true)), + Neighs, !Queue, !Prev), + (if Point = To then + get_path(!.Prev, From, To, Path) + else + path(G, From, To, Path, !Queue, !Prev)). + +:- pred path(grid::in, point::in, point::in, path::out) is semidet. +path(G, From, To, Path) :- + init_queue(G, From, Queue), + path(G, From, To, Path, Queue, _, init, _). + +:- pred path(grid::in, path::out) is semidet. +path(G, Path) :- path(G, G^start, G^end, Path). + + +run(_, Lines, Out) :- + if + grid(Lines, G), + init_queue(G, G^start, Q), + path(G, G^start, G^end, Path, Q, nq(Q1, S1), init, Prev) + then + Out = 'new other'({"RESULT", length(Path):int, + "G", G, "Path", Path, + "Q1", Q1, + "S1", to_assoc_list(S1):list(_), + "Prev", to_assoc_list(Prev):list(_)}) + else + die("bad input"). + +/* omg could u imagine if this had worked tho + +:- pragma memo(path/5, [fast_loose]). +:- pred path(grid::in, point::in, point::in, path::in, int::out) + is nondet. +path(G, P, P, _, 0). +path(G, P, Q, Seen, Len + 1) :- + adj(G, P, P1), + not member(P1, Seen), + path(G, P1, Q, [P|Seen], Len). + +:- pred path(grid::in, point::in, point::in, int::out) is nondet. +path(G, P, Q, Len) :- path(G, P, Q, [], Len). + +:- import_module solutions. + +run(_, Lines, Out) :- + if grid(Lines, G) then + solutions(path(G, G^start, G^end), Paths), + Out = int(det_head(Paths)) + else + die("bad input"). +*/ diff --git a/abandoned/day15.m b/abandoned/day15.m new file mode 100644 index 0000000..ef69146 --- /dev/null +++ b/abandoned/day15.m @@ -0,0 +1,334 @@ +:- module day15. +:- interface. +:- import_module basics. + +:- pred run(part::in, lines::in, answer::out) is cc_multi. + +:- implementation. +:- import_module int. +:- import_module string. +:- import_module list. +:- import_module maybe. +:- import_module array2d. +:- import_module array. + +:- import_module set_bbbtree. +:- type set(T) == set_bbbtree(T). + + +:- type cell ---> unknown; empty; sensor; beacon. + +:- type data == array2d(cell). + +:- type grid ---> + g(start_x :: int, end_x :: int, + start_y :: int, end_y :: int, + data :: data). + +:- inst grid for grid/0 ---> g(ground, ground, ground, ground, array2d). +:- mode grid_di == di(grid). +:- mode grid_uo == out(grid). + +:- type point == {int, int}. + +:- type sensor ---> s(self :: point, beacon :: point). + + +:- import_module parsing_utils. + +:- pred line(src::in, sensor::out, ps::in, ps::out) is semidet. +line(Src, s(S, B)) --> + kws(["sensor", "at"], Src), point(Src, S), punct(":", Src, _), + kws(["closest", "beacon", "is", "at"], Src), point(Src, B), eof(Src, _). + +:- pred point(src::in, point::out, ps::in, ps::out) is semidet. +point(Src, {X, Y}) --> + kw("x", Src), punct("=", Src, _), int_literal(Src, X), punct(",", Src, _), + kw("y", Src), punct("=", Src, _), int_literal(Src, Y). + +:- pred kw(string::in, src::in, ps::in, ps::out) is semidet. +kw(K, Src) --> ikeyword("abcdefghijklmnopqrsuvwxyz", K, Src, _). + +:- pred kws(list(string)::in, src::in, ps::in, ps::out) is semidet. +kws([], _) --> []. +kws([K | Ks], Src) --> kw(K, Src), kws(Ks, Src). + +:- pred lines(lines::in, list(sensor)::out) is cc_multi. +lines(Lines, Sensors) :- map_index(line, Lines, Sensors). + +:- pred line(int::in, string::in, sensor::out) is cc_multi. +line(Line, Str, Out) :- + parse(Str, line, Result), + from_result(Line, Result, Out). + +from_result(_, ok(X), X). +from_result(Line, error(yes(Msg), _, Col), _) :- + die("%d:%d: %s", [i(Line), i(Col), s(Msg)]). +from_result(Line, error(no, _, Col), _) :- + die("%d:%d: unknown error lol", [i(Line), i(Col)]). + + +:- func distance(point, point) = int. +distance({X1, Y1}, {X2, Y2}) = abs(X1 - X2) + abs(Y1 - Y2). + +:- func point + int = point. +{X, Y} + D = {X+D, Y+D}. + +:- func point - int = point. +{X, Y} - D = {X-D, Y-D}. + + +:- pred in_bounds(grid::in, point::in) is semidet. +in_bounds(G, {X, Y}) :- + G^start_x =< X, X =< G^end_x, + G^start_y =< Y, Y =< G^end_y. + +:- func get(grid, point) = cell. +get(G, {X, Y}) = G^data^elem(Y - G^start_y, X - G^start_x). + +:- pred set_d(point::in, point::in, cell::in, + data::array2d_di, data::array2d_uo) is det. +set_d({StartX, StartY}, {X, Y}, A, !Data) :- + !Data^elem(Y - StartY, X - StartX) := A. + +:- pred set(point::in, cell::in, grid::grid_di, grid::grid_uo) is det. +set(XY, A, !Grid) :- some [!Data] ( + !:Data = !.Grid^data, + set_d({!.Grid^start_x, !.Grid^start_y}, XY, A, !Data), + !Grid^data := !.Data +). + + +:- type bounds ---> b(min :: point, max :: point). + +:- func bounds(list(sensor)) = bounds. +bounds(Sensors) = + foldl(expand_bounds, points_all(Sensors), b({0, 0}, {0, 0})). + +:- func points_all(list(sensor)) = list(point). +points_all(Sensors) = + foldr(func(S, Rest) = points(S) ++ Rest, Sensors, []). + +:- func points(sensor) = list(point). +points(s(S, B)) = [S - D, S + D, S, B] :- + D = distance(S, B). + +:- func expand_bounds(point, bounds) = bounds. +expand_bounds({X, Y}, b({LoX, LoY}, {HiX, HiY})) = + b({LoX `min` X, LoY `min` Y}, {HiX `max` X, HiY `max` Y}). + + +:- pred place_sensors( + point::in, list(sensor)::in, data::array2d_di, data::array2d_uo) is det. +place_sensors(_, [], !Data). +place_sensors(Start, [s(S, B) | Rest], !Data) :- + set_d(Start, S, sensor, !Data), + set_d(Start, B, beacon, !Data), + place_sensors(Start, Rest, !Data). + +:- func grid_from_sensors(list(sensor)::in) = (grid::grid_uo) is det. +grid_from_sensors(Sensors) = !:G :- + b({StartX, StartY}, {EndX, EndY}) = bounds(Sensors), + Width = EndX - StartX + 1, Height = EndY - StartY + 1, + place_sensors({StartX, StartY}, Sensors, + init(Height, Width, unknown), Arr), + !:G = g(StartX, EndX, StartY, EndY, Arr), + set_empty_all(Sensors, !G). + +:- pred make_grid(lines::in, grid::grid_uo) is cc_multi. +make_grid(Lines, grid_from_sensors(Sensors)) :- + lines(Lines, Sensors). + + +:- pred set_empty_all(list(sensor)::in, grid::grid_di, grid::grid_uo) is det. +set_empty_all([], !G). +set_empty_all([S | Ss], !G) :- + set_empty(S, !G), set_empty_all(Ss, !G). + +:- pred set_empty(sensor::in, grid::grid_di, grid::grid_uo) is det. +set_empty(s(S, B), !G) :- + D = distance(S, B) + 1, + up(S, D, !G), down(S, D, !G). + +:- func up(point) = point. +up({X, Y}) = {X, Y-1}. + +:- func down(point) = point. +down({X, Y}) = {X, Y+1}. + +:- func left(point) = point. +left({X, Y}) = {X-1, Y}. + +:- func right(point) = point. +right({X, Y}) = {X+1, Y}. + +:- pred go_v((func(point) = point)::(func(in) = out is det), + point::in, int::in, grid::grid_di, grid::grid_uo) is det. +go_v(F, XY, D, !G) :- + if D = 0 ; not in_bounds(!.G, XY) then true else + set_unknown(XY, empty, !G), + go_v(F, F(XY), D-1, !G), + left(left(XY), D-1, !G), + right(right(XY), D-1, !G). + +:- pred go_h((func(point) = point)::(func(in) = out is det), + point::in, int::in, grid::grid_di, grid::grid_uo) is det. +go_h(F, XY, D, !G) :- + if D = 0 ; not in_bounds(!.G, XY) then true else + set_unknown(XY, empty, !G), + go_h(F, F(XY), D-1, !G). + +:- pred set_unknown(point::in, cell::in, grid::grid_di, grid::grid_uo) is det. +set_unknown(XY, C, !G) :- + if get(!.G, XY) = unknown then set(XY, C, !G) else true. + +:- pred up(point::in, int::in, grid::grid_di, grid::grid_uo) is det. +up(XY, D, !G) :- go_v(up, XY, D, !G). + +:- pred down(point::in, int::in, grid::grid_di, grid::grid_uo) is det. +down(XY, D, !G) :- go_v(down, XY, D, !G). + +:- pred left(point::in, int::in, grid::grid_di, grid::grid_uo) is det. +left(XY, D, !G) :- go_h(left, XY, D, !G). + +:- pred right(point::in, int::in, grid::grid_di, grid::grid_uo) is det. +right(XY, D, !G) :- go_h(right, XY, D, !G). + + +:- func draw(grid) = lines. +draw(G) = map(func(L) = from_char_list(map(to_char, L)), lists(G^data)). + +to_char(unknown) = '·'. +to_char(empty) = ' '. +to_char(sensor) = '⏿'. +to_char(beacon) = '⌑'. + + +:- func row(int::in, grid::in) = (array(cell)::array_uo). +row(J, G) = Arr :- + Size = G^end_x - G^start_x + 1, + Arr = generate(Size, func(I) = get(G, {I + G^start_x, J})). + +:- func count(pred(T)::(pred(in) is semidet), array(T)::in) = (int::out). +count(P, Arr) = + foldl(func(X, Acc) = ite((pred) is semidet :- P(X), 1+Acc, Acc), Arr, 0). + +:- pred maybe_beacon(cell::in) is semidet. +maybe_beacon(beacon). +maybe_beacon(unknown). + + +/* +:- func expand(list(list(point))) = set(point). +expand(Points) = from_list(condense(map(expand1, Points))). + +:- func expand1(list(point)) = list(point). +expand1([]) = []. +expand1([P]) = [P]. +expand1([P, Q | Rest]) = expand(P, Q) ++ expand1([Q | Rest]). + +:- func expand(point, point) = list(point). +expand({X1, Y1}, {X2, Y2}) = List :- + if X1 = X2 then List = map(func(Y) = {X1, Y}, between(Y1, Y2)) + else if Y1 = Y2 then List = map(func(X) = {X, Y1}, between(X1, X2)) + else die("expand/2: non-orthogonal line"). + +:- func between(int, int) = list(int). +between(I, J) = to_sorted_list(range(min(I, J), max(I, J))). + + +:- func bounds(set(point)) = {point, point}. +bounds(Points) = {{LoX, LoY}, {HiX, HiY}} :- + Points0 = insert(Points, hole), + Xs = to_sorted_list(map(func({X, _}) = X, Points0)), + Ys = to_sorted_list(map(func({_, Y}) = Y, Points0)), + LoX = det_head(Xs), det_last(Xs, HiX), + LoY = det_head(Ys), det_last(Ys, HiY). + + +:- func add_floor(set(point)) = set(point). +add_floor(Points) = insert_list(Points, Floor) :- + {_, {_, Lo}} = bounds(Points), + FloorY = Lo + 2, Start = holeX - FloorY, End = holeX + FloorY, + Floor = map(func(X) = {X, FloorY}, between(Start, End)). + + +:- func get(grid, point) = cell. +get(G, {X, Y}) = G^data^elem(Y - G^start_y, X - G^start_x). + +:- pred set_d(point::in, point::in, cell::in, + data::array2d_di, data::array2d_uo) is det. +set_d({StartX, StartY}, {X, Y}, A, !Data) :- + !Data^elem(Y - StartY, X - StartX) := A. + +:- pred set(point::in, cell::in, grid::grid_di, grid::grid_uo) is det. +set(XY, A, !Grid) :- some [!Data] ( + !:Data = !.Grid^data, + set_d({!.Grid^start_x, !.Grid^start_y}, XY, A, !Data), + !Grid^data := !.Data +). + +:- pred in_bounds(grid::in, point::in) is semidet. +in_bounds(G, {X, Y}) :- + G^start_x =< X, X =< G^end_x, + G^start_y =< Y, Y =< G^end_y. + +:- pred place_rocks(point::in, list(point)::in, + data::array2d_di, data::array2d_uo) is det. +place_rocks(_, [], !Data). +place_rocks(Start, [XY | Rest], !Data) :- + set_d(Start, XY, rock, !Data), + place_rocks(Start, Rest, !Data). + +:- func grid_from_set(set(point)) = grid. +:- mode grid_from_set(in) = grid_uo. +grid_from_set(Points) = G :- + {{StartX, StartY}, {EndX, EndY}} = bounds(Points), + Width = EndX - StartX + 1, Height = EndY - StartY + 1, + place_rocks({StartX, StartY}, to_sorted_list(Points), + init(Height, Width, empty), Arr), + G = g(StartX, EndX, StartY, EndY, Arr). + +:- func make_grid(lines) = grid. +:- mode make_grid(in) = grid_uo is semidet. +make_grid(Lines) = grid_from_set(expand(Points)) :- + lines(Lines, Points). + +:- func make_floor_grid(lines) = grid. +:- mode make_floor_grid(in) = grid_uo is semidet. +make_floor_grid(Lines) = grid_from_set(add_floor(expand(Points))) :- + lines(Lines, Points). + + +:- type fall ---> stop(point); overflow. + +:- pred move(point::in, fall::out, grid::grid_di, grid::grid_uo) is semidet. +move({X, Y}, B, !Grid) :- + if not in_bounds(!.Grid, {X, Y}) then B = overflow + else if get(!.Grid, {X, Y}) \= empty then fail + else if move({X, Y+1}, B0, !Grid) then B = B0 + else if move({X-1, Y+1}, B0, !Grid) then B = B0 + else if move({X+1, Y+1}, B0, !Grid) then B = B0 + else set({X, Y}, sand, !Grid), B = stop({X, Y}). + +:- pred fill(int::out, grid::grid_di, grid::grid_uo) is det. +fill(N, !Grid) :- + if move(hole, stop(_), !Grid) then fill(N0, !Grid), N = N0 + 1 + else N = 0. + +:- pragma no_determinism_warning(run/3). +run(one, Lines, int(Res)) :- + if Grid = make_grid(Lines) then fill(Res, Grid, _) + else die("bad input"). +run(two, Lines, int(Res)) :- + if Grid = make_floor_grid(Lines) then fill(Res, Grid, _) + else die("bad input"). +*/ + +:- import_module std_util. + +run(_, Lines, Out) :- + make_grid(Lines, Grid), + Out = lines(draw(Grid) ++ + [string([Grid^start_x, Grid^start_y, Grid^end_x, Grid^end_y]), + string(count(isnt(maybe_beacon), row(2_000_000, Grid)))]). diff --git a/abandoned/day16.2.m b/abandoned/day16.2.m new file mode 100644 index 0000000..5b08de4 --- /dev/null +++ b/abandoned/day16.2.m @@ -0,0 +1,163 @@ +:- module day16. +:- interface. +:- import_module basics. + +:- pred run(part::in, lines::in, answer::out) is cc_multi. + +:- implementation. +:- import_module int. +:- import_module char. +:- import_module string. +:- import_module list. +:- import_module map. +:- import_module digraph. +:- import_module set. + +:- type label == string. +:- type key == digraph_key(label). +:- type rates == map(key, int). +:- type graph == digraph(label). +:- type open == set(key). + + +:- pred spaces(chars::in, chars::out) is det. +spaces --> if [' '] then spaces else []. + +:- pred word0(chars::out, chars::in, chars::out) is semidet. +word0([C | Cs]) --> + [C], {is_alpha(C)}, + (if word0(Cs0) then {Cs = Cs0} else {Cs = []}). + +:- pred word(string::out, chars::in, chars::out) is semidet. +word(W) --> word0(Cs), {W = from_char_list(Cs)}, spaces. + +:- pred words(list(string)::in, chars::in, chars::out) is semidet. +words([]) --> []. +words([W | Ws]) --> word(W), words(Ws). + +:- pred sym(char::in, chars::in, chars::out) is semidet. +sym(S) --> [S], spaces. + +:- pred tunnels(list(string)::out, chars::in, chars::out) is semidet. +tunnels([T | Ts]) --> + word(T), (if sym(',') then tunnels(Ts) else {Ts = []}). + +:- pred number(int::out, chars::in, chars::out) is semidet. +number(N) --> digits(S), {to_int(from_char_list(S), N)}. + +:- pred digits(chars::out, chars::in, chars::out) is semidet. +digits([C | Cs]) --> + [C], {is_digit(C)}, + (if digits(Cs2) then {Cs = Cs2} else {Cs = []}). + +:- pred line(graph::in, graph::out, rates::in, rates::out, + chars::in, chars::out) is nondet. +line(!Graph, !Rates) --> + word("Valve"), word(Label), + words(["has", "flow", "rate"]), sym('='), + number(Rate), sym(';'), + (words(["tunnels", "lead", "to", "valves"]) ; + words(["tunnel", "leads", "to", "valve"])), + tunnels(Tunnels), + {add_vertex(Label, Key, !Graph)}, + {insert(Key, Rate, !Rates)}, + {foldl(add_vertices_and_edge(Label), Tunnels, !Graph)}. + +:- pred line(string::in, graph::in, graph::out, rates::in, rates::out) + is nondet. +line(Str, !G, !R) :- line(!G, !R, to_char_list(Str), []). + +:- pred lines(lines::in, graph::out, rates::out) is cc_nondet. +lines(Lines, G, R) :- foldl2(line, Lines, digraph.init, G, map.init, R). + + +:- pred max_release(int::in, label::in, graph::in, rates::in, int::out) is det. +max_release(Time, Start, Graph, Rates, Max) :- + max_release(Time, lookup_key(Graph, Start), Graph, Rates, init, _, Max). + +:- pred max_release(int, key, graph, rates, open, open, int). +:- mode max_release(in, in, in, in, in, out, out) is det. +:- pragma memo(max_release/7, + [specified([value, value, addr, addr, value, output, output])]). +max_release(Time, Here, Graph, Rates, !Open, Max) :- + if Time = 0 then Max = 0 else + HereRate = lookup(Rates, Here), + StartOpen = !.Open, + (if + HereRate \= 0, + insert_new(Here, !Open) + then + max_release(Time - 1, Here, Graph, Rates, !Open, Max0), + MaxHere = Max0 + HereRate * (Time - 1) + else + MaxHere = 0), + Nexts = [Here | set.to_sorted_list(lookup_from(Graph, Here))], + max_releases(Time - 1, Nexts, Graph, Rates, StartOpen, Outs), + get_max([o(!.Open, MaxHere) | Outs], o(!:Open, Max)). + +:- type out ---> o(open :: open, max :: int). + +:- pred max_releases(int, list(key), graph, rates, open, list(out)). +:- mode max_releases(in, in, in, in, in, out) is det. +max_releases(_, [], _, _, _, []). +max_releases(Time, [Here|Theres], Graph, Rates, Open0, [o(Open, Max) | Rest]) :- + max_release(Time, Here, Graph, Rates, Open0, Open, Max) & + max_releases(Time, Theres, Graph, Rates, Open0, Rest). + + +:- import_module bool. + +:- func tick(bool, int) = int. +tick(yes, N) = N - 1. +tick(no, N) = N. + + +:- pred max_release2(int::in, label::in, graph::in, rates::in, int::out) is det. +max_release2(Time, Start, Graph, Rates, Max) :- + die("this works on the example but it's too inefficient for the real thing"), + Key = lookup_key(Graph, Start), + max_release2(Time, no, Key, Key, Graph, Rates, init, _, Max). + +:- pred max_release2(int, bool, key, key, graph, rates, open, open, int). +:- mode max_release2(in, in, in, in, in, in, in, out, out) is det. +:- pragma memo(max_release2/9, + [specified([value, value, value, value, addr, addr, + value, output, output])]). +max_release2(Time, Tick, Here1, Here2, Graph, Rates, !Open, Max) :- + if Time = 0 then Max = 0 else + HereRate = lookup(Rates, Here1), + StartOpen = !.Open, + (if + HereRate \= 0, + insert_new(Here1, !Open) + then + max_release2(tick(Tick, Time), not(Tick), Here2, Here1, + Graph, Rates, !Open, Max0), + MaxHere = Max0 + HereRate * (Time - 1) + else + MaxHere = 0), + Nexts = [Here1 | set.to_sorted_list(lookup_from(Graph, Here1))], + max_releases2(tick(Tick, Time), not(Tick), Nexts, Here2, + Graph, Rates, StartOpen, Outs), + get_max([o(!.Open, MaxHere) | Outs], o(!:Open, Max)). + +:- pred max_releases2(int, bool, list(key), key, graph, rates, open, list(out)). +:- mode max_releases2(in, in, in, in, in, in, in, out) is det. +max_releases2(_, _, [], _, _, _, _, []). +max_releases2(Time, Tick, [Here1|Theres], Here2, Graph, Rates, Open0, + [o(Open, Max) | Rest]) :- + max_release2(Time, Tick, Here2, Here1, Graph, Rates, Open0, Open, Max) & + max_releases2(Time, Tick, Theres, Here2, Graph, Rates, Open0, Rest). + + +:- pred get_max(list(out)::in(non_empty_list), out::out) is det. +get_max([O], O). +get_max([O, R | Rest], O0) :- + get_max([R | Rest], OR), + (if O^max >= OR^max then O0 = O else O0 = OR). + +run(Part, Lines, int(Max)) :- + if lines(Lines, G, R) then + (if Part = one then max_release(30, "AA", G, R, Max) + else max_release2(26, "AA", G, R, Max)) + else die("bad input"). diff --git a/abandoned/day17.m b/abandoned/day17.m new file mode 100644 index 0000000..47f2ce3 --- /dev/null +++ b/abandoned/day17.m @@ -0,0 +1,95 @@ +:- module day17. +:- interface. +:- import_module basics. + +:- pred run(part::in, lines::in, answer::out) is cc_multi. + +:- implementation. +:- import_module char. +:- import_module int. +:- import_module string. +:- import_module list. +:- import_module array. + +:- type wind ---> l; r. +:- type cell ---> empty; full. + +:- type row == list(cell). +:- type board == list(row). + +:- pred empty(row::in) is semidet. +empty(Row) :- all [X] member(X, Row) => X = empty. + +:- func empty = row. +empty = replicate(7, empty). + +:- func trim_top0(board) = board. +trim_top0([]) = []. +trim_top0([R | Rs]) = Out :- + if empty(R) then Out = trim_top0(Rs) + else Out = [R | Rs]. + +:- func trim_top(board) = board. +trim_top(B) = [empty, empty, empty | trim_top0(B)]. + + +:- type piece == list(row). + +:- func make_piece(list(string)) = piece. +make_piece(Strs) = Piece :- + if map(row, Strs, Rows) then Piece = Rows + else die("piece: invalid input"). + +:- func pieces = array(piece). +pieces = array(['🬋🬋', '🬫🬃', '🬭▌', '▌', '🬹']). + +'🬋🬋' = make_piece(["..####."]). +'🬫🬃' = make_piece(["...#...", "..###..", "...#..."]). +'🬭▌' = make_piece(["....#..", "....#..", "..###.."]). +'▌' = make_piece(["..#....", "..#....", "..#....", "..#...."]). +'🬹' = make_piece(["..##...", "..##..."]). + +:- func piece(int) = piece. +piece(I) = pieces^elem(I `mod` 5). + + +:- pred left_row(row::in, row::out) is semidet. +left_row([], []). +left_row([empty | Rest], Rest ++ [empty]). + +:- pred left_piece(piece::in, piece::out) is semidet. +left_piece(P, Q) :- map(left_row, P, Q). + +:- pred right_row(row::in, row::out) is semidet. +right_row(P, Q) :- + if P = [] then Q = [] + else remove_suffix(P, [empty], P0), Q = [empty | P0]. + +:- pred right_piece(piece::in, piece::out) is semidet. +right_piece(P, Q) :- map(right_row, P, Q). + +:- func row_to_string(row) = string. +row_to_string(Row) = + from_char_list(map(func(X) = ite(unify(X, empty), '·', '█'), Row)). + +:- func piece_to_lines(piece) = lines. +piece_to_lines(P) = map(row_to_string, P). + + +:- pred cell(char::in, cell::out) is semidet. +cell('.', empty). +cell('#', full). + +:- pred row(string::in, row::out) is semidet. +row(Str, Out) :- + length(Str) = 7, + map(cell, to_char_list(Str), Out). + +:- pred parse(lines::in, array(wind)::out) is det. +parse(Lines, array(List)) :- + List = map(func(C) = ite(unify(C, '<'), l, r), + condense(map(to_char_list, Lines))). + + +run(_, _, Out) :- + Out = lines(condense(map(piece_to_lines, map(piece, [1,3,1,2])))).