# 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]).
```

### Recent Posts from This Journal

• #### A Simple Binary Tree in Perl

This Binary Tree implementation uses Class::Struct and only defines find() and insert() operations, along with a simple print function for…

• #### The Weekly Challenge 127: Conflict Intervals (C++ Solutions)

Part 2 of The Weekly Challenge 127: You are given two sets with unique numbers. Write a script to figure out if they are disjoint. #include

• #### The Weekly Challenge 127: Disjoint Lists (C++ Solutions)

Part 1 of The Weekly Challenge 127: You are given two sets with unique numbers. Write a script to figure out if they are disjoint. #include

Comments for this post were disabled by the author