Skip to content

Instantly share code, notes, and snippets.

@orendon
Created December 11, 2020 18:35
Show Gist options
  • Save orendon/9b829993afeca4ef69683ef7c6728ff0 to your computer and use it in GitHub Desktop.
Save orendon/9b829993afeca4ef69683ef7c6728ff0 to your computer and use it in GitHub Desktop.
Advent of Code 2020 - Day 11 Seating System
#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