Compare commits
No commits in common. "main" and "2023" have entirely different histories.
19 changed files with 1475 additions and 2400 deletions
8
01/.gitignore
vendored
8
01/.gitignore
vendored
|
@ -1,9 +1,3 @@
|
|||
# ClangD
|
||||
.cache
|
||||
|
||||
# Nix files
|
||||
.direnv
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
|
@ -74,8 +68,6 @@ compile_commands.json
|
|||
CTestTestfile.cmake
|
||||
_deps
|
||||
build/
|
||||
output/
|
||||
|
||||
lib/
|
||||
bin/
|
||||
*.swp
|
||||
|
|
157
01/README.md
157
01/README.md
|
@ -1,138 +1,55 @@
|
|||
# Day 1: Historian Hysteria
|
||||
# Day 1
|
||||
[link](https://adventofcode.com/2023/day/1)
|
||||
|
||||
[https://adventofcode.com/2024/day/1](https://adventofcode.com/2024/day/1)
|
||||
## Assignment
|
||||
|
||||
## Description
|
||||
### Day 1: Trebuchet?!
|
||||
|
||||
### Part One
|
||||
Something is wrong with global snow production,
|
||||
and you've been selected to take a look.
|
||||
The Elves have even given you a map;
|
||||
on it, they've used stars to mark the top fifty locations
|
||||
that are likely to be having problems.
|
||||
|
||||
#### Intro
|
||||
|
||||
The _Chief Historian_ is always present for the big Christmas sleigh launch,
|
||||
but nobody has seen him in months!
|
||||
Last anyone heard, he was visiting locations that are historically significant to the North Pole;
|
||||
a group of Senior Historians has asked you to accompany them as they check the
|
||||
places they think he was most likely to visit.
|
||||
|
||||
As each location is checked, they will mark it on their list with a _star_.
|
||||
They figure the Chief Historian _must_ be in one of the first fifty places they'll look,
|
||||
so in order to save Christmas, you need to help them get _fifty stars_ on their
|
||||
list before Santa takes off on December 25th.
|
||||
You've been doing this long enough to know that to restore snow operations,
|
||||
you need to check all fifty stars by December 25th.
|
||||
|
||||
Collect stars by solving puzzles.
|
||||
Two puzzles will be made available on each day in the Advent calendar;
|
||||
the second puzzle is unlocked when you complete the first.
|
||||
Each puzzle grants _one star_. Good luck!
|
||||
Each puzzle grants one star. Good luck!
|
||||
|
||||
#### Assignment
|
||||
You try to ask why they can't just use a weather machine ("not powerful enough")
|
||||
and where they're even sending you ("the sky") and why your map looks mostly blank
|
||||
("you sure ask a lot of questions") and hang on did you just say the sky
|
||||
("of course, where do you think snow comes from") when you realize
|
||||
that the Elves are already loading you into a trebuchet
|
||||
("please hold still, we need to strap you in").
|
||||
|
||||
You haven't even left yet and the group of Elvish Senior Historians has already hit a problem:
|
||||
their list of locations to check is currently _empty_.
|
||||
Eventually, someone decides that the best place to check first would be the Chief Historian's office.
|
||||
As they're making the final adjustments,
|
||||
they discover that their calibration document (your puzzle input)
|
||||
has been amended by a very young Elf who was apparently just excited to show off
|
||||
her art skills.
|
||||
Consequently, the Elves are having trouble reading the values on the document.
|
||||
|
||||
Upon pouring into the office, everyone confirms that the Chief Historian is
|
||||
ndeed nowhere to be found. Instead, the Elves discover an assortment of notes and
|
||||
lists of historically significant locations!
|
||||
his seems to be the planning the Chief Historian was doing before he left.
|
||||
Perhaps these notes can be used to determine which locations to search?
|
||||
|
||||
Throughout the Chief's office, the historically significant locations are listed
|
||||
not by name but by a unique number called the _location ID_.
|
||||
To make sure they don't miss anything, The Historians split into two groups,
|
||||
each searching the office and trying to create their own complete list of location IDs.
|
||||
|
||||
There's just one problem: by holding the two lists up _side by side_ (your puzzle input),
|
||||
it quickly becomes clear that the lists aren't very similar.
|
||||
Maybe you can help The Historians reconcile their lists?
|
||||
The newly-improved calibration document consists of lines of text;
|
||||
each line originally contained a specific calibration value
|
||||
that the Elves now need to recover.
|
||||
**On each line, the calibration value can be found by combining the first digit
|
||||
and the last digit (in that order) to form a single two-digit number.**
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
3 4
|
||||
4 3
|
||||
2 5
|
||||
1 3
|
||||
3 9
|
||||
3 3
|
||||
```example
|
||||
1abc2
|
||||
pqr3stu8vwx
|
||||
a1b2c3d4e5f
|
||||
treb7uchet
|
||||
```
|
||||
|
||||
In this example, the calibration values of these four lines are 12, 38, 15, and 77.
|
||||
Adding these together produces 142.
|
||||
|
||||
Maybe the lists are only off by a small amount!
|
||||
To find out, pair up the numbers and measure how far apart they are.
|
||||
Pair up the _smallest number in the left list_ with the _smallest number in the right list_,
|
||||
then the _second-smallest left number_ with the _second-smallest right number_, and so on.
|
||||
Consider your entire calibration document.
|
||||
What is the sum of all of the calibration values?
|
||||
|
||||
Within each pair, figure out _how far apart_ the two numbers are; you'll need to
|
||||
_add up all of those distances_.
|
||||
For example, if you pair up a `3` from the left list with a `7` from the right list,
|
||||
the distance apart is `4`; if you pair up a `9` with a `3`, the distance apart is `6`.
|
||||
|
||||
In the example list above, the pairs and distances would be as follows:
|
||||
|
||||
- The smallest number in the left list is `1`, and the smallest number in the right list is `3`.
|
||||
The distance between them is _`2`_.
|
||||
- The second-smallest number in the left list is `2`,
|
||||
and the second-smallest number in the right list is another `3`.
|
||||
The distance between them is _`1`_.
|
||||
- The third-smallest number in both lists is `3`, so the distance between them is _`0`_.
|
||||
- The next numbers to pair up are `3` and `4`, a distance of _`1`_.
|
||||
- The fifth-smallest numbers in each list are `3` and `5`, a distance of _`2`_.
|
||||
- Finally, the largest number in the left list is `4`,
|
||||
while the largest number in the right list is `9`; these are a distance _`5`_ apart.
|
||||
|
||||
To find the _total distance_ between the left list and the right list,
|
||||
add up the distances between all of the pairs you found.
|
||||
In the example above, this is `2 + 1 + 0 + 1 + 2 + 5`, a total distance of _`11`_!
|
||||
|
||||
Your actual left and right lists contain many location IDs.
|
||||
_What is the total distance between your lists?_
|
||||
|
||||
### Part Two
|
||||
|
||||
Your analysis only confirmed what everyone feared:
|
||||
the two lists of location IDs are indeed very different.
|
||||
|
||||
Or are they?
|
||||
|
||||
The Historians can't agree on which group made the mistakes _or_
|
||||
how to read most of the Chief's handwriting, but in the commotion you notice
|
||||
an interesting detail:
|
||||
<span title="We were THIS close to summoning the Alot of Location IDs!">a lot</span>
|
||||
of location IDs appear in both lists!
|
||||
Maybe the other numbers aren't location IDs at all but rather misinterpreted handwriting.
|
||||
|
||||
This time, you'll need to figure out exactly how often each number from the left
|
||||
list appears in the right list. Calculate a total _similarity score_
|
||||
by adding up each number in the left list after multiplying it by the number
|
||||
of times that number appears in the right list.
|
||||
|
||||
Here are the same example lists again:
|
||||
|
||||
```
|
||||
3 4
|
||||
4 3
|
||||
2 5
|
||||
1 3
|
||||
3 9
|
||||
3 3
|
||||
```
|
||||
|
||||
For these example lists, here is the process of finding the similarity score:
|
||||
|
||||
- The first number in the left list is `3`.
|
||||
It appears in the right list three times, so the similarity score increases by `3 * 3 = 9`.
|
||||
- The second number in the left list is `4`.
|
||||
It appears in the right list once, so the similarity score increases by `4 * 1 = 4`.
|
||||
- The third number in the left list is `2`.
|
||||
It does not appear in the right list, so the similarity score does not increase (`2 * 0 = 0`).
|
||||
- The fourth number, `1`,
|
||||
also does not appear in the right list.
|
||||
- The fifth number, `3`,
|
||||
appears in the right list three times; the similarity score increases by _`9`_.
|
||||
- The last number, `3`,
|
||||
appears in the right list three times; the similarity score again increases by _`9`_.
|
||||
|
||||
So, for these example lists, the similarity score at the end of this process
|
||||
is _`31`_ (`9 + 4 + 0 + 0 + 9 + 9`).
|
||||
|
||||
Once again consider your left and right lists. _What is their similarity score?_
|
||||
|
|
|
@ -42,7 +42,7 @@ DOXYFILE_ENCODING = UTF-8
|
|||
# title of most generated pages and in a few other places.
|
||||
# The default value is: My Project.
|
||||
|
||||
PROJECT_NAME = AdventOfCode
|
||||
PROJECT_NAME = AdventOfCode-01
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
|
|
2001
01/puzzle.input
2001
01/puzzle.input
File diff suppressed because it is too large
Load diff
145
01/src/main.c
145
01/src/main.c
|
@ -1,35 +1,81 @@
|
|||
/**
|
||||
* Copyright [2024] Jiří Štefka <jiriks74>
|
||||
* Copyright [2023] Jiří Štefka <jiriks74>
|
||||
* Project: AdventOfCode
|
||||
* @file main.c
|
||||
* @brief Main entry point
|
||||
* @author jiriks74
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define INC_CHUNK = 64
|
||||
/**
|
||||
* @brief Gets the first number in a string
|
||||
* param String where you want to find the number
|
||||
* return The first number found (or -1 if none found)
|
||||
* Gets the first number in a string. Can find numbers written as digits and
|
||||
* words.
|
||||
*/
|
||||
int getNum(const char *line) {
|
||||
char *str = (char *)line;
|
||||
// Mapping of words to numeric representations
|
||||
const char *numbers[] = {"zero", "one", "two", "three", "four",
|
||||
"five", "six", "seven", "eight", "nine"};
|
||||
const char *digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
|
||||
|
||||
int compareInt(const void *a, const void *b) {
|
||||
int int_a = *((int *)a);
|
||||
int int_b = *((int *)b);
|
||||
return int_a < int_b ? -1 : int_a == int_b ? 0 : 1;
|
||||
// Find first written number
|
||||
char *smallestPos = strchr(str, *"\0");
|
||||
int numAtSmallPos = -1;
|
||||
for (int i = 0; i < sizeof(numbers) / sizeof(numbers[0]); i++) {
|
||||
char *pos = NULL;
|
||||
|
||||
char *written = strstr(str, numbers[i]);
|
||||
char *digit = strstr(str, digits[i]);
|
||||
|
||||
if (written == NULL && digit == NULL)
|
||||
continue;
|
||||
if (written == NULL)
|
||||
pos = digit;
|
||||
else if (digit == NULL)
|
||||
pos = written;
|
||||
else
|
||||
pos = digit < written ? digit : written;
|
||||
|
||||
if (pos < smallestPos) {
|
||||
numAtSmallPos = i;
|
||||
smallestPos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
// Chen which was first and return it
|
||||
return numAtSmallPos;
|
||||
}
|
||||
|
||||
int compare(const void *a, const void *b) {
|
||||
int int_a = *((int *)a);
|
||||
int int_b = *((int *)b);
|
||||
|
||||
if (int_a == int_b)
|
||||
return 0;
|
||||
else if (int_a < int_b)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
/**
|
||||
* @brief Gets a calibration value from a line
|
||||
* @param char* line containing the calibration value
|
||||
* @return int the calibration value
|
||||
*/
|
||||
int getVal(const char *str) {
|
||||
int result = 0;
|
||||
int result2 = -1;
|
||||
for (int i = 0; i < strlen(str); i++) {
|
||||
int num = getNum(&str[i]);
|
||||
if (num >= 0) {
|
||||
if (result == 0) {
|
||||
result = num * 10;
|
||||
} else {
|
||||
result2 = num;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result2 == -1) {
|
||||
result += result / 10;
|
||||
} else {
|
||||
result += result2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,21 +83,20 @@ int compare(const void *a, const void *b) {
|
|||
* @param argc Number of command-line arguments.
|
||||
* @param argv Array of command-line arguments.
|
||||
*/
|
||||
#ifndef TESTING
|
||||
#ifdef TESTING
|
||||
int mainTest(FILE *stdin, int argc, char *argv[])
|
||||
#else
|
||||
int main(int argc, char *argv[])
|
||||
#endif
|
||||
#ifdef TESTING
|
||||
int main_test(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
|
||||
FILE *file;
|
||||
if (argc == 1) {
|
||||
file = stdin;
|
||||
} else {
|
||||
file = fopen(argv[1], "r");
|
||||
file = fopen(argv[1], "r"); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START
|
||||
if (file == NULL) {
|
||||
if (argc > 1)
|
||||
fprintf(stderr, "Could not open file '%s'\n", argv[1]);
|
||||
|
@ -59,51 +104,19 @@ int main(int argc, char *argv[])
|
|||
fprintf(stderr, "Couldn't open file\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
char *buffer = NULL;
|
||||
size_t bufferSize = 0;
|
||||
uint lines = 0;
|
||||
while (getline(&buffer, &bufferSize, file) != -1) {
|
||||
lines++;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read = 0;
|
||||
int result = 0;
|
||||
while ((read = getline(&line, &len, file) != -1)) {
|
||||
result += getVal(line);
|
||||
}
|
||||
|
||||
int array1[lines];
|
||||
int array2[lines];
|
||||
|
||||
rewind(file);
|
||||
|
||||
for (uint i = 0; i < lines; i++) {
|
||||
if (getline(&buffer, &bufferSize, file) == -1)
|
||||
break;
|
||||
|
||||
if(strcmp(buffer, "")) continue;
|
||||
|
||||
sscanf(buffer, "%d %d", &array1[i], &array2[i]);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
bufferSize = 0;
|
||||
free(line);
|
||||
fclose(file);
|
||||
|
||||
qsort(array1, lines, sizeof(int), compareInt);
|
||||
qsort(array2, lines, sizeof(int), compareInt);
|
||||
|
||||
uint distanceSum = 0;
|
||||
for(uint i = 0; i < lines; i++){
|
||||
distanceSum += array1[i] < array2[i] ? array2[i] - array1[i] : array1[i] - array2[i];
|
||||
}
|
||||
|
||||
uint reoccuranceSum = 0;
|
||||
for(uint i = 0; i < lines; i++){
|
||||
uint reoccurance = 0;
|
||||
for(uint j = 0; j < lines; j++){
|
||||
if(array1[i] == array2[j]) reoccurance++;
|
||||
}
|
||||
reoccuranceSum += array1[i] * reoccurance;
|
||||
}
|
||||
|
||||
printf("The distance between my lists is %d\n", distanceSum);
|
||||
printf("The simmilarity score is %d\n", reoccuranceSum);
|
||||
|
||||
return 0;
|
||||
printf("The sum of the calibration values is %d\n", result);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
3 4
|
||||
4 3
|
||||
2 5
|
||||
1 3
|
||||
3 9
|
||||
3 3
|
|
@ -1,31 +1,81 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include <gtest/gtest.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#define TESTING
|
||||
|
||||
// Include the source file(s) to be tested.
|
||||
#include "main.c"
|
||||
|
||||
// Create a test fixture class template - this will be like a "conlection" of
|
||||
// tests. the : public ::testing::Test part is important! Add it to your fixture
|
||||
// class.
|
||||
class HelloTest : public ::testing::Test {
|
||||
HelloTest() {}
|
||||
void stream_add(FILE *stream, std::string string) {
|
||||
fprintf(stream, "%s", string.c_str());
|
||||
fseek(stream, -string.length(), SEEK_CUR);
|
||||
}
|
||||
|
||||
~HelloTest() {}
|
||||
class Trebuchet : public ::testing::Test {
|
||||
public:
|
||||
FILE *input;
|
||||
|
||||
void SetUp() {}
|
||||
Trebuchet() {}
|
||||
|
||||
~Trebuchet() {}
|
||||
|
||||
void SetUp() {
|
||||
input = tmpfile();
|
||||
if (input == NULL) {
|
||||
fprintf(stderr, "Error creating tmpfile\n");
|
||||
fprintf(stderr, "Error: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
};
|
||||
|
||||
// Add tests to the test fixture class.
|
||||
// @param fixture_class_name The name of the test fixture class.
|
||||
// @param test_name The name of the test.
|
||||
TEST(HelloTest, BasicAssertions) {
|
||||
// Execute the code to be tested.
|
||||
// Expect two strings not to be equal.
|
||||
EXPECT_STRNE("hello", "world");
|
||||
// Expect equality.
|
||||
EXPECT_EQ(7 * 6, 42);
|
||||
TEST_F(Trebuchet, AssignmentInput) {
|
||||
testing::internal::CaptureStdout();
|
||||
stream_add(input, "1abc2\npqr3stu8vwx\na1b2c3d4e5f\ntreb7uchet");
|
||||
char *argv[2];
|
||||
mainTest(input, 1, argv);
|
||||
std::string output = testing::internal::GetCapturedStdout();
|
||||
// Check the output of the program.
|
||||
EXPECT_EQ("The sum of the calibration values is 142\n", output);
|
||||
}
|
||||
|
||||
TEST_F(Trebuchet, AssignmentInput2){
|
||||
testing::internal::CaptureStdout();
|
||||
stream_add(input, "two1nine\neightwothree\nabcone2threexyz\nxtwone3four\n4nineeightseven2\nzoneight234\n7pqrstsixteen");
|
||||
char *argv[2];
|
||||
mainTest(input, 1, argv);
|
||||
std::string output = testing::internal::GetCapturedStdout();
|
||||
// Check the output of the program.
|
||||
EXPECT_EQ("The sum of the calibration values is 281\n", output);
|
||||
}
|
||||
|
||||
TEST_F(Trebuchet, getVal) {
|
||||
EXPECT_EQ(12, getVal((char *)"1abc2"));
|
||||
EXPECT_EQ(38, getVal((char *)"pqr3stu8vwx"));
|
||||
EXPECT_EQ(15, getVal((char *)"a1b2c3d4e5f"));
|
||||
EXPECT_EQ(77, getVal((char *)"treb7uchet"));
|
||||
EXPECT_EQ(11, getVal((char *)"1"));
|
||||
}
|
||||
|
||||
TEST_F(Trebuchet, getNum) {
|
||||
EXPECT_EQ(0, getNum((char *)"zero"));
|
||||
EXPECT_EQ(1, getNum((char *)"one"));
|
||||
EXPECT_EQ(2, getNum((char *)"two"));
|
||||
EXPECT_EQ(3, getNum((char *)"three"));
|
||||
EXPECT_EQ(4, getNum((char *)"four"));
|
||||
EXPECT_EQ(5, getNum((char *)"five"));
|
||||
EXPECT_EQ(6, getNum((char *)"six"));
|
||||
EXPECT_EQ(7, getNum((char *)"seven"));
|
||||
EXPECT_EQ(8, getNum((char *)"eight"));
|
||||
EXPECT_EQ(9, getNum((char *)"nine"));
|
||||
|
||||
EXPECT_EQ(1, getNum((char *)"1"));
|
||||
EXPECT_EQ(1, getNum((char *)"one"));
|
||||
EXPECT_EQ(1, getNum((char *)"1two"));
|
||||
EXPECT_EQ(2, getNum((char *)"two1"));
|
||||
|
||||
EXPECT_EQ(1, getNum((char *)"1threeone"));
|
||||
}
|
||||
|
|
30
02/.gitignore
vendored
30
02/.gitignore
vendored
|
@ -4,6 +4,12 @@
|
|||
# Nix files
|
||||
.direnv
|
||||
|
||||
# Output folders
|
||||
output/
|
||||
|
||||
# Vimspector
|
||||
# .vimspector.json
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
|
@ -56,27 +62,3 @@ modules.order
|
|||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
# Vscode
|
||||
.vscode/
|
||||
|
||||
# CMake
|
||||
CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
.cache/
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
build/
|
||||
output/
|
||||
|
||||
lib/
|
||||
bin/
|
||||
*.swp
|
||||
|
||||
|
|
66
02/README.md
Normal file
66
02/README.md
Normal file
|
@ -0,0 +1,66 @@
|
|||
# Day 2
|
||||
[link](https://adventofcode.com/2023/day/2)
|
||||
|
||||
## Assignment
|
||||
|
||||
### Day 2: Cube Conundrum
|
||||
|
||||
You're launched high into the atmosphere!
|
||||
The apex of your trajectory just barely reaches the surface of a large island
|
||||
floating in the sky.
|
||||
You gently land in a fluffy pile of leaves.
|
||||
It's quite cold, but you don't see much snow.
|
||||
An Elf runs over to greet you.
|
||||
|
||||
The Elf explains that you've arrived
|
||||
at Snow Island and apologizes for the lack of snow.
|
||||
He'll be happy to explain the situation, but it's a bit of a walk,
|
||||
so you have some time.
|
||||
They don't get many visitors up here; would you like to play a game in the meantime?
|
||||
|
||||
As you walk, the Elf shows you a small bag and some cubes which are either red,
|
||||
green, or blue.
|
||||
Each time you play this game,
|
||||
he will hide a secret number of cubes of each color in the bag,
|
||||
and your goal is to figure out information about the number of cubes.
|
||||
|
||||
To get information, once a bag has been loaded with cubes,
|
||||
the Elf will reach into the bag, grab a handful of random cubes,
|
||||
show them to you, and then put them back in the bag.
|
||||
He'll do this a few times per game.
|
||||
|
||||
You play several games and record the information from each game (your puzzle input).
|
||||
Each game is listed with its ID number (like the 11 in Game 11: ...)
|
||||
followed by a semicolon-separated list of subsets of cubes that were revealed
|
||||
from the bag (like 3 red, 5 green, 4 blue).
|
||||
|
||||
For example, the record of a few games might look like this:
|
||||
|
||||
```example
|
||||
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
|
||||
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
|
||||
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
|
||||
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
|
||||
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
|
||||
```
|
||||
|
||||
In game 1, three sets of cubes are revealed from the bag (and then put back again).
|
||||
The first set is 3 blue cubes and 4 red cubes;
|
||||
the second set is 1 red cube, 2 green cubes, and 6 blue cubes;
|
||||
the third set is only 2 green cubes.
|
||||
|
||||
The Elf would first like to know which games would have been possible
|
||||
if the bag contained only 12 red cubes, 13 green cubes, and 14 blue cubes?
|
||||
|
||||
In the example above, games 1, 2, and 5 would have been possible
|
||||
if the bag had been loaded with that configuration.
|
||||
However, game 3 would have been impossible because at one point
|
||||
the Elf showed you 20 red cubes at once;
|
||||
similarly, game 4 would also have been impossible because the Elf
|
||||
showed you 15 blue cubes at once.
|
||||
If you add up the IDs of the games that would have been possible, you get 8.
|
||||
|
||||
Determine which games would have been possible
|
||||
if the bag had been loaded with only 12 red cubes, 13 green cubes, and 14 blue cubes.
|
||||
What is the sum of the IDs of those games?
|
||||
|
|
@ -42,7 +42,7 @@ DOXYFILE_ENCODING = UTF-8
|
|||
# title of most generated pages and in a few other places.
|
||||
# The default value is: My Project.
|
||||
|
||||
PROJECT_NAME = AdventOfCode
|
||||
PROJECT_NAME = AdventOfCode-02
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
|
|
1101
02/puzzle.input
1101
02/puzzle.input
File diff suppressed because it is too large
Load diff
192
02/src/main.c
192
02/src/main.c
|
@ -1,111 +1,137 @@
|
|||
/**
|
||||
* Copyright [2024] Jiří Štefka <jiriks74>
|
||||
* Copyright [2023] Jiří Štefka <jiriks74>
|
||||
* Project: AdventOfCode
|
||||
* @file main.c
|
||||
* @brief Main entry point
|
||||
* @author jiriks74
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
enum STATUS {
|
||||
DECREASING,
|
||||
INIT,
|
||||
INCREASING,
|
||||
};
|
||||
const int MAX_RED = 12;
|
||||
const int MAX_GREEN = 13;
|
||||
const int MAX_BLUE = 14;
|
||||
|
||||
typedef struct {
|
||||
int red;
|
||||
int green;
|
||||
int blue;
|
||||
} GameShow;
|
||||
|
||||
/**
|
||||
* @brief Count how many cubes of each color were in a show
|
||||
* @param *show A show of cubes in a game
|
||||
* @return A count of all the cubes in a struct
|
||||
*/
|
||||
GameShow get_max_cube_counts(char *game) {
|
||||
char *curr = game;
|
||||
GameShow result = {0};
|
||||
|
||||
while (curr != NULL) {
|
||||
char *end_show = strchr(curr, ';');
|
||||
|
||||
if (end_show != NULL) {
|
||||
*end_show = '\0';
|
||||
}
|
||||
|
||||
while (curr != NULL) {
|
||||
int cube_count = atoi(curr);
|
||||
|
||||
curr = strchr(curr, ' ');
|
||||
curr += sizeof(char);
|
||||
|
||||
if (*curr == 'r') {
|
||||
if (cube_count > result.red)
|
||||
result.red = cube_count;
|
||||
} else if (*curr == 'g') {
|
||||
if (cube_count > result.green)
|
||||
result.green = cube_count;
|
||||
} else if (*curr == 'b') {
|
||||
if (cube_count > result.blue)
|
||||
result.blue = cube_count;
|
||||
} else {
|
||||
result.red = -1;
|
||||
result.green = -1;
|
||||
result.blue = -1;
|
||||
return result;
|
||||
}
|
||||
curr = strchr(curr, ',');
|
||||
if (curr != NULL)
|
||||
curr += sizeof(char) * 2;
|
||||
}
|
||||
|
||||
if (end_show != NULL) {
|
||||
*end_show = ';';
|
||||
curr = end_show + sizeof(char) * 2;
|
||||
} else
|
||||
curr = end_show;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Count how many times were the cubes shown
|
||||
* @return Number of shows or -1 when error occurs
|
||||
*/
|
||||
bool is_game_possible(char *game) {
|
||||
// char *curr = strchr(game, ':');
|
||||
// curr += sizeof(char) * 2;
|
||||
|
||||
// if (curr == NULL) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
GameShow show_counts = get_max_cube_counts(game);
|
||||
|
||||
if (show_counts.red > MAX_RED)
|
||||
return false;
|
||||
else if (show_counts.green > MAX_GREEN)
|
||||
return false;
|
||||
else if (show_counts.blue > MAX_BLUE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef TESTING
|
||||
/**
|
||||
* @brief Main entry point
|
||||
* @param argc Number of command-line arguments.
|
||||
* @param argv Array of command-line arguments.
|
||||
*/
|
||||
#ifndef TESTING
|
||||
int main(int argc, char *argv[])
|
||||
#endif
|
||||
#ifdef TESTING
|
||||
int main_test(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
FILE *file;
|
||||
if (argc > 1)
|
||||
file = fopen(argv[1], "r");
|
||||
else {
|
||||
fprintf(stderr, "No file was given.\n");
|
||||
return 1;
|
||||
}
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Couldn't open file '%s'\n", argv[1]);
|
||||
return 1;
|
||||
FILE *input = fopen(argv[1], "r");
|
||||
|
||||
int possible_game_ids_sum = 0;
|
||||
int sum_of_powers = 0;
|
||||
|
||||
char line[512];
|
||||
while (fgets(line, sizeof(line), input)) {
|
||||
if (*line != 'G')
|
||||
break;
|
||||
|
||||
int curr_game_id = atoi(line + sizeof("Game"));
|
||||
|
||||
// if (is_game_possible(line)) {
|
||||
if (is_game_possible(strchr(line, ':') + sizeof(char) * 2)) {
|
||||
possible_game_ids_sum += curr_game_id;
|
||||
// printf("Game %d is possible\n", curr_game_id);
|
||||
} // else
|
||||
// printf("Game %d is impossible\n", curr_game_id);
|
||||
GameShow min_cubes =
|
||||
get_max_cube_counts(strchr(line, ':') + sizeof(char) * 2);
|
||||
sum_of_powers += min_cubes.red * min_cubes.green * min_cubes.blue;
|
||||
}
|
||||
|
||||
char *buffer = NULL;
|
||||
size_t bufferSize = 0;
|
||||
int status = INIT;
|
||||
uint safeCount = 0;
|
||||
while (getline(&buffer, &bufferSize, file) != -1) {
|
||||
char *token = strtok(buffer, " ");
|
||||
int previousLevel = 0;
|
||||
|
||||
if (sscanf(token, "%d", &previousLevel) == EOF) {
|
||||
fprintf(stderr, "Error: Wrong input file format!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
token = strtok(NULL, " ");
|
||||
int currentLevel = 0;
|
||||
if (sscanf(token, "%d", ¤tLevel) == EOF) {
|
||||
fprintf(stderr, "Error: Wrong input file format!");
|
||||
return 1;
|
||||
}
|
||||
if (currentLevel > previousLevel)
|
||||
status = INCREASING;
|
||||
else
|
||||
status = DECREASING;
|
||||
|
||||
if (status == INCREASING) {
|
||||
if (currentLevel - previousLevel < 1 | currentLevel - previousLevel > 3)
|
||||
continue;
|
||||
} else {
|
||||
if (previousLevel - currentLevel < 1 | previousLevel - currentLevel > 3)
|
||||
continue;
|
||||
}
|
||||
|
||||
token = strtok(NULL, " ");
|
||||
|
||||
bool finished = true;
|
||||
while (token != NULL) {
|
||||
previousLevel = currentLevel;
|
||||
if (sscanf(token, "%d", ¤tLevel) == EOF) {
|
||||
fprintf(stderr, "Error: Wrong input file format!");
|
||||
return 1;
|
||||
}
|
||||
if (status == INCREASING) {
|
||||
if (currentLevel - previousLevel < 1 |
|
||||
currentLevel - previousLevel > 3) {
|
||||
finished = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (previousLevel - currentLevel < 1 |
|
||||
previousLevel - currentLevel > 3) {
|
||||
finished = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, " ");
|
||||
}
|
||||
if (finished)
|
||||
safeCount++;
|
||||
}
|
||||
free(buffer);
|
||||
fclose(file);
|
||||
|
||||
printf("Safe count: %d\n", safeCount);
|
||||
|
||||
printf("Sum of possible game IDs: %d\n", possible_game_ids_sum);
|
||||
printf("Sum of powers: %d\n", sum_of_powers);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
7 6 4 2 1
|
||||
1 2 7 8 9
|
||||
9 7 6 2 1
|
||||
1 3 2 4 5
|
||||
8 6 4 4 1
|
||||
1 3 6 7 9
|
||||
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
|
||||
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
|
||||
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
|
||||
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
|
||||
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
|
||||
|
|
38
C_Template/.vscode/launch.json
vendored
38
C_Template/.vscode/launch.json
vendored
|
@ -1,38 +0,0 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch with puzzle input",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/CTemplate",
|
||||
"args": ["../puzzle.input"],
|
||||
"stopAtEntry": true,
|
||||
"cwd": "${workspaceFolder}/build/",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
],
|
||||
"preLaunchTask": "build",
|
||||
},
|
||||
{
|
||||
"name": "Launch with test input",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/CTemplate",
|
||||
"args": ["../test.input"],
|
||||
"stopAtEntry": true,
|
||||
"cwd": "${workspaceFolder}/build/",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
],
|
||||
"preLaunchTask": "build",
|
||||
}
|
||||
]
|
||||
}
|
26
C_Template/.vscode/tasks.json
vendored
26
C_Template/.vscode/tasks.json
vendored
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "cmake",
|
||||
"type": "shell",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"command": "sh",
|
||||
"args": [
|
||||
"-c",
|
||||
"'mkdir -p build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug ..'"
|
||||
],
|
||||
},
|
||||
{
|
||||
"label": "build",
|
||||
"type": "shell",
|
||||
"command": "make",
|
||||
"options": {
|
||||
"cwd": "${workspaceRoot}/build"
|
||||
},
|
||||
"dependsOn":["cmake"]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright [2024] Jiří Štefka <jiriks74>
|
||||
* Copyright [2023] Jiří Štefka <jiriks74>
|
||||
* Project: AdventOfCode
|
||||
* @file main.c
|
||||
* @brief Main entry point
|
||||
|
|
|
@ -8,5 +8,4 @@ This repository contains all my code I've made for [`Advent of code`](https://ad
|
|||
|
||||
## Previous years
|
||||
|
||||
- [2023](https://gitea.stefka.eu/jiriks74/AdventOfCode/src/branch/2023)
|
||||
- [2022](https://gitea.stefka.eu/jiriks74/AdventOfCode/src/branch/2022)
|
||||
|
|
|
@ -4,10 +4,9 @@ in
|
|||
pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
# Choose the build tools that you need
|
||||
cmake
|
||||
gcc
|
||||
gdb
|
||||
valgrind
|
||||
cmake
|
||||
];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue