aoc2022/abandoned/day17.m
2022-12-18 13:48:52 +01:00

95 lines
2.4 KiB
Mathematica

:- 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])))).