48 lines
1.5 KiB
Perl
48 lines
1.5 KiB
Perl
|
:- use_module(library(pio)).
|
||
|
:- use_module(library(dcg/basics)).
|
||
|
:- initialization(main, main).
|
||
|
|
||
|
main([FileName|_]) :-
|
||
|
input(FileName, Map, Starting),
|
||
|
nsteps(Map, 64, [Starting], Ends), length(Ends, Answer),
|
||
|
write(Answer), nl.
|
||
|
|
||
|
nsteps(Map, N, Starts, Reachables) :-
|
||
|
length(Range, N),
|
||
|
foldl({Map}/[_, SIn, SOut]>>(step(Map, SIn, SOut)), Range, Starts, Reachables).
|
||
|
|
||
|
step(Map, CurrentCells, NextCells) :-
|
||
|
maplist(neighbors(Map), CurrentCells, NeighborsOfCells),
|
||
|
foldl(
|
||
|
[Neighbors, SetIn, SetOut]>>(
|
||
|
list_to_ord_set(Neighbors, NeighborsSet),
|
||
|
ord_union(SetIn, NeighborsSet, SetOut)),
|
||
|
NeighborsOfCells, [], NextCells).
|
||
|
|
||
|
neighbors(Map, X-Y, Neighbors) :-
|
||
|
findall(X1-Y1, neighbor(Map, X-Y, X1-Y1), Neighbors).
|
||
|
|
||
|
neighbor(Map, X-Y, X1-Y1) :-
|
||
|
( X1 is X, Y1 is Y+1; X1 is X, Y1 is Y-1;
|
||
|
X1 is X+1, Y1 is Y; X1 is X-1, Y1 is Y ),
|
||
|
nth0(X1, Map, Row), nth0(Y1, Row, '.').
|
||
|
|
||
|
replace(I, List, E, NewList) :- nth0(I, List, _, R), nth0(I, NewList, E, R).
|
||
|
|
||
|
% input parsing stuff below
|
||
|
input(FileName, Map, StartX-StartY) :-
|
||
|
phrase_from_file(lines(MapS), FileName),
|
||
|
nth0(StartX, MapS, Row), nth0(StartY, Row, s),
|
||
|
select(s, Row, '.', NewRow), replace(StartX, MapS, NewRow, Map).
|
||
|
|
||
|
lines([]) --> eos, !.
|
||
|
lines([Line|Lines]) --> line(Line), lines(Lines).
|
||
|
|
||
|
line([]) --> "\n"; eos.
|
||
|
line([s|Chars]) --> "S", line(Chars).
|
||
|
line(['.'|Chars]) --> ".", line(Chars).
|
||
|
line(['#'|Chars]) --> "#", line(Chars).
|
||
|
|
||
|
% Debug stuff
|
||
|
print(Map) :- maplist([X]>>(atomics_to_string(X, XStr), write(XStr), nl), Map).
|