adamcrussell (adamcrussell) wrote,
adamcrussell
adamcrussell

2020 Advent Of Code Day 12 (Part 2)

Prolog. Developed and tested with SWI-Prolog 8.2.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).

adjust_coordinates_left(Value, OldCoordinates, RecalibratedCoordinates):-
    V is Value - 90,
    V \== 0,
    [Y, X] = OldCoordinates,
    X0 is X,
    Y0 is Y * -1,
    adjust_coordinates_left(V, [X0, Y0], RecalibratedCoordinates).
adjust_coordinates_left(Value, OldCoordinates, RecalibratedCoordinates):-
    V is Value - 90,
    V == 0,
    [Y, X] = OldCoordinates,
    X0 is X,
    Y0 is Y * -1,
    RecalibratedCoordinates = [X0, Y0].

adjust_coordinates_right(Value, OldCoordinates, RecalibratedCoordinates):-
    V is Value - 90,
    V \== 0,
    [Y, X] = OldCoordinates,
    X0 is X * -1,
    Y0 is Y,
    adjust_coordinates_right(V, [X0, Y0], RecalibratedCoordinates).
adjust_coordinates_right(Value, OldCoordinates, RecalibratedCoordinates):-
    V is Value - 90,
    V == 0,
    [Y, X] = OldCoordinates,
    X0 is X * -1,
    Y0 is Y,
    RecalibratedCoordinates = [X0, Y0].

move_waypoint_north(Value, WayPointPosition, UpdatedWayPointPosition):-
     [OldX, OldY] = WayPointPosition,
     NewX = OldX,
     NewY is OldY - Value,
     UpdatedWayPointPosition = [NewX, NewY].

move_waypoint_south(Value, WayPointPosition, UpdatedWayPointPosition):-
     [OldX, OldY] = WayPointPosition,
     NewX = OldX,
     NewY is OldY + ( Value),
     UpdatedWayPointPosition = [NewX, NewY].
     
move_waypoint_west(Value, WayPointPosition, UpdatedWayPointPosition):-
     [OldX, OldY] = WayPointPosition,
     NewY = OldY,
     NewX is OldX - (Value),
     UpdatedWayPointPosition = [NewX, NewY].         
         
move_waypoint_east(Value, WayPointPosition, UpdatedWayPointPosition):-
     [OldX, OldY] = WayPointPosition,
     NewY = OldY,
     NewX is OldX + Value,
     UpdatedWayPointPosition = [NewX, NewY].  
     
execute_command(Command, Value, WayPointPosition, ShipPosition, UpdatedWayPointPosition, UpdatedShipPosition):-
     (Command == 'R',
     UpdatedShipPosition = ShipPosition,
     adjust_coordinates_right(Value, WayPointPosition, UpdatedWayPointPosition));
     (Command == 'L',
     UpdatedShipPosition = ShipPosition,
     adjust_coordinates_left(Value, WayPointPosition, UpdatedWayPointPosition));
    (Command == 'N',
     UpdatedShipPosition = ShipPosition,
     move_waypoint_north(Value, WayPointPosition, UpdatedWayPointPosition));
    (Command == 'S',
     UpdatedShipPosition = ShipPosition,
     move_waypoint_south(Value, WayPointPosition, UpdatedWayPointPosition));
    (Command == 'E',
     UpdatedShipPosition = ShipPosition,
     move_waypoint_east(Value, WayPointPosition, UpdatedWayPointPosition));
    (Command == 'W',
     UpdatedShipPosition = ShipPosition,
     move_waypoint_west(Value, WayPointPosition, UpdatedWayPointPosition));
    (Command == 'F',
     UpdatedWayPointPosition = WayPointPosition,
     [X0, Y0] = WayPointPosition,
     [X1, Y1] = ShipPosition,
     X is X1 + (Value * X0 ),
     Y is Y1 + (Value * Y0 ),
     UpdatedShipPosition = [X, Y]).

move_ship([]).
move_ship(Commands, FinalPosition):-
    move_ship(Commands, [10, -1], [0, 0], FinalPosition).
move_ship([], _, FinalPosition, FinalPosition):-!.    
move_ship([H|T], WayPointPosition, ShipPosition, FinalPosition):- 
    atom_chars(H, C),
    [Command|Number] = C,
    number_chars(Value, Number),
    execute_command(Command, Value, WayPointPosition, ShipPosition, UpdatedWayPointPosition, UpdatedShipPosition),
    move_ship(T, UpdatedWayPointPosition, UpdatedShipPosition, 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]),
    halt.   
Tags: advent of code, logic programming, prolog, prolog programming
Subscribe

Recent Posts from This Journal

Comments for this post were disabled by the author