adamcrussell (adamcrussell) wrote,
adamcrussell
adamcrussell

2020 Advent Of Code Day 11 (Part 2)

Prolog. Developed and tested with SWI-Prolog 8.2.3.

line-size(91).

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

hashcount(List, HashCount):-
    hashcount(List, 0, HashCount).
hashcount([], HashCount, HashCount).
hashcount([H|T], HashCountPartial, HashCount):-  
    H == 35,
    HCP is HashCountPartial + 1,
    hashcount(T, HCP, HashCount).
hashcount([H|T], HashCountPartial, HashCount):-  
    H \== 35,
    hashcount(T, HashCountPartial, HashCount).

allseats(Records, AllSeats):-
    allseats(Records, [], AllSeats).
allseats([], AllSeats, AllSeats).
allseats([H|T], AllSeatsAccum, AllSeats):-
    string_codes(H, L),
    append(AllSeatsAccum, L, Accum),
    allseats(T, Accum, AllSeats).

adjacent_bottomleft(Seat, AllSeats, AdjacentSeat):-
    line-size(LS),
    LS1 is LS - 1,
    S is Seat + LS1,
    S > 0,
    M0 is Seat mod LS,
    M1 is S mod LS,
    ((M0 \== 0, M0 \==1,
      M1 < M0);
      (M0 == 0, M1 == LS1)),
    nth1(S, AllSeats, BLeft),
    ((BLeft \== 46, AdjacentSeat = BLeft);
      adjacent_bottomleft(S, AllSeats, AdjacentSeat)).
adjacent_bottomleft(_, _, AdjacentSeat):-
    AdjacentSeat = null.
    
adjacent_left(Seat, AllSeats, AdjacentSeat):-
    line-size(LS),
    LS1 is LS - 1,
    S is Seat - 1,
    S > 0,
    M0 is Seat mod LS,
    M1 is S mod LS,
    ((M0 \== 0, M0 \==1,
      M1 < M0);
      (M0 == 0, M1 == LS1)),
    nth1(S, AllSeats, Left),
    ((Left \== 46, AdjacentSeat = Left);
      adjacent_left(S, AllSeats, AdjacentSeat)).
adjacent_left(_, _, AdjacentSeat):-
    AdjacentSeat = null.   
adjacent_topleft(Seat, AllSeats, AdjacentSeat):-
    line-size(LS),
    LS1 is LS - 1,
    S is Seat - (LS + 1),
    S > 0,
    M0 is Seat mod LS,
    M1 is S mod LS,
    ((M0 \== 0, M0 \==1,
      M1 < M0);
      (M0 == 0, M1 == LS1)),
    nth1(S, AllSeats, TLeft),
    ((TLeft \== 46, AdjacentSeat = TLeft);
      adjacent_topleft(S, AllSeats, AdjacentSeat)).
adjacent_topleft(_, _, AdjacentSeat):-
    AdjacentSeat = null.  
adjacent_bottomright(Seat, AllSeats, AdjacentSeat):-
    line-size(LS),
    LS1 is LS - 1,
    S is Seat + (LS + 1),
    S > 0,
    M0 is Seat mod LS,
    M1 is S mod LS,
    ((M1 > M0,
     M0 \== 0);
     (M1 == 0, M0 == LS1)),
    nth1(S, AllSeats, BRight),
    ((BRight \== 46, AdjacentSeat = BRight);
      adjacent_bottomright(S, AllSeats, AdjacentSeat)).
adjacent_bottomright(_, _, AdjacentSeat):-
    AdjacentSeat = null.             
adjacent_right(Seat, AllSeats, AdjacentSeat):-
    line-size(LS),
    LS1 is LS - 1,
    S is Seat + 1,
    S > 0,
    M0 is Seat mod LS,
    M1 is S mod LS,
    ((M1 > M0,
     M0 \== 0);
     (M1 == 0, M0 == LS1)),
    nth1(S, AllSeats, Right),
    ((Right \== 46, AdjacentSeat = Right);
      adjacent_right(S, AllSeats, AdjacentSeat)).
adjacent_right(_, _, AdjacentSeat):-
    AdjacentSeat = null.
adjacent_topright(Seat, AllSeats, AdjacentSeat):-
    line-size(LS),
    LS1 is LS - 1,
    S is Seat - LS1,
    M0 is Seat mod LS,
    M1 is S mod LS,
    ((M1 > M0,
     M0 \== 0);
     (M1 == 0, M0 == LS1)),
    nth1(S, AllSeats, TRight),
    ((TRight \== 46, AdjacentSeat = TRight);
      adjacent_topright(S, AllSeats, AdjacentSeat)).
adjacent_topright(_, _, AdjacentSeat):-
    AdjacentSeat = null.    
adjacent_up(Seat, AllSeats, AdjacentSeat):-
    line-size(LS),
    S is Seat - LS,
    S > 0,
    nth1(S, AllSeats, Up),
    ((Up \== 46, AdjacentSeat = Up);
      adjacent_up(S, AllSeats, AdjacentSeat)).
adjacent_up(_, _, AdjacentSeat):-
    AdjacentSeat = null.    
adjacent_down(Seat, AllSeats, AdjacentSeat):-
    line-size(LS),
    S is Seat + LS,
    S > 0,
    nth1(S, AllSeats, Down),
    ((Down \== 46, AdjacentSeat = Down);
      adjacent_down(S, AllSeats, AdjacentSeat)).
adjacent_down(_, _, AdjacentSeat):-
    AdjacentSeat = null. 
    
adjacent(Seat, AllSeats, AdjacentSeats):-
    adjacent_left(Seat, AllSeats, AdjacentSeatLeft),
    adjacent_right(Seat, AllSeats, AdjacentSeatRight),
    adjacent_up(Seat, AllSeats, AdjacentSeatUp),
    adjacent_down(Seat, AllSeats, AdjacentSeatDown),
    adjacent_topleft(Seat, AllSeats, AdjacentSeatTopLeft),
    adjacent_topright(Seat, AllSeats, AdjacentSeatTopRight),
    adjacent_bottomleft(Seat, AllSeats, AdjacentSeatBottomLeft),
    adjacent_bottomright(Seat, AllSeats, AdjacentSeatBottomRight),
    AdjacentSeats = [AdjacentSeatLeft, AdjacentSeatRight, AdjacentSeatUp, AdjacentSeatDown,
                     AdjacentSeatTopLeft, AdjacentSeatTopRight, AdjacentSeatBottomLeft, 
                     AdjacentSeatBottomRight],!.

round(AllSeats, UpdatedSeats):-
    round(AllSeats, 0, AllSeats, [], UpdatedSeats).
round([], _, _, UpdatedSeats, UpdatedSeats).    
round([H|T], Counter, AllSeats, UpdatedSeatsAccum, UpdatedSeats):-
    C is Counter + 1,
    atom_codes(A, [H]),
    A == '.',
    append(UpdatedSeatsAccum, [H], Accum),
    round(T, C, AllSeats, Accum, UpdatedSeats).
round([H|T], Counter, AllSeats, UpdatedSeatsAccum, UpdatedSeats):-
    C is Counter + 1,
    atom_codes(A, [H]),
    A == '#',  
    adjacent(C, AllSeats, AdjacentSeats),
    hashcount(AdjacentSeats, HashCount),
    HashCount >= 5,
    H0 = 'L',
    atom_codes(H0, [A0]),
    append(UpdatedSeatsAccum, [A0], Accum),
    round(T, C, AllSeats, Accum, UpdatedSeats).
round([H|T], Counter, AllSeats, UpdatedSeatsAccum, UpdatedSeats):-
    C is Counter + 1,
    atom_codes(A, [H]),
    A == '#',  
    adjacent(C, AllSeats, AdjacentSeats),
    hashcount(AdjacentSeats, HashCount),
    HashCount \== 5,
    append(UpdatedSeatsAccum, [H], Accum),
    round(T, C, AllSeats, Accum, UpdatedSeats).    
round([H|T], Counter, AllSeats, UpdatedSeatsAccum, UpdatedSeats):-
    C is Counter + 1,
    atom_codes(A, [H]),
    A == 'L',
    adjacent(C, AllSeats, AdjacentSeats), 
    \+ member(35, AdjacentSeats),
    H0 = '#',
    atom_codes(H0, [A0]),
    append(UpdatedSeatsAccum, [A0], Accum),
    round(T, C, AllSeats, Accum, UpdatedSeats).
round([H|T], Counter, AllSeats, UpdatedSeatsAccum, UpdatedSeats):-
    C is Counter + 1,
    atom_codes(A, [H]),
    A == 'L',
    adjacent(C, AllSeats, AdjacentSeats), 
    member(35, AdjacentSeats),
    append(UpdatedSeatsAccum, [H], Accum),
    round(T, C, AllSeats, Accum, UpdatedSeats).

rounds(AllSeats, OccupiedSeats):-
    rounds(AllSeats, [], OccupiedSeats).
rounds([-1], _, _).
rounds(AllSeats, PreviousRound, OccupiedSeats):-
    round(AllSeats, UpdatedRound),!,
    write_seats(UpdatedRound), nl,
    ((
        UpdatedRound == PreviousRound,
        hashcount(UpdatedRound, OccupiedSeats),
        rounds([-1], UpdatedRound, OccupiedSeats)
    );
    (
        UpdatedRound \== PreviousRound,
        rounds(UpdatedRound, UpdatedRound, OccupiedSeats)
    )).  
    
write_seats([H|T]):-
    write_seats([H|T], 0).
write_seats([], _).    
write_seats([H|T], Counter):-
    line-size(LS),
    C is Counter + 1,
    M is C mod LS,
    M \== 0,
    atom_codes(A, [H]),
    write(A),
    write_seats(T, C).
write_seats([H|T], Counter):-
    line-size(LS),
    C is Counter + 1,
    M is C mod LS,
    M == 0,
    atom_codes(A, [H]),
    write(A),
    nl,
    write_seats(T, C).
    
main:-
    open('data', read, Stream),
    read_data(Stream, Records),
    close(Stream),
    allseats(Records, AllSeats),
    rounds(AllSeats, OccupiedSeats),
    write(OccupiedSeats), nl.
Subscribe

Recent Posts from This Journal

Comments for this post were disabled by the author