mirror of
https://github.com/HenkKalkwater/aoc-2020
synced 2024-11-22 19:15:18 +00:00
184 lines
3.6 KiB
D
184 lines
3.6 KiB
D
|
import std.array;
|
||
|
import std.algorithm;
|
||
|
import std.range;
|
||
|
import std.string;
|
||
|
import std.stdio;
|
||
|
import std.traits;
|
||
|
import std.variant;
|
||
|
|
||
|
import dayutil;
|
||
|
|
||
|
enum Spot {
|
||
|
FLOOR,
|
||
|
EMPTY,
|
||
|
TAKEN
|
||
|
}
|
||
|
|
||
|
Variant run(int part, File input, bool bigboy, string[] args) {
|
||
|
Spot[][] spots = parseInput(input.byLineCopy);
|
||
|
|
||
|
return Variant(parts!size_t(part,
|
||
|
() => part1(spots),
|
||
|
() => part2(spots)));
|
||
|
}
|
||
|
|
||
|
Spot[][] parseInput(Range)(Range range) if (isInputRange!Range && isSomeString!(ElementType!Range)) {
|
||
|
return range.map!(row => row.map!((spot) {
|
||
|
switch(spot) {
|
||
|
case '.':
|
||
|
return Spot.FLOOR;
|
||
|
case 'L':
|
||
|
return Spot.EMPTY;
|
||
|
case '#':
|
||
|
return Spot.TAKEN;
|
||
|
default:
|
||
|
assert(false, "Unknown type");
|
||
|
}
|
||
|
}).array).array;
|
||
|
}
|
||
|
|
||
|
size_t part1(Spot[][] input) {
|
||
|
Spot[][] prev = input.dup;
|
||
|
do {
|
||
|
foreach (i, row; input.enumerate) {
|
||
|
prev[i] = row.dup;
|
||
|
}
|
||
|
//prev = input.dup;
|
||
|
for (int y = 0; y < input.length; y++) {
|
||
|
for (int x = 0; x < input[y].length; x++) {
|
||
|
if(input[y][x] == Spot.FLOOR) continue;
|
||
|
|
||
|
uint adjacent_taken = 0;
|
||
|
for (int dy = max(0, y - 1); dy <= min(prev.length - 1, y + 1); dy++) {
|
||
|
for (int dx = max(0, x - 1); dx <= min(prev[y].length - 1, x + 1); dx++) {
|
||
|
if (dx == x && dy == y) continue;
|
||
|
switch(prev[dy][dx]) {
|
||
|
case Spot.TAKEN:
|
||
|
adjacent_taken++;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
import std.format;
|
||
|
if (adjacent_taken == 0) {
|
||
|
input[y][x] = Spot.TAKEN;
|
||
|
} else if (adjacent_taken >= 4) {
|
||
|
input[y][x] = Spot.EMPTY;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} while(!prev.equal(input));
|
||
|
|
||
|
return input.joiner.count(Spot.TAKEN);
|
||
|
}
|
||
|
|
||
|
|
||
|
unittest {
|
||
|
import std.format;
|
||
|
string layout = q"EOS
|
||
|
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
|
||
|
EOS";
|
||
|
size_t result = parseInput(layout.lineSplitter).part1();
|
||
|
assert(result == 37, "Result is %d (expected 37)".format(result));
|
||
|
}
|
||
|
|
||
|
size_t part2(Spot[][] input) {
|
||
|
Spot[][] prev = input.dup;
|
||
|
do {
|
||
|
foreach (i, row; input.enumerate) {
|
||
|
prev[i] = row.dup;
|
||
|
}
|
||
|
//prev = input.dup;
|
||
|
for (int y = 0; y < prev.length; y++) {
|
||
|
for (int x = 0; x < prev[y].length; x++) {
|
||
|
if(prev[y][x] == Spot.FLOOR) {
|
||
|
//debug write('.');
|
||
|
continue;
|
||
|
}
|
||
|
import std.format;
|
||
|
|
||
|
int adjacent_taken = 0;
|
||
|
for (int dy = -1; dy <= 1; dy++) {
|
||
|
for (int dx = -1; dx <= 1; dx++) {
|
||
|
if (dx == 0 && dy == 0) continue;
|
||
|
|
||
|
Spot spot;
|
||
|
int i = 1;
|
||
|
do {
|
||
|
int nx = x + i * dx;
|
||
|
int ny = y + i * dy;
|
||
|
i++;
|
||
|
if (ny < 0 || ny >= prev.length || nx < 0 || nx >= prev[ny].length) {
|
||
|
//debug write("\x1B[41m");
|
||
|
spot = Spot.EMPTY;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
spot = prev[ny][nx];
|
||
|
} while(spot == Spot.FLOOR);
|
||
|
|
||
|
if (spot == Spot.TAKEN) {
|
||
|
adjacent_taken++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//debug write(adjacent_taken);
|
||
|
//debug write("\x1B[0m");
|
||
|
if (adjacent_taken == 0) {
|
||
|
input[y][x] = Spot.TAKEN;
|
||
|
} else if (adjacent_taken >= 5) {
|
||
|
input[y][x] = Spot.EMPTY;
|
||
|
}
|
||
|
}
|
||
|
//debug writeln();
|
||
|
}
|
||
|
//debug writeln();
|
||
|
|
||
|
/+debug {
|
||
|
void printSpots(Spot[][] flop) {
|
||
|
foreach(row; flop) {
|
||
|
foreach(seat; row) {
|
||
|
write(seat == Spot.TAKEN ? '#' : (seat == Spot.EMPTY ? 'L' : '.'));
|
||
|
}
|
||
|
writeln();
|
||
|
}
|
||
|
}
|
||
|
printSpots(input);
|
||
|
}+/
|
||
|
} while(!prev.equal(input));
|
||
|
|
||
|
return input.joiner.count(Spot.TAKEN);
|
||
|
}
|
||
|
|
||
|
unittest {
|
||
|
import std.format;
|
||
|
string layout = q"EOS
|
||
|
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
|
||
|
EOS";
|
||
|
size_t result = parseInput(layout.lineSplitter).part2();
|
||
|
assert(result == 26, "Result is %d (expected 26)".format(result));
|
||
|
}
|
||
|
|