/**
* Copyright (c) 2020 Nicba1010 All rights reserved.
*/
#include <sys/stat.h>
#include <cstdint>
#include <ctgmath>
#include <fstream>
#include <iostream>
/**
* Use the retarded approach of loading everything into memory.
*/
#define OVERDRIVE 1
static constexpr const char* input = "../day5_bigboi3.txt";
#if 0
/**
* @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 input 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 input or
* lowerBoundDesignator/upperBoundDesignator.
*
* @return The found value.
*/
static uint64_t splitFind(uint64_t lowerBound,
uint64_t upperBound,
const std::input& 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 input, or "
"lowerBoundDesignator/upperBoundDesignator!");
}
}
return lowerBound == upperBound ? lowerBound
: throw std::runtime_error("Lower and upper bound do not "
"match, possibly wrong instruction "
"input!");
}
#endif
/**
* @brief More optimized version of splitFind.
*
* @param instructions Instructions char*.
* @param instructionsSize Instructions char* size.
* @param upperBoundDesignator Upper bound selector character.
*
* @return Calculated value.
*/
inline static uint64_t splitFindBetter(const char* instructions,
const uint64_t instructionsSize,
const char upperBoundDesignator)
{
uint64_t result = 0;
for (uint64_t iChar = 0; iChar < instructionsSize; ++iChar) {
result = ((result << 1) | (instructions[iChar] == upperBoundDesignator));
}
return result;
}
/**
* @brief Calculates the seat ID according to the following equation.
* @code row * rowSeatIdMultiplier + col @endcode
*
* @param row Seat row.
* @param col Seat column.
* @param rowSeatIdMultiplier Seat row multipliers.
*
* @return The calculated seat ID
*/
inline static uint64_t calculateSeatId(uint64_t row, uint64_t col, uint64_t rowSeatIdMultiplier)
{
return (row << rowSeatIdMultiplier) + col;
}
int main()
{
#if OVERDRIVE
struct stat stat_buf {};
stat(input, &stat_buf);
#endif
std::ifstream file(input);
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;
uint64_t colCharCount = line0.size() - rowCharCount;
const uint64_t rowSize = std::pow(2, rowCharCount);
const uint64_t colSize = std::pow(2, colCharCount);
auto seatGrid = new bool*[rowSize];
for (int iRow = 0; iRow < rowSize; ++iRow) {
seatGrid[iRow] = new bool[colSize];
}
uint64_t seatIdMax = 0;
#if OVERDRIVE
char* data = static_cast<char*>(malloc(stat_buf.st_size));
file.read(data, stat_buf.st_size);
uint64_t startRowIndex = 0;
while (startRowIndex < stat_buf.st_size) {
uint64_t row = splitFindBetter(data + startRowIndex, rowCharCount, 'B');
uint64_t col = splitFindBetter(data + startRowIndex + rowCharCount, colCharCount, 'R');
#else
char instructions[rowCharCount + colCharCount + 1];
while (file.read(reinterpret_cast<char*>(instructions), rowCharCount + colCharCount + 1)) {
uint64_t row = splitFindBetter(instructions, rowCharCount, 'B');
uint64_t col = splitFindBetter(instructions + rowCharCount, colCharCount, 'R');
#endif
uint64_t seatId = calculateSeatId(row, col, colCharCount);
seatIdMax = std::max(seatIdMax, seatId);
seatGrid[row][col] = true;
startRowIndex += rowCharCount + colCharCount + 1;
}
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][iCol - 1] && seatGrid[iRow][iCol + 1]) {
std::cout << "Your seat ID is: " << calculateSeatId(iRow, iCol, colSize)
<< std::endl;
return 0;
}
}
}
}
Comments