chars_digits([], []). chars_digits([C|Cs], [D|Ds]) :- char_type(C, digit(D)), chars_digits(Cs, Ds). read_file(Stream, []) :- at_end_of_stream(Stream). read_file(Stream, [X|L]) :- \+ at_end_of_stream(Stream), read_line_to_codes(Stream, C), chars_digits(C, X), read_file(Stream, L). main :- open('../input/03', read, Stream), read_file(Stream, Lines), !, close(Stream), most_solve(Lines, A), least_solve(Lines, B), bin_dec(A, A1), bin_dec(B, B1), X is A1 * B1, print([A1, B1, X]). first_elements([], []). first_elements([[X|_]|As], [B|Bs]) :- first_elements(As, Bs), B is X. last_elements([], _, []). last_elements([[X|Xs]|As], X, [Xs|Bs]) :- last_elements(As, X, Bs). last_elements([[X|_]|As], F, Bs) :- F =\= X, last_elements(As, F, Bs). freq([], 0, 0). freq([1|As], Z, O) :- freq(As, Z, O1), O is O1 + 1. freq([0|As], Z, O) :- freq(As, Z1, O), Z is Z1 + 1. most_common(A, 1) :- freq(A, Z, O), O >= Z. most_common(A, 0) :- freq(A, Z, O), O < Z. least_common(A, 0) :- freq(A, Z, O), Z > 0, (O >= Z; O = 0). least_common(A, 1) :- freq(A, Z, O), O > 0, (O < Z; Z = 0). first_elem([A|_], A). most_solve(A, [B]) :- first_elements(A, F), most_common(F, B), first_elem(A, N), length(N, 1). most_solve(A, [B|Bs]) :- first_elements(A, F), most_common(F, B), last_elements(A, B, L), most_solve(L, Bs). least_solve(A, [B]) :- first_elements(A, F), least_common(F, B), first_elem(A, N), length(N, 1). least_solve(A, [B|Bs]) :- first_elements(A, F), least_common(F, B), last_elements(A, B, L), least_solve(L, Bs). bin_dec(B, X) :- bin_dec(B, 0, X). bin_dec([], X, X). bin_dec([B|Bs], N, X) :- M is N * 2 + B, bin_dec(Bs, M, X).