Compare commits
6 Commits
676006891d
...
3223948f51
Author | SHA1 | Date |
---|---|---|
Benjamin Kraft | 3223948f51 | 9 months ago |
Benjamin Kraft | 2508d4cd51 | 9 months ago |
Benjamin Kraft | df538935a5 | 9 months ago |
Benjamin Kraft | 14ff577615 | 9 months ago |
Benjamin Kraft | ee36ea57db | 9 months ago |
Benjamin Kraft | 3f65baeccb | 9 months ago |
11 changed files with 485 additions and 30 deletions
@ -1,9 +1,79 @@ |
||||
#include "Day01.h" |
||||
|
||||
Result Day01::Task1() { |
||||
return Day::Task1(); |
||||
uint32_t sum = 0; |
||||
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() { |
||||
return Day::Task2(); |
||||
uint32_t sum = 0; |
||||
|
||||
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,9 +1,65 @@ |
||||
#include "Day02.h" |
||||
|
||||
Result Day02::Task1() { |
||||
return Day::Task1(); |
||||
int r = 12; |
||||
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() { |
||||
return Day::Task2(); |
||||
uint32_t sum = 0; |
||||
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,9 +1,102 @@ |
||||
#include "Day03.h" |
||||
|
||||
Result Day03::Task1() { |
||||
return Day::Task1(); |
||||
uint32_t sum = 0; |
||||
|
||||
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() { |
||||
return Day::Task2(); |
||||
uint32_t sum = 0; |
||||
|
||||
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,9 +1,62 @@ |
||||
#include "Day04.h" |
||||
#include <cmath> |
||||
|
||||
Result Day04::Task1() { |
||||
return Day::Task1(); |
||||
uint64 sum = 0; |
||||
|
||||
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() { |
||||
return Day::Task2(); |
||||
vector<uint64> matches; |
||||
|
||||
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,9 +1,125 @@ |
||||
#include "Day05.h" |
||||
|
||||
Result Day05::Task1() { |
||||
return Day::Task1(); |
||||
auto seeds = parseSeeds(); |
||||
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() { |
||||
return Day::Task2(); |
||||
auto seeds = parseSeeds(); |
||||
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; |
||||
} |
@ -0,0 +1,47 @@ |
||||
#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