// Solutions to the Advent Of Code 2024. // Copyright (C) 2025 Stefan Müller // // This program is free software: you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software // Foundation, either version 3 of the License, or (at your option) any later // version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along with // this program. If not, see . #include const std::string DiskFragmenter::getPuzzleName() const { return "Day 9: Disk Fragmenter"; } const std::string DiskFragmenter::getInputFileName() const { return "disk_fragmenter.txt"; } void DiskFragmenter::processDataLine(const std::string& line) { //size_t maxIdNumber{ line.size() / 2 }; // Index of the first unprocessed digit in the disk map. size_t front{ 0 }; // ID number of the file 'front' refers to (when 'isFile == true'). Equivalent to 'front / 2', but calculated // incrementally. size_t frontIdNumber{ 0 }; // Index of the last unprocessed digit in the disk map. size_t back{ line.size() - 1 }; // Number of remaining fragmented blocks in the file that 'back' refers to (when 'isFile == true'). int nRemainingBackBlocks{ getDigit(line, back) }; // ID number of the file 'back' refers to (when 'isFile == true'). Equivalent to 'back / 2', but calculated // incrementally. size_t backIdNumber{ line.size() / 2 }; // Current block position. size_t position{ 0 }; bool isFile{ true }; while (front < back) { if (isFile) { // Adds the checksum for the file at 'front'. int nFileBlocks = getDigit(line, front); part1 += calcChecksumPart(frontIdNumber, nFileBlocks, position); frontIdNumber++; } else { int nFreeBlocks = getDigit(line, front); while (nFreeBlocks > 0) { if (nFreeBlocks >= nRemainingBackBlocks) { // Adds the checksum for all the blocks of the file at 'back'. part1 += calcChecksumPart(backIdNumber, nRemainingBackBlocks, position); backIdNumber--; nFreeBlocks -= nRemainingBackBlocks; back -= 2; nRemainingBackBlocks = getDigit(line, back); } else { // Adds the checksum for the blocks of the file at 'back' that fit into the empty blocks at 'front'. part1 += calcChecksumPart(backIdNumber, nFreeBlocks, position); nRemainingBackBlocks -= nFreeBlocks; nFreeBlocks = 0; } } } front++; isFile = !isFile; } // Adds the checksum for the remaining blocks of the file at 'back'. part1 += calcChecksumPart(backIdNumber, nRemainingBackBlocks, position); } void DiskFragmenter::finish() { } int DiskFragmenter::getDigit(const std::string& line, const size_t index) const { return line[index] - '0'; } long long int DiskFragmenter::calcChecksumPart(const size_t idNumber, const int nBlocks, size_t& position) const { position += nBlocks; return idNumber * ((nBlocks * (2 * position - nBlocks - 1)) / 2); }