284 lines
8.0 KiB
C#
284 lines
8.0 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace _2020
|
|
{
|
|
class Q11
|
|
{
|
|
static SeatState[,] list = null;
|
|
static int numRows = 0;
|
|
static int numCols = 0;
|
|
|
|
enum SeatState
|
|
{
|
|
Floor,
|
|
Empty,
|
|
Occupied,
|
|
}
|
|
|
|
public static void Go()
|
|
{
|
|
var start = DateTime.Now;
|
|
MakeList();
|
|
Util.Log($"Q11 MakeList took {(DateTime.Now - start).TotalMilliseconds}ms");
|
|
var p1start = DateTime.Now;
|
|
Part1();
|
|
Util.Log($"Q11 part1 took {(DateTime.Now - p1start).TotalMilliseconds}ms");
|
|
var p2start = DateTime.Now;
|
|
Part2();
|
|
Util.Log($"Q11 part2 took {(DateTime.Now - p2start).TotalMilliseconds}ms");
|
|
|
|
Util.Log($"Q11 took {(DateTime.Now - start).TotalMilliseconds}ms");
|
|
}
|
|
|
|
static void MakeList()
|
|
{
|
|
var lines = File.ReadAllLines("11input.txt");
|
|
numRows = lines.Length;
|
|
numCols = lines[0].Length;
|
|
|
|
list = new SeatState[numRows, numCols];
|
|
for (int i = 0; i < numRows; i++)
|
|
{
|
|
for (int j = 0; j < numCols; j++)
|
|
{
|
|
list[i, j] = lines[i][j] == '.' ? SeatState.Floor : SeatState.Empty;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int GetNumOccupiedAdjacent(SeatState[,] seatList, int row, int col)
|
|
{
|
|
int numOccupied = 0;
|
|
if (row - 1 >= 0)
|
|
{
|
|
if (col - 1 >= 0 && seatList[row - 1, col - 1] == SeatState.Occupied)
|
|
{
|
|
numOccupied++;
|
|
}
|
|
if (seatList[row - 1, col] == SeatState.Occupied)
|
|
{
|
|
numOccupied++;
|
|
}
|
|
if (col + 1 < numCols && seatList[row - 1, col + 1] == SeatState.Occupied)
|
|
{
|
|
numOccupied++;
|
|
}
|
|
}
|
|
|
|
if (col - 1 >= 0 && seatList[row, col - 1] == SeatState.Occupied)
|
|
{
|
|
numOccupied++;
|
|
}
|
|
if (col + 1 < numCols && seatList[row, col + 1] == SeatState.Occupied)
|
|
{
|
|
numOccupied++;
|
|
}
|
|
|
|
if (row + 1 < numRows)
|
|
{
|
|
if (col - 1 >= 0 && seatList[row + 1, col - 1] == SeatState.Occupied)
|
|
{
|
|
numOccupied++;
|
|
}
|
|
if (seatList[row + 1, col] == SeatState.Occupied)
|
|
{
|
|
numOccupied++;
|
|
}
|
|
if (col + 1 < numCols && seatList[row + 1, col + 1] == SeatState.Occupied)
|
|
{
|
|
numOccupied++;
|
|
}
|
|
}
|
|
|
|
return numOccupied;
|
|
}
|
|
|
|
static int GetNumOccupiedLOS(SeatState[,] seatList, int row, int col)
|
|
{
|
|
int numOccupied = 0;
|
|
|
|
bool checkSeat(int checkRow, int checkCol)
|
|
{
|
|
if (seatList[checkRow, checkCol] == SeatState.Occupied)
|
|
{
|
|
numOccupied++;
|
|
return true;
|
|
}
|
|
if (seatList[checkRow, checkCol] == SeatState.Empty)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// ul
|
|
for (int checkRow = row - 1, checkCol = col - 1; checkRow >= 0 && checkCol >= 0; checkRow--, checkCol--)
|
|
{
|
|
if (checkSeat(checkRow, checkCol))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// u
|
|
for (int checkRow = row - 1, checkCol = col; checkRow >= 0; checkRow--)
|
|
{
|
|
if (checkSeat(checkRow, checkCol))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// ur
|
|
for (int checkRow = row - 1, checkCol = col + 1; checkRow >= 0 && checkCol < numCols; checkRow--, checkCol++)
|
|
{
|
|
if (checkSeat(checkRow, checkCol))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// l
|
|
for (int checkRow = row, checkCol = col - 1; checkCol >= 0; checkCol--)
|
|
{
|
|
if (checkSeat(checkRow, checkCol))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// r
|
|
for (int checkRow = row, checkCol = col + 1; checkCol < numCols; checkCol++)
|
|
{
|
|
if (checkSeat(checkRow, checkCol))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// dl
|
|
for (int checkRow = row + 1, checkCol = col - 1; checkRow < numRows && checkCol >= 0; checkRow++, checkCol--)
|
|
{
|
|
if (checkSeat(checkRow, checkCol))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// d
|
|
for (int checkRow = row + 1, checkCol = col; checkRow < numRows; checkRow++)
|
|
{
|
|
if (checkSeat(checkRow, checkCol))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// dr
|
|
for (int checkRow = row + 1, checkCol = col + 1; checkRow < numRows && checkCol < numCols; checkRow++, checkCol++)
|
|
{
|
|
if (checkSeat(checkRow, checkCol))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return numOccupied;
|
|
}
|
|
|
|
static int GetNumOccupied(SeatState[,] currState)
|
|
{
|
|
int totalNumOccupied = 0;
|
|
for (int i = 0; i < numRows; i++)
|
|
{
|
|
for (int j = 0; j < numCols; j++)
|
|
{
|
|
if (currState[i, j] == SeatState.Occupied)
|
|
{
|
|
totalNumOccupied++;
|
|
}
|
|
}
|
|
}
|
|
return totalNumOccupied;
|
|
}
|
|
|
|
static void Part1()
|
|
{
|
|
SeatState[,] currState = new SeatState[numRows, numCols];
|
|
SeatState[,] nextState = new SeatState[numRows, numCols];
|
|
Array.Copy(list, currState, numRows * numCols);
|
|
|
|
int rounds = 0;
|
|
for (int numChanges = 0; rounds == 0 || numChanges != 0; rounds++)
|
|
{
|
|
Array.Copy(currState, nextState, numRows * numCols);
|
|
|
|
numChanges = 0;
|
|
|
|
Parallel.For(0, numRows, (i) =>
|
|
{
|
|
for (int j = 0; j < numCols; j++)
|
|
{
|
|
var numOccupied = GetNumOccupiedAdjacent(currState, i, j);
|
|
if (currState[i, j] == SeatState.Empty && numOccupied == 0)
|
|
{
|
|
nextState[i, j] = SeatState.Occupied;
|
|
Interlocked.Increment(ref numChanges);
|
|
}
|
|
else if (currState[i, j] == SeatState.Occupied && numOccupied >= 4)
|
|
{
|
|
nextState[i, j] = SeatState.Empty;
|
|
Interlocked.Increment(ref numChanges);
|
|
}
|
|
}
|
|
});
|
|
|
|
Array.Copy(nextState, currState, numRows * numCols);
|
|
}
|
|
|
|
Util.Log($"Q11Part1: stabilized after {rounds - 1} rounds, total occupied={GetNumOccupied(currState)}");
|
|
}
|
|
|
|
static void Part2()
|
|
{
|
|
SeatState[,] currState = new SeatState[numRows, numCols];
|
|
SeatState[,] nextState = new SeatState[numRows, numCols];
|
|
Array.Copy(list, currState, numRows * numCols);
|
|
|
|
int rounds = 0;
|
|
for (int numChanges = 0; rounds == 0 || numChanges != 0; rounds++)
|
|
{
|
|
Array.Copy(currState, nextState, numRows * numCols);
|
|
|
|
numChanges = 0;
|
|
|
|
Parallel.For(0, numRows, (i) =>
|
|
{
|
|
for (int j = 0; j < numCols; j++)
|
|
{
|
|
var numOccupied = GetNumOccupiedLOS(currState, i, j);
|
|
if (currState[i, j] == SeatState.Empty && numOccupied == 0)
|
|
{
|
|
nextState[i, j] = SeatState.Occupied;
|
|
Interlocked.Increment(ref numChanges);
|
|
}
|
|
else if (currState[i, j] == SeatState.Occupied && numOccupied >= 5)
|
|
{
|
|
nextState[i, j] = SeatState.Empty;
|
|
Interlocked.Increment(ref numChanges);
|
|
}
|
|
}
|
|
});
|
|
|
|
Array.Copy(nextState, currState, numRows * numCols);
|
|
}
|
|
|
|
Util.Log($"Q11Part2: stabilized after {rounds - 1} rounds, total occupied={GetNumOccupied(currState)}");
|
|
}
|
|
}
|
|
}
|