% usase: swipl day11.pl input.txt 1000000 :- use_module(library(pio)). :- initialization(main, main). main([FileName, ExpandFactorArg | _]) :- input(FileName, Map), atom_number(ExpandFactorArg, ExpandFactor), findall(Dist, distance(_, Map, _, ExpandFactor, Dist), Dists), sum_list(Dists, Sum), writef('Answer=%t\n', [Sum]). % Dist is distance along Axis in Map between two row/col A & B (after expansion) distance(Axis, Map, A-B, ExpandFactor, Dist) :- true_coords(Axis, Map, ExpandFactor, TrueNs), member(A-ACount, TrueNs), member(B-BCount, TrueNs), A < B, Dist is (B - A) * ACount * BCount. % TrueXs is the list of all coordinates after expanion along Axis in Map true_coords(x, Map, ExpandFactor, TrueXs) :- NextX = {ExpandFactor}/[Row, LastX-_, X-Count]>>( sum_list(Row, Count), (Count = 0 -> X is LastX + ExpandFactor; X is LastX + 1)), scanl(NextX, Map, -1-0, Xs), Xs = [_ | TrueXs]. true_coords(y, [FirstRow | Map], ExpandFactor, TrueYs) :- foldl(add_vectors, Map, FirstRow, CountY), NextY = {ExpandFactor}/[Count, LastY-_, Y-Count]>>( Count = 0 -> Y is LastY + ExpandFactor; Y is LastY + 1), scanl(NextY, CountY, -1-0, Ys), Ys = [_ | TrueYs]. add_vectors([], [], []). add_vectors([A | V1], [B | V2], [C | V]) :- C is A + B, add_vectors(V1, V2, V). % Read file into 2D array Map. 1 corresponding to a galaxy and 0 otherwise. input(FileName, Map) :- phrase_from_file(lines(Map), FileName). lines([]) --> eos. lines([Line|Lines]) --> line(Line), lines(Lines). line([]) --> "\n" ; eos. line([1|Ls]) --> "#", line(Ls). line([0|Ls]) --> ".", line(Ls). eos([], []).