:- use_module(library(dcg/basics)). :- use_module(library(dcg/high_order)). :- table ok/3. ok([], [], []). ok([0'.|Ts], Cs, [0'.|Rs]) :- ok(Ts, Cs, Rs). ok([0'#|Ts], [C|Cs], [0'#|Rs]) :- C1 is C - 1, fill(Ts, C1, Rs, Ts1, Rs1), ok(Ts1, Cs, Rs1). ok([0'?|Ts], Cs, [0'.|Rs]) :- ok(Ts, Cs, Rs). ok([0'?|Ts], [C|Cs], [0'#|Rs]) :- C1 is C - 1, fill(Ts, C1, Rs, Ts1, Rs1), ok(Ts1, Cs, Rs1). :- table fill/5. fill([], 0, [], [], []) :- !. fill([T|Ts], 0, [0'.|Rs], Ts, Rs) :- !, can_empty(T). fill([T|Ts], C, [0'#|Rs], Ts1, Rs1) :- C > 0, C1 is C - 1, can_fill(T), !, fill(Ts, C1, Rs, Ts1, Rs1). can_fill(0'#). can_fill(0'?). can_empty(0'.). can_empty(0'?). count(T, C, N) :- bagof(S, ok(T, C, S), Ss), length(Ss, N). count(T-C, N) :- count(T, C, N). examples1 :- count(`???.###`, [1, 1, 3], 1), count(`.??..??...?##.`, [1, 1, 3], 4), count(`?#?#?#?#?#?#?#?`, [1, 3, 1, 6], 1), count(`????.#...#...`, [4, 1, 1], 1), count(`????.######..#####.`, [1, 6, 5], 4), count(`?###????????`, [3, 2, 1], 10). file(Lines) --> sequence(line, Lines). line(T-C) --> template(T), " ", clues(C), blanks. template(T) --> sequence(tchar, T). tchar(T) --> [T], {member(T, `?#.`)}. clues(C) --> sequence(number, ",", C). part1(File) :- phrase_from_file(file(TCs), File), !, maplist(count, TCs, Ns), foldl(plus, Ns, 0, N), writeln(N). /* % oof ouch my memory ☹ count_unfold(T, C, N) :- unfold_template(T, T1), unfold_clues(C, C1), count(T1, C1, N). unfold_template(T, R) :- unfold_template(5, T, R). unfold_template(1, T, T) :- !. unfold_template(N, T, R) :- N > 1, N1 is N - 1, unfold_template(N1, T, R1), append(T, [0'?|R1], R). unfold_clues(C, R) :- unfold_clues(5, C, R). unfold_clues(1, C, C) :- !. unfold_clues(N, C, R) :- N > 1, N1 is N - 1, unfold_clues(N1, C, R1), append(C, R1, R). examples2 :- count_unfold(`???.###`, [1,1,3], 1), count_unfold(`.??..??...?##.`, [1,1,3], 16384), count_unfold(`?#?#?#?#?#?#?#?`, [1,3,1,6], 1), count_unfold(`????.#...#...`, [4,1,1], 16), count_unfold(`????.######..#####.`, [1,6,5], 2500), count_unfold(`?###????????`, [3,2,1], 506250), abolish_all_tables. count_unfold_all(Ls, Ns) :- length(Ls, Len), count_unfold_all(1, Len, Ls, Ns). count_unfold_all(_, _, [], []) :- !, abolish_all_tables. count_unfold_all(I, Len, [T0-C0|Ls], [N|Ns]) :- abolish_all_tables, unfold_template(T0, T), unfold_clues(C0, C), length(T, LenT), length(C, LenC), wildcards(T, W), format("[~d/~d] ~w ~w ~w > ", [I, Len, 'T'(LenT), 'C'(LenC), 'W'(W)]), flush, !, call_time(count(T, C, N), Time), !, format("[~2fs] ~d~n", [Time.wall, N]), I1 is I + 1, count_unfold_all(I1, Len, Ls, Ns). wildcards(T, N) :- setof(I, nth0(I, T, 0'?), Is), length(Is, N). part2(File) :- abolish_all_tables, writeln(go), set_prolog_flag(stack_limit, 18_000_000_000), set_prolog_flag(table_space, 40_000_000_000), phrase_from_file(file(TCs), File), !, count_unfold_all(TCs, Ns), foldl(plus, Ns, 0, N), writeln(N). */ % vim: set ft=prolog :