adamcrussell (adamcrussell) wrote,
adamcrussell
adamcrussell

2020 Advent Of Code Day 12 (Part 1)

Prolog. Developed and tested with SWI-Prolog 8.2.3.

right(0, east, east).
right(90, east, south).
right(180, east, west).
right(270, east, north).
right(360, east, east).
right(0, south, south).
right(90, south, west).
right(180, south, north).
right(270, south, east).
right(360, south, south).
right(0, west, west).
right(90, west, north).
right(180, west, east).
right(270, west, south).
right(360, west, west).
right(0, north, north).
right(90, north, east).
right(180, north, south).
right(270, north, west).
right(360, north, north).

left(Degree, Facing, NewFacing):-
    D is 360 - Degree,
    right(D, Facing, NewFacing).

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).

execute_command(Command, Value, Position, Direction, NewDirection, UpdatedPosition):-
    (Command == 'R',
     right(Value, Direction, NewDirection),
     UpdatedPosition = Position
     );
    (Command == 'L',
     left(Value, Direction, NewDirection),
     UpdatedPosition = Position);
    (Command == 'N',
     NewDirection = Direction,
     [X0, Y0] = Position,
     Y1 is Y0 + Value,
     UpdatedPosition = [X0, Y1]);
    (Command == 'S',
     NewDirection = Direction,
     [X0, Y0] = Position,
     Y1 is Y0 - Value,
     UpdatedPosition = [X0, Y1]);
    (Command == 'E',
     NewDirection = Direction,
     [X0, Y0] = Position,
     X1 is X0 + Value,
     UpdatedPosition = [X1, Y0]);
    (Command == 'W',
     NewDirection = Direction,
     [X0, Y0] = Position,
     X1 is X0 - Value,
     UpdatedPosition = [X1, Y0]);
    (Command == 'F',
     (Direction == east, execute_command('E', Value, Position, Direction, NewDirection, UpdatedPosition));
     (Direction == south, execute_command('S', Value, Position, Direction, NewDirection, UpdatedPosition));
     (Direction == west, execute_command('W', Value, Position, Direction, NewDirection, UpdatedPosition));
     (Direction == north, execute_command('N', Value, Position, Direction, NewDirection, UpdatedPosition))
     ).

move_ship([]).
move_ship(Commands, FinalPosition):-
    move_ship(Commands, east, [0, 0], FinalPosition).
move_ship([], _, FinalPosition, FinalPosition):-!.    
move_ship([H|T], Direction, IntermediatePosition, FinalPosition):-
    atom_chars(H, C),
    [Command|Number] = C,
    number_chars(Value, Number),
    execute_command(Command, Value, IntermediatePosition, Direction, NewDirection, UpdatedPosition),
    move_ship(T, NewDirection, UpdatedPosition, FinalPosition).

manhattan_distance(FinalPosition, ManhattanDistance):-
    [X, Y] = FinalPosition,
    ManhattanDistance is abs(X) + abs(Y).

main:-
    open('data', read, Stream),
    read_data(Stream, Commands),
    close(Stream),
    move_ship(Commands, FinalPosition),
    manhattan_distance(FinalPosition, ManhattanDistance), 
    format("Manhattan Distance from starting point: ~d.~n", [ManhattanDistance]).   
Tags: advent of code, logic programming, prolog, prolog programming
Subscribe

Recent Posts from This Journal

Comments for this post were disabled by the author