Compare commits

...

24 Commits
2022 ... main

Author SHA1 Message Date
17d14e61cc
fix(CMake): Debugger flags were not set
This caused optimization to be turned on for debug builds
2024-09-24 12:43:39 +02:00
6f92d83c97
fix(nix): Move nix to repo root to prevend cache duplication 2024-09-23 03:50:55 +02:00
75f3b04e4f
feat(02): Solve day 2 2024-09-23 03:13:21 +02:00
00e1df7490
feat(Template): Update .gitignore
- Add ClangD cache
Add direnv cache
2024-09-23 03:10:09 +02:00
deac11eb54
fix(01): Memory leaks, conditional jumps on uninitialized values 2023-12-11 11:58:46 +01:00
09fb2aea68
fix(02/CMake,Doxygen): change template name to 02 2023-12-11 04:58:21 +01:00
bf6d9e0a77
fix(01/Readme): Link 2023-12-11 04:52:34 +01:00
84acf0c823
feat(02): init 2023-12-11 04:52:21 +01:00
d91bd4e375
feat(Doxygen): forgotten function description 2023-12-11 04:43:55 +01:00
72aed56663
fix(CTemplate): spelling 2023-12-11 04:32:41 +01:00
e19fbc980b
feat(CTemplate): add basic .vscode and blank puzzle.input 2023-12-11 04:32:06 +01:00
8a4b3174b8
fix(CMake/coverage): remove cov.info, *.gcda and *.gcno for coverage
GCov and LCOV don't overwrite the files when new data is available
... for whatever reason
2023-12-11 04:29:02 +01:00
c64b0d008c
feat(01): Solved part 2 2023-12-11 04:23:14 +01:00
6f9d90bf4d
feat(Doxygen): Use logo from assets 2023-12-10 04:21:39 +01:00
c9d334aafe
feat(assets): move assets to their own folder 2023-12-10 04:19:05 +01:00
ca71b60025
feat(README): add logo, add \n to eof 2023-12-10 04:17:53 +01:00
ceefbcc3e7
feat(misc): Add logo src 2023-12-10 04:15:02 +01:00
597ef1259d
feat(CTemplate): add Doxygen 2023-12-10 04:14:43 +01:00
118f3632a9
feat(01): Solved part 1 2023-12-10 04:14:17 +01:00
baf227ce23
fix(EditorConfig): turn off \n on eof for .md 2023-12-10 01:34:06 +01:00
96477dfba3
feat(EditorConfig): Add .editorconfig files 2023-12-10 01:25:53 +01:00
1f8dce3a86
fix(CTemplate): PROJECT_NAME 2023-12-10 01:16:28 +01:00
7223f1b99b
feat(CTemplate): Move to CMake 2023-12-10 01:15:20 +01:00
595837a4ac
feat(2023): remove code for new year 2023-12-10 00:51:02 +01:00
60 changed files with 11010 additions and 1284 deletions

13
.editorconfig Normal file
View File

@ -0,0 +1,13 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Every file
[*]
# Unix-style newlines with a newline ending every file
end_of_line = lf
# Remove any trailing whitespace characters
trim_trailing_whitespace = true
# Ensure every file ends with a newline
insert_final_newline = true

1
.envrc Normal file
View File

@ -0,0 +1 @@
use nix

7
.gitignore vendored
View File

@ -1,4 +1,11 @@
# ClangD
.cache
# Nix files
.direnv
# Output folders
build/
output/
# Vimspector

14
01/.editorconfig Normal file
View File

@ -0,0 +1,14 @@
# EditorConfig is awesome: https://EditorConfig.org
# Project files
# Matches multiple files with brace expansion notation
[*.{c,h,cc}]
# Set charset
charset = utf-8
max_line_length = 80
# 2 space indentation
indent_style = space
indent_size = 2

74
01/.gitignore vendored Normal file
View File

@ -0,0 +1,74 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
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/
lib/
bin/
*.swp

View File

@ -1,39 +0,0 @@
{
"configurations": {
"Launch": {
"adapter": "vscode-cpptools",
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/output/main",
"args": [ "${workspaceRoot}/tests/calories_test.dat"],
"cwd": "${workspaceRoot}/output",
//"environment": [ ... ],
"externalConsole": true,
"MIMode": "gdb"
}
},
"Attach": {
"adapter": "vscode-cpptools",
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
"configuration": {
"request": "attach",
"program": "${workspaceRoot}/output/main",
"MIMode": "gdb"
}
},
"Launch prod": {
"adapter": "vscode-cpptools",
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/output/main",
"args": [ "calories.dat"],
"cwd": "${workspaceRoot}/output",
//"environment": [ ... ],
"externalConsole": true,
"MIMode": "gdb"
}
}
}
}

52
01/CMakeLists.txt Normal file
View File

@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 3.14)
# Generate compile_commands.json
set(PROJECT_NAME 01)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Turn on testing by default
option(BUILD_TESTING "Build tests" ON)
# Turn off documentation build by default
option(BUILD_DOC "Build documentation" OFF)
# Turn off coverage by default
option(ENABLE_COVERAGE "Enable test coverage" ON)
# Set C standard to C99
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
set(CMAKE_C_FLAGS_DEBUG "-std=c99 -Wall -Wextra -Wunreachable-code -g -O0")
# Set the project name and version number. This allows for a user of your
project(${PROJECT_NAME} VERSION 0.1)
set(${PROJECT_NAME} 0.1)
# Function to prepend the subdirectory to source files in subdirectories
FUNCTION(PREPEND var )
SET(listVar "")
FOREACH(f ${${var}})
LIST(APPEND listVar "${CMAKE_CURRENT_SOURCE_DIR}/${f}")
ENDFOREACH(f)
SET(${var} "${listVar}" PARENT_SCOPE)
ENDFUNCTION(PREPEND)
# Include source code and headers. This calls the CMakeLists.txt in each
# subdirectory. These can define their own libraries, executables, etc. as targets,
# but here we define all exportable targets in the root CMakeLists.txt.
add_subdirectory(src)
add_subdirectory(include)
# enable unit testing via "make test" once the code has been compiled.
# TODO: Google Test
if(BUILD_TESTING)
message("Testing enabled")
enable_testing()
add_subdirectory(tests)
target_include_directories(tests PRIVATE include)
endif()
# Add PROJECT_NAME as an executable target.
add_executable(${PROJECT_NAME} ${SRC} ${INC})
target_include_directories(${PROJECT_NAME} PRIVATE include)
if(BUILD_DOC)
add_subdirectory(docs)
endif()

View File

@ -1,90 +0,0 @@
#
# 'make' build executable file 'main'
# 'make clean' removes all .o and executable files
#
# define the C compiler to use CC = gcc
# define any compile-time flags
CFLAGS := -std=c99 -Wall -Wextra -g
# define library paths in addition to /usr/lib
# if I wanted to include libraries not in /usr/lib I'd specify
# their path using -Lpath, something like:
LFLAGS =
# define output directory
OUTPUT := output
# define source directory
SRC := src
# define include directory
INCLUDE := include
# define lib directory
LIB := lib
ifeq ($(OS),Windows_NT)
MAIN := main.exe
SOURCEDIRS := $(SRC)
INCLUDEDIRS := $(INCLUDE)
LIBDIRS := $(LIB)
FIXPATH = $(subst /,\,$1)
RM := del /q /f
MD := mkdir
else
MAIN := main
SOURCEDIRS := $(shell find $(SRC) -type d)
INCLUDEDIRS := $(shell find $(INCLUDE) -type d)
LIBDIRS := $(shell find $(LIB) -type d)
FIXPATH = $1
RM = rm -f
MD := mkdir -p
endif
# define any directories containing header files other than /usr/include
INCLUDES := $(patsubst %,-I%, $(INCLUDEDIRS:%/=%))
# define the C libs
LIBS := $(patsubst %,-L%, $(LIBDIRS:%/=%))
# define the C source files
SOURCES := $(wildcard $(patsubst %,%/*.c, $(SOURCEDIRS)))
# define the C object files
OBJECTS := $(SOURCES:.c=.o)
#
# The following part of the makefile is generic; it can be used to
# build any executable just by changing the definitions above and by
# deleting dependencies appended to the file from 'make depend'
#
OUTPUTMAIN := $(call FIXPATH,$(OUTPUT)/$(MAIN))
all: $(OUTPUT) $(MAIN)
@echo Executing 'all' complete!
$(OUTPUT):
$(MD) $(OUTPUT)
$(MAIN): $(OBJECTS)
$(CC) $(INCLUDES) $(OBJECTS) $(LFLAGS) $(LIBS) -o $(OUTPUTMAIN) $(CFLAGS)
# this is a suffix replacement rule for building .o's from .c's
# it uses automatic variables $<: the name of the prerequisite of
# the rule(a .c file) and $@: the name of the target of the rule (a .o file)
# (see the gnu make manual section about automatic variables)
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
.PHONY: clean
clean:
$(RM) $(OUTPUTMAIN)
$(RM) $(call FIXPATH,$(OBJECTS))
@echo Cleanup complete!
run: all
./$(OUTPUTMAIN)
@echo Executing 'run: all' complete!

55
01/README.md Normal file
View File

@ -0,0 +1,55 @@
# Day 1
[link](https://adventofcode.com/2023/day/1)
## Assignment
### Day 1: Trebuchet?!
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.
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!
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").
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.
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:
```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.
Consider your entire calibration document.
What is the sum of all of the calibration values?

20
01/docs/CMakeLists.txt Normal file
View File

@ -0,0 +1,20 @@
# check if Doxygen is installed
find_package(Doxygen)
if (DOXYGEN_FOUND)
# set input and output files
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
# request to configure the file
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
message("Doxygen build started")
# note the option ALL which allows to build the docs together with the application
add_custom_target(doc ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating documentation with Doxygen"
VERBATIM )
else (DOXYGEN_FOUND)
message("Doxygen needs to be installed to generate the documentation")
endif (DOXYGEN_FOUND)

2826
01/docs/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

16
01/include/CMakeLists.txt Normal file
View File

@ -0,0 +1,16 @@
# Make an explicit list of all source files in IFJ23_INC. This is important
# because CMake is not a build system: it is a build system generator. Suppose
# you add a file foo.cpp to src/ after running cmake .. . If you set
# IFJ23_INC with `file(GLOB ... )`, this is not passed to the makefile; it
# doesn't know that foo.cpp exists and will not re-run cmake. Your
# collaborator's builds will fail and it will be unclear why. Whether you use
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
# file list, you know beforehand why your code isn't compiling.
set(INC
)
# Form the full path to the source files...
PREPEND(INC)
# ... and pass the variable to the parent scope.
set(INC ${INC} PARENT_SCOPE)

1001
01/puzzle.input Normal file

File diff suppressed because it is too large Load Diff

17
01/src/CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
# Make an explicit list of all source files in `CMakeDemo_SRC`. This is important
# because CMake is not a build system: it is a build system generator. Suppose
# you add a file foo.cpp to src/ after running cmake .. . If you set
# `CMakeDemo_SRC` with `file(GLOB ... )`, this is not passed to the makefile;
# the makefile doesn't know that foo.cpp exists and will not re-run cmake. Your
# collaborator's builds will fail and it will be unclear why. Whether you use
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
# file list, you know beforehand why your code isn't compiling.
set(SRC
main.c
)
# Form the full path to the source files...
PREPEND(SRC)
# ... and pass the variable to the parent scope.
set(SRC ${SRC} PARENT_SCOPE)

View File

@ -1,246 +1,122 @@
#include <stdbool.h>
/**
* 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>
struct elf {
int size;
int *calories;
};
// Gets the number of elves in the input file.
int get_num_of_elves(const char *fileName) {
// Max line length
char line[300];
// Stores the number of empty lines (elves)
int emptyLine = 0;
// Open the file
FILE *fp = fopen(fileName, "r");
// Check if the file opened successfully
if (fp == NULL) {
printf("Error: Could not open specified file!\n");
return -1;
}
// Read the file and count blank lines
while (fgets(line, 300, fp)) {
int i = 0;
int len = strlen(line);
emptyLine++;
for (i = 0; i < len; i++) {
if (line[i] != '\n' && line[i] != '\t' && line[i] != ' ') {
emptyLine--;
break;
}
}
}
// Check if the last line in the file is empty
if (line[0] == '\n') {
emptyLine--;
}
// Close the file
fclose(fp);
// Return the number of elves (one elf won't be counted if there is a blank line at the end of the file)
return ++emptyLine;
}
/*
* Loads the elve's carried calories from the input file.
* Params:
* - int num_of_elves: The number of elves in the input file.
* - const char *fileName: The name of the input file.
* - struct elf *elves: The array of elves to store the data in.
/**
* @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.
*/
void load_data(int num_of_elves, char *filename, struct elf **arr) {
// Open the file
FILE *fp = fopen(filename, "r");
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"};
// Check if the file opened successfully
if (fp == NULL) {
printf("Error: Could not open specified file!\n");
return;
}
// 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;
// Go through each elf
for (int i = 0; i < num_of_elves; i++) {
// Count number of lines until blank line
int num_of_lines = 0;
// Stores the current line (max length 300)
char line[300];
/*
* NOTE: The code below is used to get the number of items does the elf have
* so that the memory can be allocated corretly. But then wee need to go back
* to the start of the elve's data and we need the number of characters we read
* to do that
*/
// Counts the number of characters
int char_count = 0;
char *written = strstr(str, numbers[i]);
char *digit = strstr(str, digits[i]);
// Go through the elve's data
while (fgets(line, 300, fp)) {
// Length of the current line
int len = strlen(line);
// Update character count
char_count += len;
// Go through the line until a new line character is found
for (int i = 0; i < len; i++) {
if (line[i] != '\n' && line[i] != '\t' && line[i] != ' ') {
num_of_lines++;
break;
}
}
// Check if the line is empty
if (line[0] == '\n') {
break;
}
}
// Check for blank line at EOF (or you'll get an infinit loop if the last line is blank LOL)
if (line[0] == EOF) {
break;
}
// If the line is empty, go back to the start of the next elve
if (num_of_lines == 0) {
i--;
if (written == NULL && digit == NULL)
continue;
}
if (written == NULL)
pos = digit;
else if (digit == NULL)
pos = written;
else
pos = digit < written ? digit : written;
// Go back to start of current elf's data
fseek(fp, -char_count, SEEK_CUR);
// Reference the array
struct elf *data = *arr;
// Allocate memory for array
data[i].calories = malloc(num_of_lines * sizeof(int));
// Remember how many calories are stored
data[i].size = num_of_lines;
// Load the data
for (int j = 0; j < num_of_lines; j++) {
// Read the line ans add the calories to the correct elf in the array
int res = fscanf(fp, "%d", &data[i].calories[j]);
// Check if the line has the correct formatting
if (res != 1) {
printf("Error, bad file format!");
return;
}
}
}
// Close the file
fclose(fp);
}
// Count all the calories each elf has
// Params:
// - int num_of_elves: The number of elves in the input file.
// - struct elf *elves: The array with the data.
void count_elf_calories(struct elf **arr, int num_of_elves) {
// Reference the array
struct elf *data = *arr;
// Go through each elf
for (int i = 0; i < num_of_elves; i++) {
// Sum of the callories for the current elf
int sum = 0;
// Go through the elve's calories
for (int j = 0; j < data[i].size; j++) {
// Add the calories to the sum
sum += data[i].calories[j];
// Remove the callories and decrease the stored calories number
data[i].calories[j] = 0;
}
// Set the sum to indes 0
data[i].calories[0] = sum;
data[i].size = 1;
if (pos < smallestPos) {
numAtSmallPos = i;
smallestPos = pos;
}
}
// Argument parser
char *argv_parser(int argc, char *argv[]) {
// This program has only one argument
if (argc != 2) {
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return NULL;
// Chen which was first and return it
return numAtSmallPos;
}
// Return the argument as pos 1 (the filename)
return argv[1];
}
int main(int argc, char *argv[]) {
// The array of elves
struct elf *arr;
// Get the filename
char *filename = argv_parser(argc, argv);
// Get the number of elves in the file
int num_of_elves = get_num_of_elves(filename);
// Check if the operation was successful
if (num_of_elves == -1) {
return 1;
}
// Alocate the memory for the array
arr = malloc(num_of_elves * sizeof(struct elf));
// Load all the elve's calorias
load_data(num_of_elves, filename, &arr);
// Count all the calories each elf has
count_elf_calories(&arr, num_of_elves);
// Get 3 elves with the most calories
int first_elf_cal = 0;
int first_elf_idx = 0;
int second_elf_cal = 0;
int second_elf_idx = 0;
int third_elf_cal = 0;
int third_elf_idx = 0;
for (int i = 0; i < num_of_elves; i++) {
// If the elf has more calories than others, move the other elves down
if (arr[i].calories[0] > first_elf_cal) {
third_elf_cal = second_elf_cal;
third_elf_idx = second_elf_idx;
second_elf_cal = first_elf_cal;
second_elf_idx = first_elf_idx;
first_elf_cal = arr[i].calories[0];
first_elf_idx = i;
} else if (arr[i].calories[0] > second_elf_cal) {
third_elf_cal = second_elf_cal;
third_elf_idx = second_elf_idx;
second_elf_cal = arr[i].calories[0];
second_elf_idx = i;
} else if (arr[i].calories[0] > third_elf_cal) {
third_elf_cal = arr[i].calories[0];
third_elf_idx = i;
/**
* @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;
}
}
// Print out the 3 elves with the most calories
printf("Elf %d carries the most calories at %d calories\n", first_elf_idx,
first_elf_cal);
printf("Elf %d carries the second most calories at %d calories\n",
second_elf_idx, second_elf_cal);
printf("Elf %d carries the third most calories at %d calories\n",
third_elf_idx, third_elf_cal);
// Print the top 3 elves with the most calories
printf("The top 3 elves carry %d calories\n",
first_elf_cal + second_elf_cal + third_elf_cal);
// Free memory
for (int i = 0; i < num_of_elves; i++) {
free(arr[i].calories);
}
// Free the array
free(arr);
return 0;
if (result2 == -1) {
result += result / 10;
} else {
result += result2;
}
return result;
}
/**
* @brief Main entry point
* @param argc Number of command-line arguments.
* @param argv Array of command-line arguments.
*/
#ifdef TESTING
int mainTest(FILE *stdin, int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
FILE *file;
if (argc == 1) {
file = stdin;
} else {
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]);
else
fprintf(stderr, "Couldn't open file\n");
exit(EXIT_FAILURE);
}
// LCOV_EXCL_STOP
char *line = NULL;
size_t len = 0;
ssize_t read = 0;
int result = 0;
while ((read = getline(&line, &len, file) != -1)) {
result += getVal(line);
}
free(line);
fclose(file);
printf("The sum of the calibration values is %d\n", result);
return EXIT_SUCCESS;
}

83
01/tests/CMakeLists.txt Normal file
View File

@ -0,0 +1,83 @@
set(PROJECT_NAME ${PROJECT_NAME} PARENT_SCOPE )
# GoogleTest requires at least C++14
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Get GoogleTest
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
add_subdirectory(src)
add_executable(tests ${TESTS})
# Link test executable against gtest & gtest_main
target_link_libraries(
tests
GTest::gtest_main
)
target_include_directories(tests PRIVATE
${CMAKE_SOURCE_DIR}/src
)
# Discover tests
include(GoogleTest)
gtest_discover_tests(tests)
add_dependencies(tests ${PROJECT_NAME})
# The following section is inspired by https://github.com/cmake-modules/lcov
if(ENABLE_COVERAGE)
message("Test coverage enabled")
# set(exclude_dir "*/tests/* */_deps/* /usr/include/c++/11/**/* /usr/include/c++/**/*")
# set(exclude_dir "*/tests/* */_deps/* /usr/include/c++/11/tuple /usr/include/c++/11/**/*")
# Check for lcov, gcov and genhtml
find_program(GCOV gcov)
if (NOT GCOV)
message(WARNING "gcov not found")
endif()
find_program(LCOV lcov)
if (NOT LCOV)
message(WARNING "lcov not found")
endif()
find_program(GENHTML genhtml)
if (NOT GENHTML)
message(WARNING "genhtml not found")
endif()
if (GCOV AND LCOV AND GENHTML)
# Set C compiler flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
# Set C++ compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
set(covname cov.info)
add_custom_target(coverage DEPENDS ${covname})
add_dependencies(coverage tests ${PROJECT_NAME})
add_custom_command(
OUTPUT ${covname}
COMMAND rm -rf **/coverage
COMMAND ${LCOV} -c -o ${covname} -d ${CMAKE_BINARY_DIR}/tests/CMakeFiles/tests.dir/ -b . --gcov-tool ${GCOV}
COMMAND ${LCOV} -r ${covname} -o ${covname} "*/tests/*" "*/_deps/**/*" "/usr/include/c++/**/*" "/usr/include/c++/11/**/*"
COMMAND ${LCOV} -l ${covname}
COMMAND ${GENHTML} ${covname} -output coverage
COMMAND ${LCOV} -l ${covname} 2>/dev/null | grep Total | sed 's/|//g' | sed 's/Total://g' | awk '{print $1}' | sed s/%//g > coverage/total
COMMAND rm -rf CMakeFiles/tests.dir/src/*.gcda CMakeFiles/tests.dir/src/*.gcno
COMMAND rm -f ${covname}
)
set_directory_properties(PROPERTIES
ADDITIONAL_CLEAN_FILES ${covname}
)
set_directory_properties(PROPERTIES
ADDITIONAL_CLEAN_FILES coverage/
)
else()
message(WARNING "Cannot enable coverage. Missing the required tools")
endif()
endif()

View File

@ -1,14 +0,0 @@
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000

View File

@ -0,0 +1,17 @@
# Make an explicit list of all source files in `IFJ23_TESTS`. This is important
# because CMake is not a build system: it is a build system generator. Suppose
# you add a file foo.cpp to src/ after running cmake .. . If you set
# `IFJ23_TESTS` with `file(GLOB ... )`, this is not passed to the makefile;
# the makefile doesn't know that foo.cpp exists and will not re-run cmake. Your
# collaborator's builds will fail and it will be unclear why. Whether you use
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
# file list, you know beforehand why your code isn't compiling.
set(TESTS
test.cpp
)
# Form the full path to the source files...
PREPEND(TESTS)
# ... and pass the variable to the parent scope.
set(TESTS ${TESTS} PARENT_SCOPE)

81
01/tests/src/test.cpp Normal file
View File

@ -0,0 +1,81 @@
#include "gtest/gtest.h"
#include <gtest/gtest.h>
#include <stdio.h>
#include <string>
#define TESTING
#include "main.c"
void stream_add(FILE *stream, std::string string) {
fprintf(stream, "%s", string.c_str());
fseek(stream, -string.length(), SEEK_CUR);
}
class Trebuchet : public ::testing::Test {
public:
FILE *input;
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() {}
};
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"));
}

14
02/.editorconfig Normal file
View File

@ -0,0 +1,14 @@
# EditorConfig is awesome: https://EditorConfig.org
# Project files
# Matches multiple files with brace expansion notation
[*.{c,h,cc}]
# Set charset
charset = utf-8
max_line_length = 80
# 2 space indentation
indent_style = space
indent_size = 2

64
02/.gitignore vendored Normal file
View File

@ -0,0 +1,64 @@
# ClangD
.cache
# Nix files
.direnv
# Output folders
output/
# Vimspector
# .vimspector.json
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

View File

@ -1,39 +0,0 @@
{
"configurations": {
"Launch": {
"adapter": "vscode-cpptools",
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/output/main",
"args": [ "${workspaceRoot}/tests/guide.dat", "2" ],
"cwd": "${workspaceRoot}/output",
//"environment": [ ... ],
"externalConsole": true,
"MIMode": "gdb"
}
},
"Attach": {
"adapter": "vscode-cpptools",
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
"configuration": {
"request": "attach",
"program": "${workspaceRoot}/output/main",
"MIMode": "gdb"
}
},
"Launch prod": {
"adapter": "vscode-cpptools",
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/output/main",
"args": [ "guide.dat", "2" ],
"cwd": "${workspaceRoot}/output",
//"environment": [ ... ],
"externalConsole": true,
"MIMode": "gdb"
}
}
}
}

52
02/CMakeLists.txt Normal file
View File

@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 3.14)
# Generate compile_commands.json
set(PROJECT_NAME 02)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Turn on testing by default
option(BUILD_TESTING "Build tests" ON)
# Turn off documentation build by default
option(BUILD_DOC "Build documentation" OFF)
# Turn off coverage by default
option(ENABLE_COVERAGE "Enable test coverage" ON)
# Set C standard to C99
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
set(CMAKE_C_FLAGS_DEBUG "-std=c99 -Wall -Wextra -Wunreachable-code -g -O0")
# Set the project name and version number. This allows for a user of your
project(${PROJECT_NAME} VERSION 0.1)
set(${PROJECT_NAME} 0.1)
# Function to prepend the subdirectory to source files in subdirectories
FUNCTION(PREPEND var )
SET(listVar "")
FOREACH(f ${${var}})
LIST(APPEND listVar "${CMAKE_CURRENT_SOURCE_DIR}/${f}")
ENDFOREACH(f)
SET(${var} "${listVar}" PARENT_SCOPE)
ENDFUNCTION(PREPEND)
# Include source code and headers. This calls the CMakeLists.txt in each
# subdirectory. These can define their own libraries, executables, etc. as targets,
# but here we define all exportable targets in the root CMakeLists.txt.
add_subdirectory(src)
add_subdirectory(include)
# enable unit testing via "make test" once the code has been compiled.
# TODO: Google Test
if(BUILD_TESTING)
message("Testing enabled")
enable_testing()
add_subdirectory(tests)
target_include_directories(tests PRIVATE include)
endif()
# Add PROJECT_NAME as an executable target.
add_executable(${PROJECT_NAME} ${SRC} ${INC})
target_include_directories(${PROJECT_NAME} PRIVATE include)
if(BUILD_DOC)
add_subdirectory(docs)
endif()

View File

@ -1,91 +0,0 @@
#
# 'make' build executable file 'main'
# 'make clean' removes all .o and executable files
#
# define the C compiler to use CC = gcc
# define any compile-time flags
# CFLAGS := -std=c99 -Wall -Wextra -g -lm
CFLAGS := -std=c99 -Wall -Wextra -g
# define library paths in addition to /usr/lib
# if I wanted to include libraries not in /usr/lib I'd specify
# their path using -Lpath, something like:
LFLAGS =
# define output directory
OUTPUT := output
# define source directory
SRC := src
# define include directory
INCLUDE := include
# define lib directory
LIB := lib
ifeq ($(OS),Windows_NT)
MAIN := main.exe
SOURCEDIRS := $(SRC)
INCLUDEDIRS := $(INCLUDE)
LIBDIRS := $(LIB)
FIXPATH = $(subst /,\,$1)
RM := del /q /f
MD := mkdir
else
MAIN := main
SOURCEDIRS := $(shell find $(SRC) -type d)
INCLUDEDIRS := $(shell find $(INCLUDE) -type d)
LIBDIRS := $(shell find $(LIB) -type d)
FIXPATH = $1
RM = rm -f
MD := mkdir -p
endif
# define any directories containing header files other than /usr/include
INCLUDES := $(patsubst %,-I%, $(INCLUDEDIRS:%/=%))
# define the C libs
LIBS := $(patsubst %,-L%, $(LIBDIRS:%/=%))
# define the C source files
SOURCES := $(wildcard $(patsubst %,%/*.c, $(SOURCEDIRS)))
# define the C object files
OBJECTS := $(SOURCES:.c=.o)
#
# The following part of the makefile is generic; it can be used to
# build any executable just by changing the definitions above and by
# deleting dependencies appended to the file from 'make depend'
#
OUTPUTMAIN := $(call FIXPATH,$(OUTPUT)/$(MAIN))
all: $(OUTPUT) $(MAIN)
@echo Executing 'all' complete!
$(OUTPUT):
$(MD) $(OUTPUT)
$(MAIN): $(OBJECTS)
$(CC) $(INCLUDES) $(OBJECTS) $(LFLAGS) $(LIBS) -o $(OUTPUTMAIN) $(CFLAGS)
# this is a suffix replacement rule for building .o's from .c's
# it uses automatic variables $<: the name of the prerequisite of
# the rule(a .c file) and $@: the name of the target of the rule (a .o file)
# (see the gnu make manual section about automatic variables)
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
.PHONY: clean
clean:
$(RM) $(OUTPUTMAIN)
$(RM) $(call FIXPATH,$(OBJECTS))
@echo Cleanup complete!
run: all
./$(OUTPUTMAIN)
@echo Executing 'run: all' complete!

66
02/README.md Normal file
View 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?

20
02/docs/CMakeLists.txt Normal file
View File

@ -0,0 +1,20 @@
# check if Doxygen is installed
find_package(Doxygen)
if (DOXYGEN_FOUND)
# set input and output files
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
# request to configure the file
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
message("Doxygen build started")
# note the option ALL which allows to build the docs together with the application
add_custom_target(doc ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating documentation with Doxygen"
VERBATIM )
else (DOXYGEN_FOUND)
message("Doxygen needs to be installed to generate the documentation")
endif (DOXYGEN_FOUND)

2826
02/docs/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

16
02/include/CMakeLists.txt Normal file
View File

@ -0,0 +1,16 @@
# Make an explicit list of all source files in IFJ23_INC. This is important
# because CMake is not a build system: it is a build system generator. Suppose
# you add a file foo.cpp to src/ after running cmake .. . If you set
# IFJ23_INC with `file(GLOB ... )`, this is not passed to the makefile; it
# doesn't know that foo.cpp exists and will not re-run cmake. Your
# collaborator's builds will fail and it will be unclear why. Whether you use
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
# file list, you know beforehand why your code isn't compiling.
set(INC
)
# Form the full path to the source files...
PREPEND(INC)
# ... and pass the variable to the parent scope.
set(INC ${INC} PARENT_SCOPE)

101
02/puzzle.input Normal file
View File

@ -0,0 +1,101 @@
Game 1: 19 blue, 12 red; 19 blue, 2 green, 1 red; 13 red, 11 blue
Game 2: 1 green, 1 blue, 1 red; 11 red, 3 blue; 1 blue, 18 red; 9 red, 1 green; 2 blue, 11 red, 1 green; 1 green, 2 blue, 10 red
Game 3: 3 blue, 2 red, 6 green; 4 blue, 6 green, 1 red; 11 green, 12 blue; 2 red, 6 green, 4 blue; 4 green
Game 4: 10 red, 5 green, 5 blue; 3 red, 3 blue, 6 green; 2 blue, 9 red, 6 green; 8 green, 10 red, 4 blue; 9 red, 2 green, 3 blue; 1 blue, 5 red, 15 green
Game 5: 11 green, 7 blue; 5 green, 5 red, 1 blue; 1 green, 1 red, 4 blue; 1 red, 1 blue, 4 green; 4 blue, 1 red, 10 green; 5 red, 6 green
Game 6: 1 green, 1 red, 11 blue; 1 blue, 2 green; 1 red, 5 green, 9 blue; 7 blue; 1 red, 2 green, 9 blue; 12 blue, 1 red, 2 green
Game 7: 1 blue, 10 red, 7 green; 14 blue, 10 green; 12 red, 2 green; 16 red, 13 blue, 1 green; 12 green, 10 red, 3 blue; 9 red, 19 blue, 11 green
Game 8: 3 blue, 1 green, 3 red; 4 blue, 10 red, 6 green; 1 green, 10 red, 9 blue; 9 blue, 7 red, 8 green; 8 green, 12 red, 8 blue; 6 blue, 1 green, 13 red
Game 9: 10 green, 2 blue, 11 red; 2 green, 2 red; 6 blue, 8 red, 13 green
Game 10: 8 red, 3 blue, 5 green; 5 green, 7 blue, 1 red; 3 red, 10 blue, 6 green; 2 red, 6 green, 7 blue; 3 blue, 11 red, 4 green; 8 red, 8 blue, 4 green
Game 11: 14 green, 9 red; 3 blue, 6 green, 8 red; 14 green
Game 12: 10 red, 5 blue, 1 green; 4 blue, 8 red; 5 blue, 1 green, 6 red; 14 red, 4 blue; 1 green, 11 red, 3 blue
Game 13: 1 blue, 16 green, 1 red; 6 red, 2 blue, 5 green; 2 blue, 12 red, 10 green; 3 red, 4 blue, 13 green; 14 red, 4 blue, 12 green; 7 red, 2 green
Game 14: 17 red, 11 blue, 3 green; 16 red, 3 blue, 8 green; 3 green, 9 red, 13 blue; 4 green, 15 red, 14 blue
Game 15: 7 blue, 2 red, 2 green; 1 green, 5 red, 6 blue; 3 green, 6 red, 2 blue
Game 16: 3 red, 3 green; 6 green, 4 red, 3 blue; 3 red, 4 blue; 4 blue, 2 red, 4 green
Game 17: 6 red, 1 blue, 5 green; 3 red, 1 green, 12 blue; 13 green, 1 blue; 5 blue, 7 green, 6 red; 5 blue, 14 green, 2 red; 4 green, 6 red, 10 blue
Game 18: 4 red, 8 blue; 8 blue, 4 red; 12 blue, 1 green
Game 19: 1 blue, 15 green, 9 red; 1 red, 3 green; 4 blue, 2 green, 1 red
Game 20: 7 blue, 4 green, 12 red; 1 red, 9 green, 8 blue; 4 blue, 2 green; 13 green, 8 blue; 3 red, 4 green, 1 blue; 6 green, 7 red, 3 blue
Game 21: 9 green, 4 blue, 8 red; 5 blue; 7 red, 8 blue, 1 green
Game 22: 3 green, 4 red; 6 red, 3 green; 4 red, 1 blue, 1 green; 11 red, 3 green, 1 blue; 7 red, 1 blue
Game 23: 3 blue, 4 green; 3 green, 1 red; 1 red, 2 blue, 4 green
Game 24: 2 blue, 3 green; 9 red, 4 green; 2 blue, 9 red; 2 green, 10 red, 1 blue; 1 blue, 1 red, 5 green
Game 25: 8 green, 4 blue; 9 blue, 7 red; 5 green, 15 blue, 11 red; 11 green, 14 red, 10 blue
Game 26: 3 blue; 2 red, 1 green; 2 red, 3 blue; 10 blue, 1 red, 3 green; 1 green, 2 red; 1 green, 6 blue
Game 27: 1 green, 6 blue; 2 green, 1 red, 6 blue; 1 red, 2 blue, 1 green
Game 28: 8 blue, 1 red, 5 green; 1 red; 3 green, 4 red, 2 blue; 4 green, 2 red, 4 blue; 5 blue, 3 red, 7 green
Game 29: 2 green, 4 blue; 7 blue, 4 red, 10 green; 7 blue, 9 green; 14 green, 7 red, 5 blue
Game 30: 19 green, 3 red; 19 green; 1 blue, 14 green; 2 blue, 5 green; 3 red, 19 green
Game 31: 3 red, 1 green, 4 blue; 10 blue; 3 red, 4 green, 5 blue; 10 blue, 1 red, 6 green
Game 32: 19 red, 1 green, 2 blue; 1 blue, 6 green, 13 red; 10 green, 9 red; 11 red, 2 blue, 6 green; 8 green, 5 red
Game 33: 2 red, 8 blue, 2 green; 1 red, 3 green; 9 red, 9 blue, 1 green; 6 red, 1 green; 9 blue, 1 green, 8 red; 5 green, 10 red, 8 blue
Game 34: 1 red, 6 blue, 2 green; 7 red; 14 red, 13 blue; 13 red, 12 blue; 1 green, 9 red, 13 blue; 2 green, 15 blue
Game 35: 8 blue, 2 red, 3 green; 2 green, 2 red; 3 red, 6 blue, 2 green; 2 green, 6 blue; 1 green, 5 blue, 4 red; 3 green, 6 blue
Game 36: 3 red, 5 blue, 10 green; 1 red, 1 green, 7 blue; 2 blue, 2 green, 1 red
Game 37: 8 red, 7 green; 5 green, 1 blue, 6 red; 7 red, 6 blue, 11 green
Game 38: 4 green, 10 red, 9 blue; 12 green, 2 blue, 2 red; 6 red, 6 blue, 9 green; 1 blue, 1 green, 6 red; 3 blue, 1 red, 5 green; 5 blue, 2 red, 12 green
Game 39: 1 blue, 2 red; 7 blue, 2 green, 1 red; 7 blue, 11 green, 3 red; 8 blue, 13 green, 1 red; 6 green, 6 blue, 3 red
Game 40: 8 green, 5 blue; 5 green, 1 blue, 10 red; 9 green, 3 blue; 3 green, 7 red; 2 green, 3 blue, 5 red
Game 41: 7 green, 8 red; 3 blue, 15 green, 7 red; 2 red, 2 green, 4 blue; 10 green, 4 red, 5 blue; 3 red, 8 blue, 9 green; 7 red, 8 green
Game 42: 6 blue, 12 green; 3 red, 1 green; 1 red, 12 green, 3 blue; 10 red, 9 green; 9 red, 4 green, 5 blue
Game 43: 11 red, 6 green; 2 blue, 11 red; 3 red, 1 blue; 3 green, 11 red, 2 blue; 4 red, 5 green, 1 blue; 8 green, 2 blue, 17 red
Game 44: 2 green, 9 blue, 3 red; 7 blue, 1 green, 4 red; 1 green
Game 45: 1 green, 10 red; 5 red, 10 green, 1 blue; 11 red, 3 green, 2 blue; 2 blue, 3 green, 4 red; 7 green, 3 red, 2 blue; 1 blue, 10 red
Game 46: 1 green, 4 blue, 7 red; 13 blue, 2 green, 9 red; 7 blue, 3 red, 1 green
Game 47: 4 blue; 2 green, 2 red, 1 blue; 1 green, 1 red, 4 blue; 1 green, 2 red, 2 blue; 2 blue, 2 red
Game 48: 5 green, 10 red; 7 red, 5 green; 1 green, 11 red; 12 red, 11 green; 11 red, 1 blue, 1 green
Game 49: 2 green, 1 red, 1 blue; 1 blue, 2 red; 2 green, 1 red, 2 blue; 1 blue, 1 red, 1 green
Game 50: 5 green, 2 blue; 4 green, 4 blue, 3 red; 1 red, 7 green, 3 blue
Game 51: 9 green, 1 red, 2 blue; 7 red, 3 blue, 6 green; 5 green, 4 blue, 5 red
Game 52: 2 green, 4 blue, 1 red; 2 blue, 2 red, 13 green; 8 blue, 3 green; 3 green, 4 blue, 2 red; 2 green
Game 53: 3 red; 4 blue, 4 red; 2 blue, 2 red; 6 blue, 1 red, 2 green; 1 red, 1 green, 6 blue; 2 blue, 4 red
Game 54: 3 blue, 3 green, 18 red; 4 blue, 18 red, 3 green; 7 blue, 4 green
Game 55: 1 green, 2 red, 3 blue; 1 red, 4 blue, 1 green; 3 blue, 2 red; 2 blue, 1 green; 3 blue, 2 red; 1 blue, 1 green, 1 red
Game 56: 12 green, 2 red, 1 blue; 11 green, 16 red, 13 blue; 7 red, 5 blue, 12 green; 4 blue, 16 red; 5 red, 1 blue, 3 green
Game 57: 5 green, 17 blue, 11 red; 6 blue, 1 green; 1 green, 5 blue, 8 red; 9 green, 11 red, 1 blue; 9 green, 11 blue, 7 red; 8 green, 4 blue
Game 58: 5 red, 10 blue, 6 green; 5 green, 11 blue, 5 red; 9 green; 4 red, 2 green
Game 59: 2 red, 6 blue, 1 green; 1 green, 12 blue; 2 red
Game 60: 6 blue, 10 green, 9 red; 8 red, 19 blue, 2 green; 16 red, 10 green, 12 blue; 13 red, 12 blue, 6 green
Game 61: 12 green, 1 red, 3 blue; 3 red, 4 blue, 19 green; 1 blue, 7 green
Game 62: 7 red, 6 blue, 8 green; 10 blue, 3 green, 17 red; 13 blue, 3 red, 10 green; 13 red, 5 blue, 9 green; 12 blue, 4 red; 10 red, 4 green
Game 63: 19 green, 4 red; 5 blue, 4 red, 1 green; 4 red, 2 blue, 15 green; 5 green, 4 red, 5 blue
Game 64: 6 red, 3 green; 6 green, 3 red, 3 blue; 3 blue, 8 red, 5 green; 3 blue, 7 red, 1 green; 1 blue, 6 red, 6 green
Game 65: 1 green, 9 blue; 6 blue, 4 green, 6 red; 6 blue, 5 green; 3 red, 1 blue, 4 green
Game 66: 1 blue, 2 red; 2 green, 1 blue; 2 red, 1 blue, 1 green; 1 blue, 1 green
Game 67: 16 blue, 1 green; 1 blue, 2 green, 2 red; 1 red, 9 blue; 12 blue, 4 green, 1 red; 6 green, 11 blue, 3 red
Game 68: 6 blue, 2 red, 1 green; 2 blue, 2 green; 1 green, 7 red, 15 blue; 14 blue, 12 green, 3 red; 13 green, 10 red, 6 blue; 2 green, 5 blue, 1 red
Game 69: 2 red, 1 blue, 2 green; 1 blue, 7 green, 1 red; 3 blue, 1 red, 7 green; 2 red, 1 blue, 11 green
Game 70: 2 green, 9 red, 3 blue; 12 blue, 1 green, 13 red; 6 red, 1 green, 5 blue; 1 red, 17 blue
Game 71: 7 red, 5 green, 6 blue; 5 blue, 5 green; 7 green, 4 blue; 2 green, 4 blue, 8 red; 10 red, 8 green; 3 blue, 13 red, 7 green
Game 72: 13 red, 17 green; 9 red, 20 green, 3 blue; 1 green, 3 blue, 8 red
Game 73: 1 blue, 7 red, 2 green; 2 green, 1 blue, 8 red; 1 blue, 2 red; 4 red, 7 green; 4 red, 5 green; 3 green, 7 red
Game 74: 2 green, 14 blue; 1 red, 1 blue, 7 green; 1 red, 8 green, 11 blue; 4 green, 12 blue; 1 green, 5 blue
Game 75: 12 blue, 1 red; 1 red, 7 blue, 4 green; 4 blue, 6 green; 4 green, 3 blue, 1 red
Game 76: 7 green, 5 red, 6 blue; 18 red, 1 green; 14 green, 4 red, 15 blue; 4 blue, 6 red
Game 77: 2 blue, 2 green, 2 red; 2 blue, 1 red, 1 green; 2 green, 1 red; 6 blue, 4 green; 1 red, 1 blue, 6 green
Game 78: 5 red, 16 blue, 12 green; 11 blue, 3 red, 2 green; 13 blue, 4 red
Game 79: 9 red, 11 green, 6 blue; 1 red, 3 green; 7 blue, 7 red, 11 green; 8 red, 9 blue, 11 green; 7 red, 11 green, 4 blue
Game 80: 7 green, 5 red, 2 blue; 1 blue, 7 green, 1 red; 2 red, 2 blue; 1 red, 4 blue, 12 green; 4 green, 2 blue
Game 81: 5 blue, 2 green, 12 red; 2 green, 1 blue, 5 red; 3 blue, 13 red, 3 green; 3 green, 9 blue, 3 red; 10 blue, 4 red, 3 green
Game 82: 11 blue, 1 red, 9 green; 11 green, 1 blue, 12 red; 13 red, 6 blue, 19 green
Game 83: 6 red, 5 blue, 16 green; 4 green, 17 blue, 9 red; 15 red, 2 green, 9 blue
Game 84: 19 green, 11 blue, 3 red; 1 blue, 18 green, 6 red; 17 blue, 5 green, 4 red; 18 blue, 7 green, 3 red
Game 85: 3 green, 15 blue; 12 blue; 2 green, 1 red; 1 red, 9 blue, 1 green; 12 blue, 3 red, 1 green
Game 86: 3 green, 4 blue, 5 red; 9 red, 4 green, 1 blue; 6 green, 1 blue, 8 red; 3 green, 2 blue, 5 red
Game 87: 2 red, 8 blue, 5 green; 3 red, 5 blue, 10 green; 2 red, 3 green
Game 88: 16 green, 13 red; 7 green, 1 blue, 2 red; 7 red, 12 green; 5 red, 7 green, 2 blue; 2 blue, 10 green, 7 red; 8 red, 16 green
Game 89: 1 blue, 8 red; 2 green, 10 red, 12 blue; 13 green, 14 blue; 10 blue, 15 red, 13 green; 2 green, 5 red, 13 blue
Game 90: 16 blue, 7 red, 4 green; 4 green, 6 red, 11 blue; 2 red, 8 blue, 2 green; 5 green, 8 red, 10 blue; 4 red, 2 green, 7 blue; 4 green, 5 blue, 5 red
Game 91: 4 red, 4 green, 1 blue; 3 blue, 2 green; 6 blue, 4 green, 5 red; 2 red, 6 blue, 4 green; 6 blue, 1 green
Game 92: 1 red, 3 green; 3 blue, 6 green; 5 blue, 1 red, 11 green; 1 red; 3 green, 13 blue
Game 93: 1 red, 14 blue, 6 green; 10 blue, 6 red; 9 green, 15 red, 17 blue; 9 red, 1 green, 9 blue
Game 94: 3 red, 14 green; 3 blue, 15 green, 3 red; 2 red, 15 green
Game 95: 4 blue, 13 red; 5 blue, 1 green, 11 red; 3 green, 3 blue, 10 red; 13 red, 6 blue; 2 green, 5 blue; 3 green, 11 red
Game 96: 7 blue, 1 green; 1 green, 4 blue; 1 green, 2 red, 5 blue; 1 red, 2 blue, 1 green; 1 blue
Game 97: 15 green, 9 blue; 14 blue, 14 red, 2 green; 18 red, 12 blue, 2 green
Game 98: 1 green, 9 red; 1 red, 2 green, 7 blue; 8 red, 1 blue; 6 red, 2 green; 1 green, 6 blue
Game 99: 1 green, 2 red, 6 blue; 6 red, 1 green, 5 blue; 11 blue, 6 red; 11 red, 1 green; 1 green, 11 red, 9 blue
Game 100: 12 green, 8 blue, 2 red; 7 blue, 14 red, 8 green; 14 red, 1 blue, 4 green

17
02/src/CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
# Make an explicit list of all source files in `CMakeDemo_SRC`. This is important
# because CMake is not a build system: it is a build system generator. Suppose
# you add a file foo.cpp to src/ after running cmake .. . If you set
# `CMakeDemo_SRC` with `file(GLOB ... )`, this is not passed to the makefile;
# the makefile doesn't know that foo.cpp exists and will not re-run cmake. Your
# collaborator's builds will fail and it will be unclear why. Whether you use
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
# file list, you know beforehand why your code isn't compiling.
set(SRC
main.c
)
# Form the full path to the source files...
PREPEND(SRC)
# ... and pass the variable to the parent scope.
set(SRC ${SRC} PARENT_SCOPE)

View File

@ -1,271 +1,137 @@
/**
* Copyright [2023] Jiří Štefka <jiriks74>
* Project: AdventOfCode
* @file main.c
* @brief Main entry point
* @author jiriks74
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Error codes:
* 0 - no error
* 1 - invalid number of arguments
* 2 - invalid file
* 3 - invalid file format
* 4 - invalid solution part
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};
/* NOTE: info to remember:
* The aliases for rock, paper, scissors are:
* - A = X = rock
* - B = Y = paper
* - C = Z = scissors
* ------------------------------------------
* Scores:
* - Shape
* - Rock: 1
* - Paper: 2
* - Scissors: 3
* - Outcome
* - Win: 6
* - Draw: 3
* - Loss: 0
*/
while (curr != NULL) {
char *end_show = strchr(curr, ';');
int arg_parser(int argc, char *argv[], char **file_name, int *solution_part) {
if (argc != 3) {
printf("Usage: %s <file> <solution_part (1/2)>\n", argv[0]);
return 1;
}
// Check if the file exists
FILE *file = fopen(argv[1], "r");
if (file == NULL) {
printf("Error: File does not exist.\n");
return 2;
}
fclose(file);
// Check if the solution part is a valid number
if (atoi(argv[2]) != 1 && atoi(argv[2]) != 2) {
printf("Error: Invalid solution part.\nValid values are [1, 2]\n");
return 4;
if (end_show != NULL) {
*end_show = '\0';
}
*file_name = argv[1];
*solution_part = atoi(argv[2]);
while (curr != NULL) {
int cube_count = atoi(curr);
return 0;
}
curr = strchr(curr, ' ');
curr += sizeof(char);
// Returns the score of the given shape
// 1 = rock, 2 = paper, 3 = scissors
int score_shapes(char shape) {
switch (shape) {
case 'A':
case 'X':
return 1;
case 'B':
case 'Y':
return 2;
case 'C':
case 'Z':
return 3;
default:
return -1;
}
}
/* Returns my score for the round
*
* Parameters:
* - opponents_shape
* - A = rock
* - B = paper
* - C = scissors
* - my_shape
* - X = rock
* - Y = paper
* - Z = scissors
*/
int round_score(char opponents_shape, char my_shape) {
// Checks if the shapes are valid and get their scores
int opponents_score = score_shapes(opponents_shape);
int shape_score = score_shapes(my_shape);
if (opponents_score == -1 || shape_score == -1) {
printf("Error: Invalid shape.\n");
return -1;
}
// Draw
if (opponents_shape == 'A' && my_shape == 'X') {
return 3 + shape_score;
} else if (opponents_shape == 'B' && my_shape == 'Y') {
return 3 + shape_score;
} else if (opponents_shape == 'C' && my_shape == 'Z') {
return 3 + shape_score;
}
// Rock win
else if (my_shape == 'X' && opponents_shape == 'C') {
return 6 + shape_score;
}
// Paper win
else if (my_shape == 'Y' && opponents_shape == 'A') {
return 6 + shape_score;
} // Scissors win
else if (my_shape == 'Z' && opponents_shape == 'B') {
return 6 + shape_score;
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 {
return shape_score;
result.red = -1;
result.green = -1;
result.blue = -1;
return result;
}
curr = strchr(curr, ',');
if (curr != NULL)
curr += sizeof(char) * 2;
}
int score_file(char **file_name) {
FILE *file = fopen(*file_name, "r");
if (file == NULL) {
printf("Error opening the file.\n");
return -2;
if (end_show != NULL) {
*end_show = ';';
curr = end_show + sizeof(char) * 2;
} else
curr = end_show;
}
return result;
}
int my_score = 0;
/**
* @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;
// Read the file
while (!feof(file)) {
char opponent[1];
char me[1];
int res = fscanf(file, "%s %s", opponent, me);
// if (curr == NULL) {
// return false;
// }
if (res == EOF) {
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.
*/
int main(int argc, char *argv[])
#endif
#ifdef TESTING
int main_test(int argc, char *argv[])
#endif
{
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;
}
// Check for blank line at the end of the file
else if (res == 1 && opponent[0] == '\n') {
continue;
} else if (res != 2) {
printf("Error: Bad file format.\n");
return -3;
}
my_score += round_score(*opponent, *me);
}
fclose(file);
return my_score;
}
/* NOTE:
* ------------------------------------------------------------
* PART 2 OF THE SOLUTION
* ------------------------------------------------------------
*/
char *get_win_shape_part2(char *opponents_shape) {
switch (*opponents_shape) {
case 'A':
return "B";
case 'B':
return "C";
case 'C':
return "A";
default:
return "0";
}
}
// Returns the shape that looses against the given shape
//
// Parameters:
// - opponents_shape
// - A = rock
// - B = paper
// - C = scissors
char *get_loss_shape_part2(char *opponents_shape) {
switch (*opponents_shape) {
case 'A':
return "C";
case 'B':
return "A";
case 'C':
return "B";
default:
return "0";
}
}
/* Returns the score for a given round
*
* Parameters:
* - opponents_shape
* - A = rock
* - B = paper
* - C = scissors
* - round_result
* - X = loss
* - Y = draw
* - Z = win
*/
int score_round_part_2(char *opponents_shape, char *round_result) {
if (*round_result == 'X') {
char *loss_shape = get_loss_shape_part2(opponents_shape);
return score_shapes(*loss_shape);
} else if (*round_result == 'Y') {
// I have the same shape as the opponent
return 3 + score_shapes(*opponents_shape);
} else if (*round_result == 'Z') {
char *win_shape = get_win_shape_part2(opponents_shape);
return 6 + score_shapes(*win_shape);
} else {
return -1;
}
}
// score_part2
int score_file_part2(char **file_name, int *score) {
FILE *file = fopen(*file_name, "r");
if (file == NULL) {
printf("Error opening the file.\n");
return 2;
}
// int score = 0;
// Read the file
while (!feof(file)) {
char opponent;
char round_res;
int res = fscanf(file, "%s %s", &opponent, &round_res);
if (res == EOF) {
break;
}
// Check for blank line at the end of the file
else if (res == 1 && opponent == '\n') {
continue;
} else if (res != 2) {
printf("Error: Bad file format.\n");
return 3;
}
*score += score_round_part_2(&opponent, &round_res);
}
fclose(file);
// return score;
return 0;
}
int main(int argc, char *argv[]) {
char *file_name;
int solution_part;
int score = 0;
int res = arg_parser(argc, argv, &file_name, &solution_part);
if (res != 0) {
return res;
}
if (solution_part == 1) {
printf("My score: %d\n", score_file(&file_name));
} else {
int res = score_file_part2(&file_name, &score);
if (res != 0) {
return res;
}
printf("My score: %d\n", score);
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;
}
printf("Sum of possible game IDs: %d\n", possible_game_ids_sum);
printf("Sum of powers: %d\n", sum_of_powers);
return 0;
}

5
02/test.input Normal file
View File

@ -0,0 +1,5 @@
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

83
02/tests/CMakeLists.txt Normal file
View File

@ -0,0 +1,83 @@
set(PROJECT_NAME ${PROJECT_NAME} PARENT_SCOPE )
# GoogleTest requires at least C++14
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Get GoogleTest
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
add_subdirectory(src)
add_executable(tests ${TESTS})
# Link test executable against gtest & gtest_main
target_link_libraries(
tests
GTest::gtest_main
)
target_include_directories(tests PRIVATE
${CMAKE_SOURCE_DIR}/src
)
# Discover tests
include(GoogleTest)
gtest_discover_tests(tests)
add_dependencies(tests ${PROJECT_NAME})
# The following section is inspired by https://github.com/cmake-modules/lcov
if(ENABLE_COVERAGE)
message("Test coverage enabled")
# set(exclude_dir "*/tests/* */_deps/* /usr/include/c++/11/**/* /usr/include/c++/**/*")
# set(exclude_dir "*/tests/* */_deps/* /usr/include/c++/11/tuple /usr/include/c++/11/**/*")
# Check for lcov, gcov and genhtml
find_program(GCOV gcov)
if (NOT GCOV)
message(WARNING "gcov not found")
endif()
find_program(LCOV lcov)
if (NOT LCOV)
message(WARNING "lcov not found")
endif()
find_program(GENHTML genhtml)
if (NOT GENHTML)
message(WARNING "genhtml not found")
endif()
if (GCOV AND LCOV AND GENHTML)
# Set C compiler flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
# Set C++ compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
set(covname cov.info)
add_custom_target(coverage DEPENDS ${covname})
add_dependencies(coverage tests ${PROJECT_NAME})
add_custom_command(
OUTPUT ${covname}
COMMAND rm -rf **/coverage
COMMAND ${LCOV} -c -o ${covname} -d ${CMAKE_BINARY_DIR}/tests/CMakeFiles/tests.dir/ -b . --gcov-tool ${GCOV}
COMMAND ${LCOV} -r ${covname} -o ${covname} "*/tests/*" "*/_deps/**/*" "/usr/include/c++/**/*" "/usr/include/c++/11/**/*"
COMMAND ${LCOV} -l ${covname}
COMMAND ${GENHTML} ${covname} -output coverage
COMMAND ${LCOV} -l ${covname} 2>/dev/null | grep Total | sed 's/|//g' | sed 's/Total://g' | awk '{print $1}' | sed s/%//g > coverage/total
COMMAND rm -rf CMakeFiles/tests.dir/src/*.gcda CMakeFiles/tests.dir/src/*.gcno
COMMAND rm -f ${covname}
)
set_directory_properties(PROPERTIES
ADDITIONAL_CLEAN_FILES ${covname}
)
set_directory_properties(PROPERTIES
ADDITIONAL_CLEAN_FILES coverage/
)
else()
message(WARNING "Cannot enable coverage. Missing the required tools")
endif()
endif()

View File

@ -1,4 +0,0 @@
A Y
B X
C Z

View File

@ -0,0 +1,17 @@
# Make an explicit list of all source files in `IFJ23_TESTS`. This is important
# because CMake is not a build system: it is a build system generator. Suppose
# you add a file foo.cpp to src/ after running cmake .. . If you set
# `IFJ23_TESTS` with `file(GLOB ... )`, this is not passed to the makefile;
# the makefile doesn't know that foo.cpp exists and will not re-run cmake. Your
# collaborator's builds will fail and it will be unclear why. Whether you use
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
# file list, you know beforehand why your code isn't compiling.
set(TESTS
test.cpp
)
# Form the full path to the source files...
PREPEND(TESTS)
# ... and pass the variable to the parent scope.
set(TESTS ${TESTS} PARENT_SCOPE)

31
02/tests/src/test.cpp Normal file
View File

@ -0,0 +1,31 @@
#include <gtest/gtest.h>
#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() {}
~HelloTest() {}
void SetUp() {}
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);
}

View File

@ -1,39 +0,0 @@
{
"configurations": {
"Launch": {
"adapter": "vscode-cpptools",
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/output/main",
"args": [ "../tests/rucksacks.dat", "2" ],
"cwd": "${workspaceRoot}/output",
//"environment": [ ... ],
"externalConsole": true,
"MIMode": "gdb"
}
},
"Attach": {
"adapter": "vscode-cpptools",
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
"configuration": {
"request": "attach",
"program": "${workspaceRoot}/output/main",
"MIMode": "gdb"
}
},
"Launch prod": {
"adapter": "vscode-cpptools",
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/output/main",
"args": [ "rucksacks.dat", "2" ],
"cwd": "${workspaceRoot}/output",
//"environment": [ ... ],
"externalConsole": true,
"MIMode": "gdb"
}
}
}
}

View File

@ -1,91 +0,0 @@
#
# 'make' build executable file 'main'
# 'make clean' removes all .o and executable files
#
# define the C compiler to use CC = gcc
# define any compile-time flags
# CFLAGS := -std=c99 -Wall -Wextra -g -lm
CFLAGS := -std=c99 -Wall -Wextra -g
# define library paths in addition to /usr/lib
# if I wanted to include libraries not in /usr/lib I'd specify
# their path using -Lpath, something like:
LFLAGS =
# define output directory
OUTPUT := output
# define source directory
SRC := src
# define include directory
INCLUDE := include
# define lib directory
LIB := lib
ifeq ($(OS),Windows_NT)
MAIN := main.exe
SOURCEDIRS := $(SRC)
INCLUDEDIRS := $(INCLUDE)
LIBDIRS := $(LIB)
FIXPATH = $(subst /,\,$1)
RM := del /q /f
MD := mkdir
else
MAIN := main
SOURCEDIRS := $(shell find $(SRC) -type d)
INCLUDEDIRS := $(shell find $(INCLUDE) -type d)
LIBDIRS := $(shell find $(LIB) -type d)
FIXPATH = $1
RM = rm -f
MD := mkdir -p
endif
# define any directories containing header files other than /usr/include
INCLUDES := $(patsubst %,-I%, $(INCLUDEDIRS:%/=%))
# define the C libs
LIBS := $(patsubst %,-L%, $(LIBDIRS:%/=%))
# define the C source files
SOURCES := $(wildcard $(patsubst %,%/*.c, $(SOURCEDIRS)))
# define the C object files
OBJECTS := $(SOURCES:.c=.o)
#
# The following part of the makefile is generic; it can be used to
# build any executable just by changing the definitions above and by
# deleting dependencies appended to the file from 'make depend'
#
OUTPUTMAIN := $(call FIXPATH,$(OUTPUT)/$(MAIN))
all: $(OUTPUT) $(MAIN)
@echo Executing 'all' complete!
$(OUTPUT):
$(MD) $(OUTPUT)
$(MAIN): $(OBJECTS)
$(CC) $(INCLUDES) $(OBJECTS) $(LFLAGS) $(LIBS) -o $(OUTPUTMAIN) $(CFLAGS)
# this is a suffix replacement rule for building .o's from .c's
# it uses automatic variables $<: the name of the prerequisite of
# the rule(a .c file) and $@: the name of the target of the rule (a .o file)
# (see the gnu make manual section about automatic variables)
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
.PHONY: clean
clean:
$(RM) $(OUTPUTMAIN)
$(RM) $(call FIXPATH,$(OBJECTS))
@echo Cleanup complete!
run: all
./$(OUTPUTMAIN)
@echo Executing 'run: all' complete!

View File

@ -1,271 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Error codes:
* 0 - no error
* 1 - invalid arguments
* 2 - memory allocation error
* 3 - invalid file
* 4 - invalid file format
*/
/*
* Finds duplicate character in a given rucksack
* It finds the duplicates between the first and second compartments
* (first compartment is the first half of the rucksack, second compartment
* is the second half of the rucksack)
*
* Parameters:
* - char *str
* - The input string
*
* Returns:
* - char
* - The duplicate character
*/
char find_dup_char(char *str) {
int i, j;
int len = strlen(str);
char *first_compartment = (char *)malloc(len / 2);
char *second_compartment = (char *)malloc(len / 2);
char dup_char;
// Copy the first half of the rucksack to the first compartment
// Copy the second half of the rucksack to the second compartment
for (i = 0; i < len; i++) {
if (i < len / 2) {
first_compartment[i] = str[i];
} else {
second_compartment[i - len / 2] = str[i];
}
}
// Find the duplicate character
for (i = 0; i < len / 2; i++) {
for (j = 0; j < len / 2; j++) {
if (first_compartment[i] == second_compartment[j]) {
dup_char = first_compartment[i];
// Free the memory
free(first_compartment);
free(second_compartment);
return dup_char;
}
}
}
return '\0';
}
// Returns the score for a given character
int score_char(char c) {
// If the character is a capital letter
if (64 < c && c < 91) {
return c - 38;
}
// If the character is a lower case letter
else if (96 < c && c < 123) {
return c - 96;
} else {
return -1;
}
}
int score_file(char **filename, int *score) {
FILE *fp = fopen(*filename, "r");
if (fp == NULL) {
fprintf(stderr, "Error opening file `%s!\n", *filename);
return 3;
}
// Count the number of rucksacks
// One rucksack per line
// Ignore the empty lines
int num_rucksacks = 0;
// Get the number of rucksacks
// Number of lines in the file (without last empty line)
char line[300];
while (fgets(line, 100, fp) != NULL) {
if (strcmp(line, "\n") != 0)
num_rucksacks++;
}
rewind(fp);
// Alocate memory for the temporary rucksack
char *rucksack = malloc(100 * sizeof(char));
if (rucksack == NULL) {
fprintf(stderr, "Error allocating memory for rucksack\n");
return 2;
}
for (int i = 0; i < num_rucksacks; i++) {
// Get the rucksack
int res = fscanf(fp, "%s", rucksack);
if (res == EOF) {
break;
}
// Check for blank line at the end of the file
else if (res == 1 && strcmp(rucksack, "\n") == 0) {
i--;
continue;
} else if (res != 1) {
printf("Error: Bad file format.\n");
// Free the memory
free(rucksack);
fclose(fp);
return 4;
}
// Find the duplicate character and score it
*score += score_char(find_dup_char(rucksack));
}
// Free the memory
fclose(fp);
free(rucksack);
return 0;
}
/*
* NOTE: Part 2
* ------------------------------------------------------
*/
/* Find badge character
*
* Parameters:
* - char *rucksack 1
* - char *rucksack 2
* - char *rucksack 3
* Returns:
* - char
* - The badge character
*/
char find_badge(char *rucksack1, char *rucksack2, char *rucksack3) {
for (size_t i = 0; i < strlen(rucksack1); i++) {
for (size_t j = 0; j < strlen(rucksack2); j++) {
if (rucksack1[i] == rucksack2[j]) {
for (size_t k = 0; k < strlen(rucksack3); k++) {
if (rucksack1[i] == rucksack3[k]) {
return rucksack1[i];
}
}
}
}
}
return '\0';
}
/* Score badges in a file
*
* Parameters:
* - char **filename
* - The name of the file
* - The file must have one rucksack per line
* - 3 rucksacks are separated by a blank line
* - int *score
* - The score of the badges in the file
* Returns:
* - int
* - Error code
*/
int score_badges_file(char **filename, int *score) {
FILE *fp = fopen(*filename, "r");
if (fp == NULL) {
fprintf(stderr, "Error opening file `%s!\n", *filename);
return 3;
}
// Allocate memory for the rucksacks
char *rucksack1 = malloc(100 * sizeof(char));
char *rucksack2 = malloc(100 * sizeof(char));
char *rucksack3 = malloc(100 * sizeof(char));
// Iterate over the file
int res = fscanf(fp, "%s\n%s\n%s\n\n", rucksack1, rucksack2, rucksack3);
while (res != EOF) {
if (res != 3) {
fprintf(stderr, "Error: Bad file format.\n");
// Free the memory
free(rucksack1);
free(rucksack2);
free(rucksack3);
fclose(fp);
return 4;
}
// Find the badge character
char badge = find_badge(rucksack1, rucksack2, rucksack3);
// Score the badge
*score += score_char(badge);
res = fscanf(fp, "%s\n%s\n%s\n\n", rucksack1, rucksack2, rucksack3);
}
// Free the memory
free(rucksack1);
free(rucksack2);
free(rucksack3);
fclose(fp);
return 0;
}
int arg_parser(int argc, char *argv[], char **filename, int *part) {
if (argc != 3) {
printf("Usage: %s <file> <part (1,2)>\n", argv[0]);
return 1;
}
// Check if the file exists
FILE *fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "File %s does not exist\n", argv[1]);
return 3;
}
fclose(fp);
*filename = argv[1];
// Check if the part is valid
if (strcmp(argv[2], "1") != 0 && strcmp(argv[2], "2") != 0) {
fprintf(stderr, "Invalid part number: %s\n", argv[2]);
return 1;
}
*part = atoi(argv[2]);
return 0;
}
int main(int argc, char *argv[]) {
char *filename;
int part;
int score = 0;
int res = arg_parser(argc, argv, &filename, &part);
if (res != 0) {
return res;
}
if (part == 1) {
res = score_file(&filename, &score);
if (res != 0) {
return res;
}
} else {
res = score_badges_file(&filename, &score);
if (res != 0) {
return res;
}
}
printf("Score: %d\n", score);
return 0;
}

View File

@ -1,6 +0,0 @@
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw

View File

@ -1,26 +0,0 @@
{
"configurations": {
"Launch": {
"adapter": "vscode-cpptools",
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/output/main",
//"args": [ "", "" ],
"cwd": "${workspaceRoot}/output",
//"environment": [ ... ],
"externalConsole": true,
"MIMode": "gdb"
}
},
"Attach": {
"adapter": "vscode-cpptools",
"filetypes": [ "cpp", "c", "objc", "rust" ], // optional
"configuration": {
"request": "attach",
"program": "${workspaceRoot}/output/main",
"MIMode": "gdb"
}
}
}
}

View File

@ -1,91 +0,0 @@
#
# 'make' build executable file 'main'
# 'make clean' removes all .o and executable files
#
# define the C compiler to use CC = gcc
# define any compile-time flags
# CFLAGS := -std=c99 -Wall -Wextra -g -lm
CFLAGS := -std=c99 -Wall -Wextra -g
# define library paths in addition to /usr/lib
# if I wanted to include libraries not in /usr/lib I'd specify
# their path using -Lpath, something like:
LFLAGS =
# define output directory
OUTPUT := output
# define source directory
SRC := src
# define include directory
INCLUDE := include
# define lib directory
LIB := lib
ifeq ($(OS),Windows_NT)
MAIN := main.exe
SOURCEDIRS := $(SRC)
INCLUDEDIRS := $(INCLUDE)
LIBDIRS := $(LIB)
FIXPATH = $(subst /,\,$1)
RM := del /q /f
MD := mkdir
else
MAIN := main
SOURCEDIRS := $(shell find $(SRC) -type d)
INCLUDEDIRS := $(shell find $(INCLUDE) -type d)
LIBDIRS := $(shell find $(LIB) -type d)
FIXPATH = $1
RM = rm -f
MD := mkdir -p
endif
# define any directories containing header files other than /usr/include
INCLUDES := $(patsubst %,-I%, $(INCLUDEDIRS:%/=%))
# define the C libs
LIBS := $(patsubst %,-L%, $(LIBDIRS:%/=%))
# define the C source files
SOURCES := $(wildcard $(patsubst %,%/*.c, $(SOURCEDIRS)))
# define the C object files
OBJECTS := $(SOURCES:.c=.o)
#
# The following part of the makefile is generic; it can be used to
# build any executable just by changing the definitions above and by
# deleting dependencies appended to the file from 'make depend'
#
OUTPUTMAIN := $(call FIXPATH,$(OUTPUT)/$(MAIN))
all: $(OUTPUT) $(MAIN)
@echo Executing 'all' complete!
$(OUTPUT):
$(MD) $(OUTPUT)
$(MAIN): $(OBJECTS)
$(CC) $(INCLUDES) $(OBJECTS) $(LFLAGS) $(LIBS) -o $(OUTPUTMAIN) $(CFLAGS)
# this is a suffix replacement rule for building .o's from .c's
# it uses automatic variables $<: the name of the prerequisite of
# the rule(a .c file) and $@: the name of the target of the rule (a .o file)
# (see the gnu make manual section about automatic variables)
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
.PHONY: clean
clean:
$(RM) $(OUTPUTMAIN)
$(RM) $(call FIXPATH,$(OBJECTS))
@echo Cleanup complete!
run: all
./$(OUTPUTMAIN)
@echo Executing 'run: all' complete!

View File

@ -1,8 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("Hello world!\n");
return 0;
}

14
C_Template/.editorconfig Normal file
View File

@ -0,0 +1,14 @@
# EditorConfig is awesome: https://EditorConfig.org
# Project files
# Matches multiple files with brace expansion notation
[*.{c,h,cc}]
# Set charset
charset = utf-8
max_line_length = 80
# 2 space indentation
indent_style = space
indent_size = 2

82
C_Template/.gitignore vendored Normal file
View File

@ -0,0 +1,82 @@
# ClangD
.cache
# Nix files
.direnv
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
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

52
C_Template/CMakeLists.txt Normal file
View File

@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 3.14)
# Generate compile_commands.json
set(PROJECT_NAME CTemplate)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Turn on testing by default
option(BUILD_TESTING "Build tests" ON)
# Turn off documentation build by default
option(BUILD_DOC "Build documentation" OFF)
# Turn off coverage by default
option(ENABLE_COVERAGE "Enable test coverage" ON)
# Set C standard to C99
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
set(CMAKE_C_FLAGS_DEBUG "-std=c99 -Wall -Wextra -Wunreachable-code -g -O0")
# Set the project name and version number. This allows for a user of your
project(${PROJECT_NAME} VERSION 0.1)
set(${PROJECT_NAME} 0.1)
# Function to prepend the subdirectory to source files in subdirectories
FUNCTION(PREPEND var )
SET(listVar "")
FOREACH(f ${${var}})
LIST(APPEND listVar "${CMAKE_CURRENT_SOURCE_DIR}/${f}")
ENDFOREACH(f)
SET(${var} "${listVar}" PARENT_SCOPE)
ENDFUNCTION(PREPEND)
# Include source code and headers. This calls the CMakeLists.txt in each
# subdirectory. These can define their own libraries, executables, etc. as targets,
# but here we define all exportable targets in the root CMakeLists.txt.
add_subdirectory(src)
add_subdirectory(include)
# enable unit testing via "make test" once the code has been compiled.
# TODO: Google Test
if(BUILD_TESTING)
message("Testing enabled")
enable_testing()
add_subdirectory(tests)
target_include_directories(tests PRIVATE include)
endif()
# Add PROJECT_NAME as an executable target.
add_executable(${PROJECT_NAME} ${SRC} ${INC})
target_include_directories(${PROJECT_NAME} PRIVATE include)
if(BUILD_DOC)
add_subdirectory(docs)
endif()

View File

@ -0,0 +1,20 @@
# check if Doxygen is installed
find_package(Doxygen)
if (DOXYGEN_FOUND)
# set input and output files
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
# request to configure the file
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
message("Doxygen build started")
# note the option ALL which allows to build the docs together with the application
add_custom_target(doc ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating documentation with Doxygen"
VERBATIM )
else (DOXYGEN_FOUND)
message("Doxygen needs to be installed to generate the documentation")
endif (DOXYGEN_FOUND)

2826
C_Template/docs/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
# Make an explicit list of all source files in IFJ23_INC. This is important
# because CMake is not a build system: it is a build system generator. Suppose
# you add a file foo.cpp to src/ after running cmake .. . If you set
# IFJ23_INC with `file(GLOB ... )`, this is not passed to the makefile; it
# doesn't know that foo.cpp exists and will not re-run cmake. Your
# collaborator's builds will fail and it will be unclear why. Whether you use
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
# file list, you know beforehand why your code isn't compiling.
set(INC
)
# Form the full path to the source files...
PREPEND(INC)
# ... and pass the variable to the parent scope.
set(INC ${INC} PARENT_SCOPE)

0
C_Template/puzzle.input Normal file
View File

View File

@ -0,0 +1,17 @@
# Make an explicit list of all source files in `CMakeDemo_SRC`. This is important
# because CMake is not a build system: it is a build system generator. Suppose
# you add a file foo.cpp to src/ after running cmake .. . If you set
# `CMakeDemo_SRC` with `file(GLOB ... )`, this is not passed to the makefile;
# the makefile doesn't know that foo.cpp exists and will not re-run cmake. Your
# collaborator's builds will fail and it will be unclear why. Whether you use
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
# file list, you know beforehand why your code isn't compiling.
set(SRC
main.c
)
# Form the full path to the source files...
PREPEND(SRC)
# ... and pass the variable to the parent scope.
set(SRC ${SRC} PARENT_SCOPE)

25
C_Template/src/main.c Normal file
View File

@ -0,0 +1,25 @@
/**
* Copyright [2023] Jiří Štefka <jiriks74>
* Project: AdventOfCode
* @file main.c
* @brief Main entry point
* @author jiriks74
*/
#include <stdio.h>
/**
* @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
{
printf("Hello world!\n");
return 0;
}

View File

@ -0,0 +1,83 @@
set(PROJECT_NAME ${PROJECT_NAME} PARENT_SCOPE )
# GoogleTest requires at least C++14
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Get GoogleTest
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
add_subdirectory(src)
add_executable(tests ${TESTS})
# Link test executable against gtest & gtest_main
target_link_libraries(
tests
GTest::gtest_main
)
target_include_directories(tests PRIVATE
${CMAKE_SOURCE_DIR}/src
)
# Discover tests
include(GoogleTest)
gtest_discover_tests(tests)
add_dependencies(tests ${PROJECT_NAME})
# The following section is inspired by https://github.com/cmake-modules/lcov
if(ENABLE_COVERAGE)
message("Test coverage enabled")
# set(exclude_dir "*/tests/* */_deps/* /usr/include/c++/11/**/* /usr/include/c++/**/*")
# set(exclude_dir "*/tests/* */_deps/* /usr/include/c++/11/tuple /usr/include/c++/11/**/*")
# Check for lcov, gcov and genhtml
find_program(GCOV gcov)
if (NOT GCOV)
message(WARNING "gcov not found")
endif()
find_program(LCOV lcov)
if (NOT LCOV)
message(WARNING "lcov not found")
endif()
find_program(GENHTML genhtml)
if (NOT GENHTML)
message(WARNING "genhtml not found")
endif()
if (GCOV AND LCOV AND GENHTML)
# Set C compiler flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
# Set C++ compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -fprofile-arcs -ftest-coverage")
set(covname cov.info)
add_custom_target(coverage DEPENDS ${covname})
add_dependencies(coverage tests ${PROJECT_NAME})
add_custom_command(
OUTPUT ${covname}
COMMAND rm -rf **/coverage
COMMAND ${LCOV} -c -o ${covname} -d ${CMAKE_BINARY_DIR}/tests/CMakeFiles/tests.dir/ -b . --gcov-tool ${GCOV}
COMMAND ${LCOV} -r ${covname} -o ${covname} "*/tests/*" "*/_deps/**/*" "/usr/include/c++/**/*" "/usr/include/c++/11/**/*"
COMMAND ${LCOV} -l ${covname}
COMMAND ${GENHTML} ${covname} -output coverage
COMMAND ${LCOV} -l ${covname} 2>/dev/null | grep Total | sed 's/|//g' | sed 's/Total://g' | awk '{print $1}' | sed s/%//g > coverage/total
COMMAND rm -rf CMakeFiles/tests.dir/src/*.gcda CMakeFiles/tests.dir/src/*.gcno
COMMAND rm -f ${covname}
)
set_directory_properties(PROPERTIES
ADDITIONAL_CLEAN_FILES ${covname}
)
set_directory_properties(PROPERTIES
ADDITIONAL_CLEAN_FILES coverage/
)
else()
message(WARNING "Cannot enable coverage. Missing the required tools")
endif()
endif()

View File

@ -0,0 +1,17 @@
# Make an explicit list of all source files in `IFJ23_TESTS`. This is important
# because CMake is not a build system: it is a build system generator. Suppose
# you add a file foo.cpp to src/ after running cmake .. . If you set
# `IFJ23_TESTS` with `file(GLOB ... )`, this is not passed to the makefile;
# the makefile doesn't know that foo.cpp exists and will not re-run cmake. Your
# collaborator's builds will fail and it will be unclear why. Whether you use
# file(GLOB ...) or not, you will need to re-run cmake, but with an explicit
# file list, you know beforehand why your code isn't compiling.
set(TESTS
test.cpp
)
# Form the full path to the source files...
PREPEND(TESTS)
# ... and pass the variable to the parent scope.
set(TESTS ${TESTS} PARENT_SCOPE)

View File

@ -0,0 +1,31 @@
#include <gtest/gtest.h>
#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() {}
~HelloTest() {}
void SetUp() {}
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);
}

View File

@ -1,2 +1,11 @@
<p align="center">
<img src="https://gitea.stefka.eu/jiriks74/AdventOfCode/raw/branch/main/assets/logo.png" />
</p>
# AdventOfCode
This repository contains all my code I've made for [`Advent of code`](https://adventofcode.com)!
## Previous years
- [2022](https://gitea.stefka.eu/jiriks74/AdventOfCode/src/branch/2022)

BIN
assets/logo-hr.xcf Normal file

Binary file not shown.

BIN
assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
assets/logo.xcf Normal file

Binary file not shown.

12
default.nix Normal file
View File

@ -0,0 +1,12 @@
let
pkgs = import <nixpkgs> {};
in
pkgs.mkShell {
packages = with pkgs; [
# Choose the build tools that you need
gcc
gdb
cmake
];
}