adamcrussell (adamcrussell) wrote,
adamcrussell
adamcrussell

2020 Advent Of Code Day 9

Prolog. Developed and tested with SWI-Prolog 8.0.3.

check_and_read(10, [] ,_):-
    !.
check_and_read(13, [], _):-
    !.
check_and_read(32, [], _):-
    !.
check_and_read(end_of_file, [], _):-
    !.
check_and_read(Char, [Char|Chars], Stream):-
    get_code(Stream, NextChar),
    check_and_read(NextChar, Chars, Stream).

read_data(Stream, []):-
    at_end_of_stream(Stream).
read_data(Stream, [X|L]):-
    \+ at_end_of_stream(Stream),
    get_code(Stream, Char),
    check_and_read(Char, Chars, Stream),
    atom_codes(X, Chars),
    read_data(Stream, L).

get_n(N, List, ListN):-
    get_n(N, List, 0, [], ListN).
get_n(N, [_|_], N, ListN, ListN).     
get_n(N, [H|T], Counter, ListAccum, ListN):- 
    C is Counter + 1,
    get_n(N, T, C, [H|ListAccum], ListN).

check_sum(X, List):-
    member(A, List),
    member(B, List),
    atom_number(A, N0),
    atom_number(B, N1),
    A \== B,
    X is N0 + N1.
    
check_sum_list(X, List, Sum):-
    check_sum_list(X, List, 0, Sum).
check_sum_list(_, [], Sum, Sum).    
check_sum_list(X, [H|T], SumAccum, Sum):-
    atom_number(H, H0),
    S is H0 + SumAccum,
    check_sum_list(X, T, S, Sum).

first_not_sum(Records, FirstNotSum):-
    get_n(5, Records, Preamble),
    first_not_sum(Preamble, 0, 25, Records, [], FirstNotSum). 
first_not_sum(_, _, _, _, [-1], _).    
first_not_sum(Preamble, Counter, Ignore, [H|T], Seen, FirstNotSum):-
    Counter >= Ignore,
    C is Counter + 1,
    atom_number(H, X),
    \+ check_sum(X, Seen),
    FirstNotSum is X,
    first_not_sum(Preamble, C, Ignore, T, [-1], FirstNotSum).
first_not_sum(Preamble, Counter, Ignore, [H|T], Seen, FirstNotSum):- 
    Counter < Ignore,
    C is Counter + 1,
    append(Seen, [H], Seent),
    first_not_sum(Preamble, C, Ignore, T, Seent, FirstNotSum).     
first_not_sum(Preamble, Counter, Ignore, [H|T], [_|ST], FirstNotSum):-
    append(ST, [H], STH),
    first_not_sum(Preamble, Counter, Ignore, T, STH, FirstNotSum).

sum_to_missing(Missing, Records, SumToMissing):-
    sum_to_missing(Missing, Records, Records, [], SumToMissing).
sum_to_missing(_, [], _, SumToMissing, SumToMissing).
sum_to_missing(Missing, [H|T], Records, SumToMissingAccum, SumToMissing):-
    check_sum_list(Missing, SumToMissingAccum, Sum),
    Sum < Missing,
    append(SumToMissingAccum, [H], S0),
    sum_to_missing(Missing, T, Records, S0, SumToMissing).
sum_to_missing(Missing, _, Records, SumToMissingAccum, SumToMissing):-
    check_sum_list(Missing, SumToMissingAccum, Sum),
    Sum == Missing,
    sum_to_missing(Missing, [], Records, SumToMissingAccum, SumToMissing).
sum_to_missing(Missing, [H|T], Records, SumToMissingAccum, SumToMissing):-
    check_sum_list(Missing, SumToMissingAccum, Sum),
    Sum > Missing,
    [_|TAccum] = SumToMissingAccum,
    sum_to_missing(Missing, [H|T], Records, TAccum, SumToMissing).
    
main:-
    open('data', read, Stream),
    read_data(Stream, Records),
    close(Stream),
    first_not_sum(Records, FirstNotSum),
    format("The first number not a sum of two previous numbers: ~d.~n",[FirstNotSum]),
    sum_to_missing(FirstNotSum, Records, SumToMissing),
    sort(SumToMissing, SumToMissingSorted),
    [L, S|_] = SumToMissingSorted,
    atom_number(S, Smallest),
    atom_number(L, Largest),
    SmallestLargestSum is Smallest + Largest,
    format("The sum of the smallest and largest of the list of numbers that sum to ~d ([~d, ~d]): ~d.~n",[FirstNotSum, Smallest, Largest, SmallestLargestSum]).
Tags: advent of code, logic programming, prolog, prolog programming
Subscribe

Recent Posts from This Journal

Comments for this post were disabled by the author