adamcrussell (adamcrussell) wrote,
adamcrussell
adamcrussell

2020 Advent Of Code Day 10

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),
    number_codes(X, Chars),
    read_data(Stream, L).

differences([H|[]]):-
    H == 1,
    assert(difference(1, [H-0])).
differences([H|[]]):-
    H == 3,
    assert(difference(1, [H-0])).
differences([H0, H1|T]):-
    Delta is H0 - H1,
    Delta == 1,
    assert(difference(1, [H0-H1])),
    differences([H1|T]).
differences([H0, H1|T]):-
    Delta is H0 - H1,
    Delta == 3,
    assert(difference(3, [H0-H1])),
    differences([H1|T]).    
differences([H0, H1|[]]):-
    Delta is H0 - H1,
    Delta == 1,
    assert(difference(1, [H0-H1])).
differences([H0, H1|[]]):-
    Delta is H0 - H1,
    Delta == 1,
    assert(difference(1, [H0-H1])).
    
adapters(Adapters, AdapterChain):-
    sort(Adapters, SortedAdapters),
    adapters(SortedAdapters, 0, 0, [], AdapterChain).
adapters([], _, _, [PreviousAdapter|AdapterChainAccum], AdapterChain):-
    BuiltInAdapter is PreviousAdapter + 3,
    AdapterChain = [BuiltInAdapter, PreviousAdapter|AdapterChainAccum].
adapters(Adapters, CumulativeJoltage, PreviousAdapter, AdapterChainAccum, AdapterChain):-
    member(Adapter, Adapters),
    \+ member(Adapter, AdapterChainAccum),
    Delta is Adapter - PreviousAdapter,
    (Delta == 0; Delta == 1; Delta == 2; Delta == 3),
    C is CumulativeJoltage + Adapter,
    delete(Adapters, Adapter, RemainingAdapters),
    adapters(RemainingAdapters, C, Adapter, [Adapter|AdapterChainAccum], AdapterChain).

within3(Adapter, [H|T], Adapters):-
    within3(Adapter, [H|T], [], Adapters).
within3(_, [], Adapters, Adapters).
within3(Adapter, [H|T], AdaptersAccum, Adapters):-
    Delta is H - Adapter,
    between(1, 3, Delta),
    within3(Adapter, T, [H|AdaptersAccum], Adapters).
within3(Adapter, [_|T], AdaptersAccum, Adapters):-
    within3(Adapter, T, AdaptersAccum, Adapters).

add_branch(_, []).
add_branch(Adapter, [H|T]):-
    assert(branch(Adapter-H)),
    add_branch(Adapter, T).

adapter_tree([], _).
adapter_tree([H|T], Adapters):-
    within3(H, Adapters, Adapters3),
    add_branch(H, Adapters3),
    adapter_tree(T, Adapters),
    adapter_tree(Adapters3, Adapters).
adapter_tree(Adapter, Adapters):-
    within3(Adapter, Adapters, Adapters3),
    add_branch(Adapter, Adapters3),
    adapter_tree(Adapters3, Adapters).
    
difference3(Difference3):-
    findall(X, difference(3, X), Differences),
    length(Differences, Difference3).

difference1(Difference1):-
    findall(X, difference(1, X), Differences),
    length(Differences, Difference1).

chain_size(Records, ChainSize):-
    sort(Records, RecordsSorted),
    adapter_tree(0, RecordsSorted),
    last(RecordsSorted, Largest),
    findall(X, branch(X-Largest), Leaves), 
    length(Leaves, ChainSize).

main:-
    open('data', read, Stream),
    read_data(Stream, Records),
    close(Stream),
    adapters(Records, AdapterChain),
    differences(AdapterChain),
    difference3(Difference3),
    difference1(Difference1),
    DifferenceProduct is Difference1 * Difference3,
    format("1-jolt differences multiplied by the number of 3-jolt differences: ~d.~n", [DifferenceProduct]),
    chain_size(Records, ChainSize),
    format("total number of distinct ways you can arrange the adapters: ~d.~n", [ChainSize]).
Tags: advent of code, logic programming, prolog, prolog programming
Subscribe

Recent Posts from This Journal

Comments for this post were disabled by the author