Day 3

2020-01-23

Problem

I’m starting to get more proficient writing Prolog. The first part was nothing to write home about. For isTree/4, I end up using two definitions that only differ by whether an accumulator value is incremented. In the definition of isTree2/6, I end up using an if predicate (Cond -> X; Y) which saves a few lines of repetition.

I spent the most time trying to debug main2/2 where the toboggan is traversing down a steeper slope i.e. going right 1 and down 2. I thought that this was an issue in atPos2/4, and I tried modifying the Index to take into account the current position in the y-axis. The problem was that I was iterating through the list one at a time, so I wrote skipList/3 to skip over elements of the original array.

Solution

sample(X):-
    X = "..##.......
#...#...#..
.#....#..#.
..#.#...#.#
.#...##..#.
..#.##.....
.#.#.#....#
.#........#
#.##...#...
#...##....#
.#..#...#.#".

atPos(String, Counter, Char):-
    string_chars(String, Chars),
    length(Chars, Modulus),
    % 3 right, 1 down
    Index is mod(Counter*3, Modulus),
    nth0(Index, Chars, Char).

isTree([], _, X, X).
isTree([X|Xs], Counter, Acc, Result):-
    atPos(X, Counter, Char),
    Char \= '#',
    C1 is Counter + 1,
    isTree(Xs, C1, Acc, Result).
isTree([X|Xs], Counter, Acc, Result):-
    atPos(X, Counter, Char),
    Char = '#',
    C1 is Counter + 1,
    A1 is Acc + 1,
    isTree(Xs, C1, A1, Result).

main(Input, Result):-
    split_string(Input, '\n', '\n', L),
    isTree(L, 0, 0, Result).

atPos2(String, Counter, Right, Char):-
    string_chars(String, Chars),
    length(Chars, Modulus),
    % make sure to take into account the slope
    Index is mod(Counter*Right, Modulus),
    nth0(Index, Chars, Char).

% This is necessary to traverse down the slope correclty
skipList(L, 0, L).
skipList([_], _, []).
skipList([_|Rest], Counter, Result):-
    C1 is Counter - 1,
    skipList(Rest, C1, Result).

isTree2([], _,_,_, X, X).
isTree2([X|Xs], Right, Down, Counter, Acc, Result):-
    atPos2(X, Counter, Right, Char),
    skipList([X|Xs], Down, Xss),
    C1 is Counter + 1,
    (   Char = '#' ->
    	A1 is Acc + 1;
    	A1 is Acc
    ),
    isTree2(Xss, Right, Down, C1, A1, Result).

main2(Input, Result):-
    split_string(Input, '\n', '\n', L),
    isTree2(L, 1, 1, 0, 0, A),
    isTree2(L, 3, 1, 0, 0, B),
    isTree2(L, 5, 1, 0, 0, C),
    isTree2(L, 7, 1, 0, 0, D),
    isTree2(L, 1, 2, 0, 0, E),
    Result is A*B*C*D*E.

Index