Day 2
2020-01-21
This problem was fun because it involved some real parsing. Being able to treat strings directly as Prolog atoms with term_string/2
was a neat way to deconstruct the first column in the solution (e.g. 1-3
) directly into a pair.
Before coming to use include/3
, I tried out maplist/3
with some moderate success by adding an extra variable to verify
. For some reason, the interpreter was unhappy with it. include/3
is a much nicer way to define the list anyhow. I was also surprised that I had to write my own predicate to count the number of times a particular item exists within a list. I might have been able to get away with this using include/3
, but I’m not proficient enough yet to know.
Solution
% https://stackoverflow.com/a/46902736
count(_, [], 0).
count(C, [C|T], N):-
count(C, T, Res),
N is Res+1.
count(C, [X|T], N):-
C \= X,
count(C, T, N).
parse(String, Data):-
split_string(String, '\s', '\s', [MinMax, CharColon, Password]),
term_string(Min-Max, MinMax),
% remove the colon in the data
string_chars(CharColon, [Char|_]),
Data = (Min, Max, Char, Password).
verify(String):-
parse(String, (Min, Max, Char, Password)),
string_chars(Password, Chars),
count(Char, Chars, N),
N >= Min,
N =< Max.
main(String, Result):-
split_string(String, '\n', '\n', L),
include(verify, L, Verified),
length(Verified, Result).
verify2(String):-
parse(String, (Min, Max, Char, Password)),
string_chars(Password, Chars),
nth1(Min, Chars, Pos0),
nth1(Max, Chars, Pos1),
Pos0 \= Pos1,
( Pos0 = Char, Pos1 \= Char;
Pos0 \= Char, Pos1 = Char).
main2(String, Result):-
split_string(String, '\n', '\n', L),
include(verify2, L, Verified),
length(Verified, Result).
sample(X):-
X = "1-3 a: abcde
1-3 b: cdefg
2-9 c: ccccccccc".