You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
2.2 KiB
Prolog
80 lines
2.2 KiB
Prolog
file_to_ranges(Path, Ranges) :-
|
|
read_file_to_string(Path, S, []),
|
|
split_string(S, ",", ",", Ranges).
|
|
|
|
range_to_tuple(Range, Start-End) :-
|
|
split_string(Range, "-", "\n", [Start0|[End0]]),
|
|
number_string(Start, Start0),
|
|
number_string(End, End0).
|
|
|
|
is_even(N) :- integer(N), mod(N, 2) =:= 0.
|
|
|
|
main :-
|
|
file_to_ranges("data.txt", Ranges),
|
|
maplist(range_to_tuple, Ranges, Tuples),
|
|
|
|
% Part 1
|
|
maplist(find_invalids_part1, Tuples, InvalidsPart1Unflattened),
|
|
flatten(InvalidsPart1Unflattened, InvalidsPart1),
|
|
sumlist(InvalidsPart1, Part1Sum),
|
|
write("Part 1: "),
|
|
writeln(Part1Sum),
|
|
|
|
% Part 2
|
|
maplist(find_invalids_part2, Tuples, InvalidsPart2Unflattened),
|
|
flatten(InvalidsPart2Unflattened, InvalidsPart2),
|
|
sumlist(InvalidsPart2, Part2Sum),
|
|
write("Part 2: "),
|
|
writeln(Part2Sum).
|
|
|
|
% Part 1
|
|
|
|
find_invalids_part1(Start-End, Invalids) :-
|
|
numlist(Start, End, Numbers),
|
|
include(is_invalid_part1, Numbers, Invalids).
|
|
|
|
is_invalid_part1(Number) :-
|
|
number_string(Number, String),
|
|
string_length(String, Len),
|
|
(is_even(Len) ->
|
|
Len2 is Len / 2,
|
|
sub_string(String, 0, Len2, _, Start),
|
|
sub_string(String, Len2, Len2, _, End),
|
|
Start = End
|
|
; false).
|
|
|
|
% Part 2
|
|
|
|
find_invalids_part2(Start-End, Invalids) :-
|
|
numlist(Start, End, Numbers),
|
|
include(is_invalid_part2, Numbers, Invalids).
|
|
|
|
is_invalid_part2(Number) :-
|
|
number_string(Number, String),
|
|
string_length(String, FullLength),
|
|
SubLenMax is floor(FullLength / 2),
|
|
numlist(1, SubLenMax, Lengths),
|
|
maplist(generate_substrings(String), Lengths, Subs),
|
|
include(is_made_of_subs(String), Subs, Results),
|
|
length(Results, L),
|
|
L > 0.
|
|
|
|
generate_substrings(S, Len, Sub) :- sub_string(S, 0, Len, _, Sub).
|
|
|
|
% don't want to try to do this smartly, let's just check a bunch
|
|
is_made_of_subs(String, Sub) :-
|
|
string_concat(Sub, Sub, Twice),
|
|
string_concat(Twice, Sub, Thrice),
|
|
string_concat(Thrice, Sub, FourTimes),
|
|
string_concat(FourTimes, Sub, FiveTimes),
|
|
string_concat(FiveTimes, Sub, SixTimes),
|
|
string_concat(SixTimes, Sub, SevenTimes),
|
|
(
|
|
String = Twice;
|
|
String = Thrice;
|
|
String = FourTimes;
|
|
String = FiveTimes;
|
|
String = SixTimes;
|
|
String = SevenTimes
|
|
).
|