the failures
This commit is contained in:
parent
7b7ac2663f
commit
fdf0a29462
5 changed files with 857 additions and 0 deletions
35
abandoned/aoc.bqn
Normal file
35
abandoned/aoc.bqn
Normal file
|
@ -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
|
||||
|
230
abandoned/day12.m
Normal file
230
abandoned/day12.m
Normal file
|
@ -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").
|
||||
*/
|
334
abandoned/day15.m
Normal file
334
abandoned/day15.m
Normal file
|
@ -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)))]).
|
163
abandoned/day16.2.m
Normal file
163
abandoned/day16.2.m
Normal file
|
@ -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").
|
95
abandoned/day17.m
Normal file
95
abandoned/day17.m
Normal file
|
@ -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])))).
|
Loading…
Add table
Reference in a new issue