Compare commits
No commits in common. '3223948f511f76570c2820135bb47f29a831e9a2' and '676006891dd4f589be564b076e393b03b8d6ced1' have entirely different histories.
3223948f51
...
676006891d
11 changed files with 30 additions and 485 deletions
@ -1,79 +1,9 @@ |
|||||||
#include "Day01.h" |
#include "Day01.h" |
||||||
|
|
||||||
Result Day01::Task1() { |
Result Day01::Task1() { |
||||||
uint32_t sum = 0; |
return Day::Task1(); |
||||||
for (const string& line : input){ |
|
||||||
uint8_t left = *std::find_if(line.begin(), line.end(), [](const char c){ |
|
||||||
int diff = c - '0'; |
|
||||||
return diff >= 0 && diff < 10; |
|
||||||
}) - '0'; |
|
||||||
uint8_t right = *std::find_if(std::make_reverse_iterator(line.end()), std::make_reverse_iterator(line.begin()), [](const char c){ |
|
||||||
int diff = c - '0'; |
|
||||||
return diff >= 0 && diff < 10; |
|
||||||
}) - '0'; |
|
||||||
sum += left * 10 + right; |
|
||||||
} |
|
||||||
return to_string(sum); |
|
||||||
} |
} |
||||||
|
|
||||||
Result Day01::Task2() { |
Result Day01::Task2() { |
||||||
uint32_t sum = 0; |
return Day::Task2(); |
||||||
|
|
||||||
std::map<string, char> convert = { |
|
||||||
{"one", '1'}, |
|
||||||
{"two", '2'}, |
|
||||||
{"three", '3'}, |
|
||||||
{"four", '4'}, |
|
||||||
{"five", '5'}, |
|
||||||
{"six", '6'}, |
|
||||||
{"seven", '7'}, |
|
||||||
{"eight", '8'}, |
|
||||||
{"nine", '9'}, |
|
||||||
}; |
|
||||||
|
|
||||||
for (const string &line : input){ |
|
||||||
|
|
||||||
uint8_t left = 0, right = 0; |
|
||||||
for (size_t i = 0; i < line.length(); i++){ |
|
||||||
auto current = line.substr(0, i + 1); |
|
||||||
auto diff = current.back() - '0'; |
|
||||||
if (diff > 0 && diff < 10){ |
|
||||||
left = diff; |
|
||||||
break; |
|
||||||
} |
|
||||||
bool found = false; |
|
||||||
for (const auto& [key, value] : convert){ |
|
||||||
auto pos = current.find(key); |
|
||||||
if (pos != string::npos){ |
|
||||||
left = value - '0'; |
|
||||||
found = true; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
if (found) break; |
|
||||||
} |
|
||||||
|
|
||||||
for (size_t i = 0; i < line.length(); i++){ |
|
||||||
auto current = line.substr(line.length() - i - 1); |
|
||||||
auto diff = current.front() - '0'; |
|
||||||
if (diff > 0 && diff < 10){ |
|
||||||
right = diff; |
|
||||||
break; |
|
||||||
} |
|
||||||
bool found = false; |
|
||||||
for (const auto& [key, value] : convert){ |
|
||||||
auto pos = current.find(key); |
|
||||||
if (pos != string::npos){ |
|
||||||
right = value - '0'; |
|
||||||
found = true; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
if (found) break; |
|
||||||
} |
|
||||||
|
|
||||||
sum += left * 10 + right; |
|
||||||
} |
|
||||||
|
|
||||||
return to_string(sum); |
|
||||||
} |
} |
@ -1,65 +1,9 @@ |
|||||||
#include "Day02.h" |
#include "Day02.h" |
||||||
|
|
||||||
Result Day02::Task1() { |
Result Day02::Task1() { |
||||||
int r = 12; |
return Day::Task1(); |
||||||
int g = 13; |
|
||||||
int b = 14; |
|
||||||
|
|
||||||
uint32_t sum = 0; |
|
||||||
uint32_t id = 1; |
|
||||||
for (const Game &game : parseGames()){ |
|
||||||
bool possible = true; |
|
||||||
for (const auto &set : game) |
|
||||||
if (set[0] > r || set[1] > g || set[2] > b) |
|
||||||
possible = false; |
|
||||||
if (possible) |
|
||||||
sum += id; |
|
||||||
|
|
||||||
id++; |
|
||||||
} |
|
||||||
return to_string(sum); |
|
||||||
} |
} |
||||||
|
|
||||||
Result Day02::Task2() { |
Result Day02::Task2() { |
||||||
uint32_t sum = 0; |
return Day::Task2(); |
||||||
for (const Game &game : parseGames()){ |
|
||||||
size_t r = 0, g = 0, b = 0; |
|
||||||
for (const auto &set : game){ |
|
||||||
r = std::max(r, set[0]); |
|
||||||
g = std::max(g, set[1]); |
|
||||||
b = std::max(b, set[2]); |
|
||||||
} |
|
||||||
sum += r * g * b; |
|
||||||
} |
|
||||||
return to_string(sum); |
|
||||||
} |
|
||||||
|
|
||||||
vector<Day02::Game> Day02::parseGames() const { |
|
||||||
vector<Game> games; |
|
||||||
for (const string &line : input){ |
|
||||||
auto record = line.substr(line.find(": ") + 1); |
|
||||||
record.push_back(';'); |
|
||||||
auto setIndices = findAll(record, ";"); |
|
||||||
|
|
||||||
Game game; |
|
||||||
size_t start = 0; |
|
||||||
for (size_t i : setIndices){ |
|
||||||
auto set = record.substr(start, i - start); |
|
||||||
|
|
||||||
auto findNumber = [set](const string &type) -> size_t { |
|
||||||
auto pos = set.find(type); |
|
||||||
if (pos != string::npos) |
|
||||||
return std::stoul(set.substr(pos - 3, 2)); |
|
||||||
return 0; |
|
||||||
}; |
|
||||||
size_t r = findNumber("red"); |
|
||||||
size_t g = findNumber("green"); |
|
||||||
size_t b = findNumber("blue"); |
|
||||||
|
|
||||||
game.push_back({r, g, b}); |
|
||||||
start = i; |
|
||||||
} |
|
||||||
games.push_back(game); |
|
||||||
} |
|
||||||
return games; |
|
||||||
} |
} |
@ -1,102 +1,9 @@ |
|||||||
#include "Day03.h" |
#include "Day03.h" |
||||||
|
|
||||||
Result Day03::Task1() { |
Result Day03::Task1() { |
||||||
uint32_t sum = 0; |
return Day::Task1(); |
||||||
|
|
||||||
auto isSymbol = [this](int32_t x, int32_t y) -> bool { |
|
||||||
if (x < 0 || x > input[0].length() - 1 || |
|
||||||
y < 0 || y > input.size() - 1){ |
|
||||||
return false; |
|
||||||
} |
|
||||||
char c = input[y][x]; |
|
||||||
return !isDigit(c) && c != '.'; |
|
||||||
}; |
|
||||||
|
|
||||||
for (const auto &[number, position] : parseEngineNumbers()){ |
|
||||||
auto &[value, size] = number; |
|
||||||
auto &[x, y] = position; |
|
||||||
|
|
||||||
bool symbolFound = false; |
|
||||||
for (int32_t sx = x - 1; sx < x + size + 1; sx++){ |
|
||||||
for (int32_t sy = y - 1; sy < y + 2; sy++){ |
|
||||||
if (isSymbol(sx, sy)){ |
|
||||||
symbolFound = true; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
if (symbolFound) |
|
||||||
sum += value; |
|
||||||
} |
|
||||||
|
|
||||||
return to_string(sum); |
|
||||||
} |
} |
||||||
|
|
||||||
Result Day03::Task2() { |
Result Day03::Task2() { |
||||||
uint32_t sum = 0; |
return Day::Task2(); |
||||||
|
|
||||||
map<pair<size_t, size_t>, set<EngineNumber>> stars; |
|
||||||
|
|
||||||
auto isStar = [this](int32_t x, int32_t y) -> bool { |
|
||||||
if (x < 0 || x > input[0].length() - 1 || |
|
||||||
y < 0 || y > input.size() - 1){ |
|
||||||
return false; |
|
||||||
} |
|
||||||
return input[y][x] == '*'; |
|
||||||
}; |
|
||||||
|
|
||||||
for (const auto &[number, position] : parseEngineNumbers()){ |
|
||||||
auto &[value, size] = number; |
|
||||||
auto &[x, y] = position; |
|
||||||
|
|
||||||
for (int32_t sx = x - 1; sx < x + size + 1; sx++){ |
|
||||||
for (int32_t sy = y - 1; sy < y + 2; sy++){ |
|
||||||
if (isStar(sx, sy)){ |
|
||||||
if (stars.contains({sx, sy})){ |
|
||||||
stars[{sx, sy}].insert({number, position}); |
|
||||||
} else { |
|
||||||
stars[{sx, sy}] = {{number, position}}; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
for (auto &[position, numbers] : stars){ |
|
||||||
if (numbers.size() == 2){ |
|
||||||
sum += numbers.begin()->first.first * (++numbers.begin())->first.first; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return to_string(sum); |
|
||||||
} |
|
||||||
|
|
||||||
vector<Day03::EngineNumber> Day03::parseEngineNumbers() const { |
|
||||||
vector<EngineNumber> numbers; |
|
||||||
|
|
||||||
for (size_t y = 0; y < input.size(); y++){ |
|
||||||
const string& line = input[y]; |
|
||||||
uint32_t value = 0; |
|
||||||
uint8_t valueLength = 0; |
|
||||||
bool readingValue = false; |
|
||||||
|
|
||||||
for (size_t x = 0; x < line.length(); x++){ |
|
||||||
uint8_t digit; |
|
||||||
if (isDigit(line[x], digit)){ |
|
||||||
value = value * 10 + digit; |
|
||||||
valueLength++; |
|
||||||
readingValue = true; |
|
||||||
if (x == line.length() - 1) |
|
||||||
numbers.push_back({{value, valueLength}, {x - valueLength, y}}); |
|
||||||
} else { |
|
||||||
if (readingValue) |
|
||||||
numbers.push_back({{value, valueLength}, {x - valueLength, y}}); |
|
||||||
readingValue = false; |
|
||||||
valueLength = 0; |
|
||||||
value = 0; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return numbers; |
|
||||||
} |
} |
@ -1,62 +1,9 @@ |
|||||||
#include "Day04.h" |
#include "Day04.h" |
||||||
#include <cmath> |
|
||||||
|
|
||||||
Result Day04::Task1() { |
Result Day04::Task1() { |
||||||
uint64 sum = 0; |
return Day::Task1(); |
||||||
|
|
||||||
for (const auto &[winning, having] : parseCards()){ |
|
||||||
std::set<uint8_t> result; |
|
||||||
std::set_intersection(winning.begin(), winning.end(), having.begin(), having.end(), std::inserter(result, result.begin())); |
|
||||||
if (!result.empty()){ |
|
||||||
sum += uint64(powl(2, result.size() - 1)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return to_string(sum); |
|
||||||
} |
} |
||||||
|
|
||||||
Result Day04::Task2() { |
Result Day04::Task2() { |
||||||
vector<uint64> matches; |
return Day::Task2(); |
||||||
|
|
||||||
for (const auto &[winning, having] : parseCards()){ |
|
||||||
std::set<uint8_t> result; |
|
||||||
std::set_intersection(winning.begin(), winning.end(), having.begin(), having.end(), std::inserter(result, result.begin())); |
|
||||||
matches.push_back(result.size()); |
|
||||||
} |
|
||||||
|
|
||||||
vector<uint64> counts(matches.size(), 1); |
|
||||||
|
|
||||||
for (size_t i = 0; i < matches.size(); i++){ |
|
||||||
for (size_t instance = 0; instance < counts[i]; instance++){ |
|
||||||
for (size_t k = 0; k < matches[i]; k++){ |
|
||||||
counts[i + k + 1]++; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
uint64 sum = std::reduce(counts.begin(), counts.end(), 0, [](uint64 a, uint64 b){return a + b;}); |
|
||||||
|
|
||||||
return to_string(sum); |
|
||||||
} |
|
||||||
|
|
||||||
vector<Day04::Card> Day04::parseCards() const { |
|
||||||
vector<Card> cards; |
|
||||||
|
|
||||||
for (string line : input){ |
|
||||||
line = line.substr(line.find(':') + 1); |
|
||||||
string left = line.substr(0, line.find(" |")); |
|
||||||
string right = line.substr(line.find(" |") + 2); |
|
||||||
|
|
||||||
set<uint8_t> winning; |
|
||||||
for (size_t i = 0; i < left.length(); i += 3) |
|
||||||
winning.insert(std::stoul(left.substr(i, 3))); |
|
||||||
|
|
||||||
set<uint8_t> having; |
|
||||||
for (size_t i = 0; i < right.length(); i += 3) |
|
||||||
having.insert(std::stoul(right.substr(i, 3))); |
|
||||||
|
|
||||||
cards.emplace_back(winning, having); |
|
||||||
} |
|
||||||
|
|
||||||
return cards; |
|
||||||
} |
} |
@ -1,125 +1,9 @@ |
|||||||
#include "Day05.h" |
#include "Day05.h" |
||||||
|
|
||||||
Result Day05::Task1() { |
Result Day05::Task1() { |
||||||
auto seeds = parseSeeds(); |
return Day::Task1(); |
||||||
auto maps = parseMaps(); |
|
||||||
|
|
||||||
uint64 min = UINT64_MAX; |
|
||||||
|
|
||||||
for (uint64 seed : seeds){ |
|
||||||
uint64 result = seed; |
|
||||||
for (const Map &map : maps) |
|
||||||
result = map.get(result); |
|
||||||
min = std::min(min, result); |
|
||||||
} |
|
||||||
|
|
||||||
return to_string(min); |
|
||||||
} |
} |
||||||
|
|
||||||
Result Day05::Task2() { |
Result Day05::Task2() { |
||||||
auto seeds = parseSeeds(); |
return Day::Task2(); |
||||||
auto maps = parseMaps(); |
|
||||||
|
|
||||||
uint64 min = UINT64_MAX; |
|
||||||
|
|
||||||
for (size_t i = 0; i < seeds.size(); i += 2){ |
|
||||||
vector<Range> resultRanges {Range(seeds[i], seeds[i] + seeds[i + 1] - 1)}; |
|
||||||
for (const Map &map : maps){ |
|
||||||
vector<Range> newRanges; |
|
||||||
for (const Range &range : resultRanges) { |
|
||||||
auto add = map.get(range); |
|
||||||
std::copy(add.begin(), add.end(), std::back_inserter(newRanges)); |
|
||||||
} |
|
||||||
resultRanges = newRanges; |
|
||||||
} |
|
||||||
for (const Range &range : resultRanges) |
|
||||||
min = std::min(min, range.start); |
|
||||||
} |
|
||||||
|
|
||||||
return to_string(min); |
|
||||||
} |
|
||||||
|
|
||||||
vector<uint64> Day05::parseSeeds() const { |
|
||||||
vector<uint64> seeds; |
|
||||||
auto list = (input[0] + " ").substr(7); |
|
||||||
size_t start = 0; |
|
||||||
for (size_t i : findAll(list, " ")){ |
|
||||||
seeds.push_back(std::stoul(list.substr(start, i - start))); |
|
||||||
start = i; |
|
||||||
} |
|
||||||
|
|
||||||
return seeds; |
|
||||||
} |
|
||||||
|
|
||||||
std::array<Day05::Map, 7> Day05::parseMaps() const { |
|
||||||
std::array<Map, 7> maps; |
|
||||||
|
|
||||||
size_t map = 0; |
|
||||||
|
|
||||||
for (size_t i = 3; i < input.size(); i++){ |
|
||||||
string line = input[i]; |
|
||||||
if (line.empty()){ |
|
||||||
i++; |
|
||||||
map++; |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
vector<string> values = split(line, ' '); |
|
||||||
maps[map].mappings.insert(Mapping(std::stoul(values[0]), std::stoul(values[1]), std::stoul(values[2]))); |
|
||||||
} |
|
||||||
|
|
||||||
return maps; |
|
||||||
} |
|
||||||
|
|
||||||
uint64 Day05::Mapping::get(uint64 src) const { |
|
||||||
return src - source + destination; |
|
||||||
} |
|
||||||
|
|
||||||
Day05::Range Day05::Mapping::get(Day05::Range src) const { |
|
||||||
if (containsKey(src.start) && containsKey(src.end)) |
|
||||||
return Range(get(src.start), get(src.end)); |
|
||||||
if (containsKey(src.start)) |
|
||||||
return Range(get(src.start), get(source + range - 1)); |
|
||||||
if (containsKey(src.end)) |
|
||||||
return Range(get(source), get(src.end)); |
|
||||||
return Range(get(source), get(source + range - 1)); |
|
||||||
} |
|
||||||
|
|
||||||
bool Day05::Mapping::touchesRange(Day05::Range src) const { |
|
||||||
return !(src.end < source || src.start > source + range - 1); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
uint64 Day05::Map::get(uint64 src) const { |
|
||||||
for (const Mapping &mapping : mappings) |
|
||||||
if (mapping.containsKey(src)) |
|
||||||
return mapping.get(src); |
|
||||||
return src; |
|
||||||
} |
|
||||||
|
|
||||||
vector<Day05::Range> Day05::Map::get(Day05::Range src) const { |
|
||||||
vector<Range> ranges; |
|
||||||
|
|
||||||
uint64 minSource = mappings.begin()->source; |
|
||||||
uint64 maxSource = (--mappings.end())->source + (--mappings.end())->range - 1; |
|
||||||
if (src.end < minSource || src.start > maxSource) |
|
||||||
return {src}; |
|
||||||
if (src.start < minSource) |
|
||||||
ranges.emplace_back(src.start, minSource - 1); |
|
||||||
if (src.end > maxSource) |
|
||||||
ranges.emplace_back(maxSource + 1, src.end); |
|
||||||
|
|
||||||
for (const Mapping &mapping : mappings) |
|
||||||
if (mapping.touchesRange(src)) |
|
||||||
ranges.emplace_back(mapping.get(src)); |
|
||||||
|
|
||||||
return ranges; |
|
||||||
} |
|
||||||
|
|
||||||
bool Day05::Mapping::containsKey(uint64 src) const { |
|
||||||
return src >= source && src < source + range; |
|
||||||
} |
|
||||||
|
|
||||||
bool Day05::Mapping::operator<(const Day05::Mapping &other) const { |
|
||||||
return source < other.source; |
|
||||||
} |
} |
@ -1,47 +0,0 @@ |
|||||||
#include "util.h" |
|
||||||
|
|
||||||
vector<size_t> findAll(const string& data, const string& toSearch){ |
|
||||||
vector<size_t> indices; |
|
||||||
|
|
||||||
size_t pos = data.find(toSearch); |
|
||||||
|
|
||||||
while (pos != string::npos){ |
|
||||||
indices.push_back(pos); |
|
||||||
|
|
||||||
pos = data.find(toSearch, pos + toSearch.size()); |
|
||||||
} |
|
||||||
|
|
||||||
return indices; |
|
||||||
} |
|
||||||
|
|
||||||
void removeAll(string& data, const string& toRemove) { |
|
||||||
vector<size_t> indices = findAll(data, toRemove); |
|
||||||
std::sort(indices.rbegin(), indices.rend()); |
|
||||||
for (size_t &i : indices) |
|
||||||
data.erase(i, toRemove.size()); |
|
||||||
} |
|
||||||
|
|
||||||
vector<string> split(const string& data, const char c){ |
|
||||||
vector<string> parts; |
|
||||||
size_t start = 0; |
|
||||||
for (size_t i : findAll(data, std::string(1, c))){ |
|
||||||
parts.push_back(data.substr(start, i - start)); |
|
||||||
start = i + 1; |
|
||||||
} |
|
||||||
parts.push_back(data.substr(start)); |
|
||||||
return parts; |
|
||||||
} |
|
||||||
|
|
||||||
bool isDigit(char c, uint8_t& result){ |
|
||||||
auto val = c - '0'; |
|
||||||
if (val >= 0 && val < 10){ |
|
||||||
result = val; |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
bool isDigit(char c){ |
|
||||||
auto val = c - '0'; |
|
||||||
return val >= 0 && val < 10; |
|
||||||
} |
|
Loading…
Reference in new issue