Nicba1010 icon

Day5v3

Nicba1010 | PRO | 12/05/20 03:47:57 PM UTC | 0 ⭐ | 995 👁️ | Never ⏰ | []
C++ |

6.16 KB

|

None

|

0 👍

/

0 👎

/**
 * 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