Created
December 11, 2020 18:35
-
-
Save orendon/9b829993afeca4ef69683ef7c6728ff0 to your computer and use it in GitHub Desktop.
Advent of Code 2020 - Day 11 Seating System
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <algorithm> | |
#include <fstream> | |
#include <iostream> | |
#include <string> | |
#include <vector> | |
using namespace std; | |
#define forn(i, j, n) for (int i = j; i < (int)n; i++) | |
#define forr(i, j, n) for (int i = j; i >= (int)n; i--) | |
#define fore(i, coll) for (auto i : coll) | |
#define endl '\n' | |
#define pb push_back | |
#define all(x) x.begin(), x.end() | |
typedef long long ll; | |
typedef pair<int, int> pii; | |
typedef vector<int> vi; | |
typedef vector<string> vs; | |
int count_occupied_adjacent(vs &, int, int); | |
int count_occupied_visible(vs &, int, int); | |
pii predict_seats(vs &, int, int(vs &, int, int)); | |
const char OCCUPIED = '#'; | |
const char FREE = 'L'; | |
const char FLOOR = '.'; | |
int main() { | |
ifstream fin("inputs/11.txt"); | |
int changes_count, seats_occupied; | |
vs part1_area, part2_area; | |
// inputs read (one copy for each problem part) | |
string line; | |
while (fin >> line) { | |
part1_area.pb(line); | |
part2_area.pb(line); | |
} | |
// part 1 | |
while (true) { | |
pii values = predict_seats(part1_area, 4, count_occupied_adjacent); | |
seats_occupied = values.first; | |
changes_count = values.second; | |
if (changes_count == 0) break; | |
} | |
cout << "Part 1: " << seats_occupied << endl; | |
// part 2 | |
while (true) { | |
pii values = predict_seats(part2_area, 5, count_occupied_visible); | |
seats_occupied = values.first; | |
changes_count = values.second; | |
if (changes_count == 0) break; | |
} | |
cout << "Part 2: " << seats_occupied << endl; | |
return 0; | |
} | |
pii predict_seats(vs &area, int tolerance, int validator(vs &, int, int)) { | |
int seats_occupied = 0, changes_count = 0; | |
vs grid; | |
for (auto row : area) grid.pb(row); | |
forn(row, 0, area.size()) { | |
forn(col, 0, area[0].size()) { | |
char seat = area[row][col]; | |
if (area[row][col] != FLOOR) { | |
int occupied = validator(grid, row, col); | |
if (area[row][col] == FREE and occupied == 0) seat = OCCUPIED; | |
if (area[row][col] == OCCUPIED and occupied >= tolerance) seat = FREE; | |
changes_count += area[row][col] != seat; | |
if (seat == OCCUPIED) seats_occupied++; | |
} | |
area[row][col] = seat; | |
} | |
} | |
return {seats_occupied, changes_count}; | |
} | |
// part 1 validator, search for occupied adjacent seats | |
int count_occupied_adjacent(vs &grid, int r, int c) { | |
int cnt = 0, rows = grid.size(), cols = grid[0].size(); | |
// seats above | |
if (r - 1 >= 0 && c - 1 >= 0 && grid[r - 1][c - 1] == OCCUPIED) cnt++; | |
if (r - 1 >= 0 && grid[r - 1][c] == OCCUPIED) cnt++; | |
if (r - 1 >= 0 && c + 1 < cols && grid[r - 1][c + 1] == OCCUPIED) cnt++; | |
// seats on the sides | |
if (c - 1 >= 0 && grid[r][c - 1] == OCCUPIED) cnt++; | |
if (c + 1 < cols && grid[r][c + 1] == OCCUPIED) cnt++; | |
// seats below | |
if (r + 1 < rows && c - 1 >= 0 && grid[r + 1][c - 1] == OCCUPIED) cnt++; | |
if (r + 1 < rows && grid[r + 1][c] == OCCUPIED) cnt++; | |
if (r + 1 < rows && c + 1 < cols && grid[r + 1][c + 1] == '#') cnt++; | |
return cnt; | |
} | |
// part 2 validator , search for occupied visible seats | |
int count_occupied_visible(vs &grid, int row, int col) { | |
int cnt = 0, rows = grid.size(), cols = grid[0].size(); | |
bool occupied; | |
occupied = false; // north | |
forr(i, row - 1, 0) { | |
if (grid[i][col] == OCCUPIED) occupied = true; | |
if (grid[i][col] == FREE) break; | |
} | |
cnt += occupied; | |
occupied = false; // south | |
forn(i, row + 1, rows) { | |
if (grid[i][col] == OCCUPIED) occupied = true; | |
if (grid[i][col] == FREE) break; | |
} | |
cnt += occupied; | |
occupied = false; // west (left) | |
forr(i, col - 1, 0) { | |
if (grid[row][i] == OCCUPIED) occupied = true; | |
if (grid[row][i] == FREE) break; | |
} | |
cnt += occupied; | |
occupied = false; // east (right) | |
forn(i, col + 1, cols) { | |
if (grid[row][i] == OCCUPIED) occupied = true; | |
if (grid[row][i] == FREE) break; | |
} | |
cnt += occupied; | |
occupied = false; // north west (diag1) | |
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { | |
if (grid[i][j] == OCCUPIED) occupied = true; | |
if (grid[i][j] == FREE) break; | |
} | |
cnt += occupied; | |
occupied = false; // south east (diag1) | |
for (int i = row + 1, j = col + 1; i < rows && j < cols; i++, j++) { | |
if (grid[i][j] == OCCUPIED) occupied = true; | |
if (grid[i][j] == FREE) break; | |
} | |
cnt += occupied; | |
occupied = false; // north east (diag2) | |
for (int i = row - 1, j = col + 1; i >= 0 && j < cols; i--, j++) { | |
if (grid[i][j] == OCCUPIED) occupied = true; | |
if (grid[i][j] == FREE) break; | |
} | |
cnt += occupied; | |
occupied = false; // south west (diag2) | |
for (int i = row + 1, j = col - 1; i < rows && j >= 0; i++, j--) { | |
if (grid[i][j] == OCCUPIED) occupied = true; | |
if (grid[i][j] == FREE) break; | |
} | |
cnt += occupied; | |
return cnt; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment