/**
* Copyright (c) 2020 Nicba1010 All rights reserved.
*/
#include <fstream>
#include <iostream>
#include <vector>
#include <ctgmath>
/**
* @brief Finds the desired value by searching through the lower and upper bound by splitting the
* search area in half every instruction.
*
* @details Finds the desired value by searching through the lower and upper bound by splitting the
* search area in half every instruction according to the following rules.<br>
* If the lowerBoundDesignator is detected it keeps the lower bound, but subtracts from
* the upper bound using the following equation.
* @code upperBound -= (upperBound - lowerBound + 1) / 2 @endcode
* If the upperBoundDesignator is detected it keeps the upper bound, but adds to the
* lower bound using the following equation.
* @code lowerBound += (upperBound - lowerBound + 1) / 2 @endcode
*
* @param lowerBound Lower bound to start searching from.
* @param upperBound Upper bound to start searching from.
* @param instructions A string of characters either lowerBoundDesignator or
* upperBoundDesignator.
* @param lowerBoundDesignator Lower bound instruction character.
* @param upperBoundDesignator Upper bound instruction character.
*
* @throws std::runtime_error in case of an invalid instruction string or
* lowerBoundDesignator/upperBoundDesignator.
*
* @return The found value.
*/
static uint64_t splitFind(uint64_t lowerBound,
uint64_t upperBound,
const std::string& instructions,
const char lowerBoundDesignator,
const char upperBoundDesignator)
{
for (uint64_t iChar = 0; iChar < instructions.size(); ++iChar) {
char c = instructions.c_str()[iChar];
if (c == lowerBoundDesignator) {
lowerBound = lowerBound;
upperBound -= (upperBound - lowerBound + 1) / 2;
} else if (c == upperBoundDesignator) {
lowerBound += (upperBound - lowerBound + 1) / 2;
upperBound = upperBound;
} else {
throw std::runtime_error("Either invalid instruction string, or "
"lowerBoundDesignator/upperBoundDesignator!");
}
}
return lowerBound == upperBound ? lowerBound
: throw std::runtime_error("Lower and upper bound do not "
"match, possibly wrong instruction "
"string!");
}
/**
* @brief More optimized version of splitFind.
*
* @param instructions Instruction string.
* @param upperBoundDesignator Upper bound selector character.
*
* @return Calculated value.
*/
static uint64_t splitFindBetter(const std::string& instructions, const char upperBoundDesignator)
{
uint64_t result = 0;
for (uint64_t iChar = 0; iChar < instructions.size(); ++iChar) {
result = ((result << 1) | (instructions.c_str()[iChar] == upperBoundDesignator));
}
return result;
}
/**
* @brief Calculates the seat ID according to the following equation.
* @code row * 8 + col @endcode
*
* @param row Seat row.
* @param col Seat column.
*
* @return The calculated seat ID
*/
static uint64_t calculateSeatId(uint64_t row, uint64_t col, uint64_t rowSeatIdMultiplier)
{
return row * rowSeatIdMultiplier + col;
}
int main()
{
std::ifstream file("../day5_bigboi3.txt");
std::vector<std::string> lines;
std::string line0;
getline(file, line0);
file.seekg(0, std::ios::beg);
uint64_t rowCharCount =
static_cast<uint64_t>(std::max(line0.find_last_of('F'), line0.find_last_of('B'))) + 1;
const uint64_t rowSize = std::pow(2, rowCharCount);
const uint64_t colSize = std::pow(2, line0.size() - rowCharCount);
auto seatGrid = new bool*[rowSize];
for (int iRow = 0; iRow < rowSize; ++iRow) {
seatGrid[iRow] = new bool[colSize];
}
uint64_t seatIdMax = 0;
std::string line;
while (getline(file, line)) {
uint64_t row = splitFindBetter(line.substr(0, rowCharCount), 'B');
uint64_t col = splitFindBetter(line.substr(rowCharCount), 'R');
uint64_t seatId = calculateSeatId(row, col, colSize);
seatIdMax = std::max(seatIdMax, seatId);
seatGrid[row][col] = true;
//#ifndef NDEBUG
// std::cout << "Row: " << row << " Column: " << col << " Seat ID: " << seatId << "\n";
//#endif
}
std::cout << "Highest seat ID is: " << seatIdMax << std::endl;
for (uint64_t iRow = 1; iRow < rowSize - 1; ++iRow) {
for (uint64_t iCol = 1; iCol < colSize - 1; ++iCol) {
if (!seatGrid[iRow][iCol] && seatGrid[iRow - 1][iCol] && seatGrid[iRow + 1][iCol] &&
seatGrid[iRow][iCol - 1] && seatGrid[iRow][iCol + 1]) {
std::cout << "Your seat ID is: " << calculateSeatId(iRow, iCol, colSize)
<< std::endl;
}
}
}
return 0;
}
Comments