:- use_module(library(clpfd)). :- use_module(library(dcg/basics)). line(Line) --> string_without("\n", L), { Line =.. [line | L] }. lines([Line]) --> line(Line), blanks. lines([L|Lines]) --> line(L), blanks, lines(Lines). traverse(_, _, [], []). traverse(R-D, Rd-Dd, Lines, Tiles) :- R #> 31, R1 #= R - 31, traverse(R1-D, Rd-Dd, Lines, Tiles). traverse(_, _-Dd, Lines, []) :- length(Lines, L), Dd #> L. traverse(R-D, Rd-Dd, [Line | Lines], [T|Tiles]) :- arg(R, Line, T), R1 #= R + Rd, D1 #= D + Dd, length(Head, Dd), append(Head, Lines1, [Line | Lines]), traverse(R1-D1, Rd-Dd, Lines1, Tiles). path(Lines, D, Count) :- traverse(1-1, D, Lines, Path), aggregate_all(count, member(35, Path), Count). step_1(Trees) :- phrase_from_file(lines(Lines), 'advent_3_inp.txt'), path(3-1, Lines, Path), aggregate_all(count, member(35, Path), Trees), !. product_(N, M, P) :- P #= N * M. step_2([C|Counts], Product) :- phrase_from_file(lines(Lines), 'advent_3_inp.txt'), maplist(path(Lines), [1-1, 3-1, 5-1, 7-1, 1-2], [C|Counts]), foldl(product_, Counts, C, Product), !.