205 lines
3.8 KiB
D
205 lines
3.8 KiB
D
|
import std;
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
File("input", "r").byLineCopy.array.calculateNumberOfOccupiedSeatsStable.writeln;
|
||
|
}
|
||
|
|
||
|
auto calculateValidNeighbouringSeatPositions(size_t i, size_t j, size_t height, size_t width)
|
||
|
{
|
||
|
return [
|
||
|
tuple(i - 1, j - 1), tuple(i - 1, j), tuple(i - 1, j + 1), tuple(i,
|
||
|
j - 1), tuple(i, j + 1), tuple(i + 1, j - 1), tuple(i + 1, j),
|
||
|
tuple(i + 1, j + 1)
|
||
|
].filter!(position => position[0] >= 0 && position[0] < height
|
||
|
&& position[1] >= 0 && position[1] < width);
|
||
|
}
|
||
|
|
||
|
auto calculateNewSeatState(const char seat, ulong numberOfOccupiedNeighbouringSeats)
|
||
|
{
|
||
|
if (seat == '#' && numberOfOccupiedNeighbouringSeats >= 4)
|
||
|
{
|
||
|
return 'L';
|
||
|
}
|
||
|
else if (seat == 'L' && numberOfOccupiedNeighbouringSeats == 0)
|
||
|
{
|
||
|
return '#';
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return seat;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
auto calculateNextSeatOccupation(const char[][] seats)
|
||
|
{
|
||
|
if (seats.empty || seats.front.empty)
|
||
|
{
|
||
|
return seats;
|
||
|
}
|
||
|
immutable height = seats.length;
|
||
|
immutable width = seats.front.length;
|
||
|
|
||
|
return seats.enumerate.map!((indexedRow) {
|
||
|
immutable i = indexedRow.index;
|
||
|
const row = indexedRow.value;
|
||
|
return row.byChar.enumerate.map!((indexedSeat) {
|
||
|
immutable j = indexedSeat.index;
|
||
|
immutable seat = indexedSeat.value;
|
||
|
immutable numberOfOccupiedNeighbouringSeats = calculateValidNeighbouringSeatPositions(i,
|
||
|
j, height, width).map!(position => seats[position[0]][position[1]])
|
||
|
.filter!(it => it == '#')
|
||
|
.count;
|
||
|
return seat.calculateNewSeatState(numberOfOccupiedNeighbouringSeats);
|
||
|
}).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.L#.##
|
||
|
#LLLLLL.L#
|
||
|
L.L.L..L..
|
||
|
#LLL.LL.L#
|
||
|
#.LL.LL.LL
|
||
|
#.LLLL#.##
|
||
|
..L.L.....
|
||
|
#LLLLLLLL#
|
||
|
#.LLLLLL.L
|
||
|
#.#LLLL.##`);
|
||
|
}
|
||
|
|
||
|
unittest
|
||
|
{
|
||
|
auto input = `#.LL.L#.##
|
||
|
#LLLLLL.L#
|
||
|
L.L.L..L..
|
||
|
#LLL.LL.L#
|
||
|
#.LL.LL.LL
|
||
|
#.LLLL#.##
|
||
|
..L.L.....
|
||
|
#LLLLLLLL#
|
||
|
#.LLLLLL.L
|
||
|
#.#LLLL.##`.dup.split("\n");
|
||
|
assert(input.calculateNextSeatOccupation.join("\n") == `#.##.L#.##
|
||
|
#L###LL.L#
|
||
|
L.#.#..#..
|
||
|
#L##.##.L#
|
||
|
#.##.LL.LL
|
||
|
#.###L#.##
|
||
|
..#.#.....
|
||
|
#L######L#
|
||
|
#.LL###L.L
|
||
|
#.#L###.##`);
|
||
|
}
|
||
|
|
||
|
unittest
|
||
|
{
|
||
|
auto input = `#.##.L#.##
|
||
|
#L###LL.L#
|
||
|
L.#.#..#..
|
||
|
#L##.##.L#
|
||
|
#.##.LL.LL
|
||
|
#.###L#.##
|
||
|
..#.#.....
|
||
|
#L######L#
|
||
|
#.LL###L.L
|
||
|
#.#L###.##`.dup.split("\n");
|
||
|
assert(input.calculateNextSeatOccupation.join("\n") == `#.#L.L#.##
|
||
|
#LLL#LL.L#
|
||
|
L.L.L..#..
|
||
|
#LLL.##.L#
|
||
|
#.LL.LL.LL
|
||
|
#.LL#L#.##
|
||
|
..L.L.....
|
||
|
#L#LLLL#L#
|
||
|
#.LLLLLL.L
|
||
|
#.#L#L#.##`);
|
||
|
}
|
||
|
|
||
|
unittest
|
||
|
{
|
||
|
auto input = `#.#L.L#.##
|
||
|
#LLL#LL.L#
|
||
|
L.L.L..#..
|
||
|
#LLL.##.L#
|
||
|
#.LL.LL.LL
|
||
|
#.LL#L#.##
|
||
|
..L.L.....
|
||
|
#L#LLLL#L#
|
||
|
#.LLLLLL.L
|
||
|
#.#L#L#.##`.dup.split("\n");
|
||
|
assert(input.calculateNextSeatOccupation.join("\n") == `#.#L.L#.##
|
||
|
#LLL#LL.L#
|
||
|
L.#.L..#..
|
||
|
#L##.##.L#
|
||
|
#.#L.LL.LL
|
||
|
#.#L#L#.##
|
||
|
..L.L.....
|
||
|
#L#L##L#L#
|
||
|
#.LLLLLL.L
|
||
|
#.#L#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 == 37);
|
||
|
}
|