aoc2020/day11/part2/main.d

148 lines
3.4 KiB
D

import std;
void main()
{
File("input", "r").byLineCopy.array.calculateNumberOfOccupiedSeatsStable.writeln;
}
auto calculateNewSeatState(const char seat, ulong numberOfSeenOccupiedSeats)
{
if (seat == '#' && numberOfSeenOccupiedSeats >= 5)
{
return 'L';
}
else if (seat == 'L' && numberOfSeenOccupiedSeats == 0)
{
return '#';
}
else
{
return seat;
}
}
auto generateIndexes(ptrdiff_t posY, ptrdiff_t posX, ptrdiff_t y, ptrdiff_t x)
{
return recurrence!((state, n) => tuple(state[n - 1][0] + y, state[n - 1][1] + x))(
tuple(posY, posX)).drop(1);
}
auto isValidPosition(Tuple!(ptrdiff_t, ptrdiff_t) pos, size_t height, size_t width)
{
return pos[0] >= 0 && pos[0] < height && pos[1] >= 0 && pos[1] < width;
}
auto findFirstSeatInDirection(const char[][] seats, const Tuple!(ptrdiff_t,
ptrdiff_t) direction, const Tuple!(ptrdiff_t,
ptrdiff_t) initialPosition, const size_t height, const size_t width)
{
return generateIndexes(initialPosition[0], initialPosition[1], direction[0], direction[1]).until!(
pos => !pos.isValidPosition(height, width))
.map!(pos => seats[pos[0]][pos[1]])
.find!(seat => seat != '.');
}
auto calculateNextSeatOccupation(const char[][] seats)
{
if (seats.empty || seats.front.empty)
{
return seats;
}
auto height = seats.length;
auto width = seats.front.length;
return seats.enumerate.map!((indexedRow) {
ptrdiff_t i = indexedRow.index;
auto row = indexedRow.value;
return row.byChar.enumerate.map!((indexedSeat) {
ptrdiff_t j = indexedSeat.index;
auto seat = indexedSeat.value;
auto numberOfSeenOccupiedSeats = [
tuple(0L, 1L), tuple(-1L, 1L), tuple(-1L, 0L), tuple(-1L,
-1L), tuple(0L, -1L), tuple(1L, -1L), tuple(1L, 0L), tuple(1L, 1L)
].map!(direction => findFirstSeatInDirection(seats, direction,
tuple(i, j), height, width))
.filter!(lineOfSight => !lineOfSight.empty)
.map!(lineOfSeight => lineOfSeight.front)
.filter!(it => it == '#')
.count;
return seat.calculateNewSeatState(numberOfSeenOccupiedSeats);
}).array;
}).array;
}
unittest
{
auto input = `L.LL.LL.LL
LLLLLLL.LL
L.L.L..L..
LLLL.LL.LL
L.LL.LL.LL
L.LLLLL.LL
..L.L.....
LLLLLLLLLL
L.LLLLLL.L
L.LLLLL.LL`.dup.split("\n");
assert(input.calculateNextSeatOccupation.join("\n") == `#.##.##.##
#######.##
#.#.#..#..
####.##.##
#.##.##.##
#.#####.##
..#.#.....
##########
#.######.#
#.#####.##`);
}
unittest
{
auto input = `#.##.##.##
#######.##
#.#.#..#..
####.##.##
#.##.##.##
#.#####.##
..#.#.....
##########
#.######.#
#.#####.##`.dup.split("\n");
assert(input.calculateNextSeatOccupation.join("\n") == `#.LL.LL.L#
#LLLLLL.LL
L.L.L..L..
LLLL.LL.LL
L.LL.LL.LL
L.LLLLL.LL
..L.L.....
LLLLLLLLL#
#.LLLLLL.L
#.LLLLL.L#`);
}
auto calculateNumberOfOccupiedSeatsStable(const char[][] seats)
{
return recurrence!((seats, n) => seats[n - 1].calculateNextSeatOccupation)(seats).slide(2)
.map!array
.find!((pair) => pair[0] == pair[1])
.front
.front
.join
.filter!(seat => seat == '#')
.count;
}
unittest
{
auto input = `L.LL.LL.LL
LLLLLLL.LL
L.L.L..L..
LLLL.LL.LL
L.LL.LL.LL
L.LLLLL.LL
..L.L.....
LLLLLLLLLL
L.LLLLLL.L
L.LLLLL.LL`.dup.split("\n");
assert(input.calculateNumberOfOccupiedSeatsStable == 26);
}