From b0b6df2d4067390ecb23bf703ffff6f87e21b67f Mon Sep 17 00:00:00 2001 From: rhiannon morris Date: Fri, 9 Dec 2022 12:18:58 +0100 Subject: [PATCH] day9 --- aoc.bqn | 6 ++-- aoc.m | 2 ++ basics.m | 8 +++++ day9.m | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 day9.m diff --git a/aoc.bqn b/aoc.bqn index dc877a5..70e53c5 100644 --- a/aoc.bqn +++ b/aoc.bqn @@ -55,9 +55,9 @@ Day7 ⇐ {𝕩, "mercury only"!0} Day8 ⇐ { _rots ← {Fβ€Ώx←𝔽‿𝕩, >{FβŒΎπ•x}¨⟨⊒,⍉,⌽˘,β‰βŒ½βŸ©} A ← {+Β΄β₯Š ∨˝ ∧´∘(βŠ‘>1βŠΈβ†“)Β¨ 𝕩} - B ← {⌈´β₯Š ×˝ {1βŠ‘βŽŠ(1-Λœβ‰ π•©)/ (βŠ‘β‰€βŠ’) 𝕩}Β¨ 𝕩} - (Aβ‹ˆB) Β―1βŠΈβ†“βˆ˜β†“Λ˜_rots '0'-˜ >β€’FLines 𝕩 + B ← {⌈´β₯Š ×˝ {1βŠ‘βŽŠ(1-Λœβ‰ π•©) (/⊒β‰₯βŠ‘) 𝕩}Β¨ 𝕩} + (Aβ‹ˆB) (Β―1↓↓)˘_rots '0'-˜ >β€’FLines 𝕩 } # ⟨ 1843 180000 ⟩ -# β€’Show Day8 βŠ‘β€’args +Day9 ⇐ {𝕩, "mercury only"!0} diff --git a/aoc.m b/aoc.m index 3929ee9..8a9ffdc 100644 --- a/aoc.m +++ b/aoc.m @@ -46,6 +46,7 @@ run_day(Day, Part, Lines, Out) :- :- import_module day6. :- import_module day7. :- import_module day8. +:- import_module day9. :- pred solution(int::in, sol::out(sol)) is semidet. solution(1, day1.run). @@ -56,3 +57,4 @@ solution(5, day5.run). solution(6, day6.run). solution(7, day7.run). solution(8, day8.run). +solution(9, day9.run). diff --git a/basics.m b/basics.m index 345b485..d5adbc6 100644 --- a/basics.m +++ b/basics.m @@ -6,6 +6,8 @@ :- mode part(in, out) is semidet. :- mode part(out, in) is det. +:- func part(part, T, T) = T. + :- import_module io. :- import_module list. @@ -33,6 +35,7 @@ :- import_module int. :- func sum(list(int)) = int. +:- func replicate(int, T) = list(T). :- import_module maybe. @@ -45,6 +48,9 @@ part("1", one). part("2", two). +part(one, X, _) = X. +part(two, _, Y) = Y. + :- import_module exception. @@ -71,6 +77,8 @@ read_lines_need(File, Lines, !IO) :- sum(Xs) = foldl(plus, Xs, 0). +replicate(N, X) = Out :- + if N = 0 then Out = [] else Out = [X | replicate(N - 1, X)]. to_int_may(Str) = Out :- if to_int(Str, N) then Out = yes(N) else Out = no. diff --git a/day9.m b/day9.m new file mode 100644 index 0000000..b570e9b --- /dev/null +++ b/day9.m @@ -0,0 +1,101 @@ +:- module day9. +:- interface. +:- import_module basics. +:- import_module univ. + +:- pred run(part::in, lines::in, univ::out) is cc_multi. + +:- implementation. +:- import_module int. +:- import_module string. +:- import_module list. +:- import_module set_bbbtree. + +:- type set(T) == set_bbbtree(T). + + +:- type coord ---> c(x :: int, y :: int). +:- type rope == list(coord). + +:- type direction ---> up; down; left; right. + +:- pred to_direction(string, direction). +:- mode to_direction(in, out) is semidet. +:- mode to_direction(out, in) is det. +to_direction("U", up). +to_direction("D", down). +to_direction("L", left). +to_direction("R", right). + +:- pred orth(direction::in, direction::in) is semidet. +orth(A, B) :- + ((A = up ; A = down), (B = left ; B = right)); + ((A = left ; A = right), (B = up ; B = down)). + +:- pred line(string::in, list(direction)::out) is semidet. +line(Str, replicate(N, D)) :- + words(Str) = [DD, NN], + to_direction(DD, D), + to_int(NN, N). + +:- pred move_head(direction::out, coord::in, coord::out) is multi. +move_head(up, c(X, Y), c(X, Y+1)). +move_head(down, c(X, Y), c(X, Y-1)). +move_head(left, c(X, Y), c(X-1, Y)). +move_head(right, c(X, Y), c(X+1, Y)). + +:- pred ok(coord::in, coord::in) is semidet. +ok(A, B) :- abs(A^x - B^x) =< 1, abs(A^y - B^y) =< 1. + +:- pred ok(rope::in) is semidet. +ok([]). ok([_]). +ok([A, B | Rest]) :- ok(A, B), ok([B | Rest]). + +:- pred same_rc(coord::in, coord::in) is semidet. +same_rc(A, B) :- A^x = B^x ; A^y = B^y. + +:- pred move_tail1(coord::in, coord::in, coord::out) is nondet. +move_tail1(H, !T) :- ok(H, !.T). +move_tail1(H, !T) :- + if same_rc(H, !.T) then + move_head(_, !T), + ok(H, !.T) + else + move_head(D1, !T), + move_head(D2, !T), + orth(D1, D2), + ok(H, !.T). + +:- pred move_tail(coord::in, rope::in, rope::out) is nondet. +move_tail(_, [], []). +move_tail(H, [!.T | !.Ts], [!:T | !:Ts]) :- + move_tail1(H, !T), + move_tail(!.T, !Ts). + +:- pred move(direction::in, rope::in, rope::out) is nondet. +move(_, [], []). +move(D, [!.H | !.T], [!:H | !:T]) :- + move_head(D, !H), + move_tail(!.H, !T). + + +:- type seen == set(coord). + +:- pred next(direction, rope, rope, seen, seen). +:- mode next(in, in, out, in, out) is nondet. +next(D, !Rope, !Seen) :- + move(D, !Rope), + last(!.Rope, Tail), + insert(Tail, !Seen). + +:- pred run0(part::in, lines::in, int::out) is cc_nondet. +run0(Part, Lines, Out) :- + Start = replicate(part(Part, 2, 10), c(0, 0)), + map(line, Lines, Dirs), + foldl2(next, condense(Dirs), Start, _, init, End), + count(End, Out). + +run(Part, Lines, univ(Out)) :- + disable_warning [no_solution_disjunct] ( + not run0(Part, Lines, Out) => die("bad input") + ).