Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
17d14e61cc | |||
6f92d83c97 | |||
75f3b04e4f | |||
00e1df7490 | |||
deac11eb54 | |||
09fb2aea68 | |||
bf6d9e0a77 | |||
84acf0c823 | |||
d91bd4e375 | |||
72aed56663 | |||
e19fbc980b | |||
8a4b3174b8 | |||
c64b0d008c | |||
6f9d90bf4d | |||
c9d334aafe | |||
ca71b60025 | |||
ceefbcc3e7 | |||
597ef1259d | |||
118f3632a9 | |||
baf227ce23 | |||
96477dfba3 | |||
1f8dce3a86 | |||
7223f1b99b | |||
595837a4ac |
13
.editorconfig
Normal file
13
.editorconfig
Normal 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
|
||||||
|
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,4 +1,11 @@
|
|||||||
|
# ClangD
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Nix files
|
||||||
|
.direnv
|
||||||
|
|
||||||
# Output folders
|
# Output folders
|
||||||
|
build/
|
||||||
output/
|
output/
|
||||||
|
|
||||||
# Vimspector
|
# Vimspector
|
||||||
|
14
01/.editorconfig
Normal file
14
01/.editorconfig
Normal 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
74
01/.gitignore
vendored
Normal 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
|
||||||
|
|
@ -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
52
01/CMakeLists.txt
Normal 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()
|
90
01/Makefile
90
01/Makefile
@ -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
55
01/README.md
Normal 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
20
01/docs/CMakeLists.txt
Normal 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
2826
01/docs/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
16
01/include/CMakeLists.txt
Normal file
16
01/include/CMakeLists.txt
Normal 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
1001
01/puzzle.input
Normal file
File diff suppressed because it is too large
Load Diff
17
01/src/CMakeLists.txt
Normal file
17
01/src/CMakeLists.txt
Normal 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)
|
324
01/src/main.c
324
01/src/main.c
@ -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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct elf {
|
/**
|
||||||
int size;
|
* @brief Gets the first number in a string
|
||||||
int *calories;
|
* 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
|
||||||
// Gets the number of elves in the input file.
|
* words.
|
||||||
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.
|
|
||||||
*/
|
*/
|
||||||
void load_data(int num_of_elves, char *filename, struct elf **arr) {
|
int getNum(const char *line) {
|
||||||
// Open the file
|
char *str = (char *)line;
|
||||||
FILE *fp = fopen(filename, "r");
|
// 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
|
// Find first written number
|
||||||
if (fp == NULL) {
|
char *smallestPos = strchr(str, *"\0");
|
||||||
printf("Error: Could not open specified file!\n");
|
int numAtSmallPos = -1;
|
||||||
return;
|
for (int i = 0; i < sizeof(numbers) / sizeof(numbers[0]); i++) {
|
||||||
}
|
char *pos = NULL;
|
||||||
|
|
||||||
// Go through each elf
|
char *written = strstr(str, numbers[i]);
|
||||||
for (int i = 0; i < num_of_elves; i++) {
|
char *digit = strstr(str, digits[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;
|
|
||||||
|
|
||||||
// Go through the elve's data
|
if (written == NULL && digit == NULL)
|
||||||
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--;
|
|
||||||
continue;
|
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
|
if (pos < smallestPos) {
|
||||||
fseek(fp, -char_count, SEEK_CUR);
|
numAtSmallPos = i;
|
||||||
|
smallestPos = pos;
|
||||||
// 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
|
// Chen which was first and return it
|
||||||
fclose(fp);
|
return numAtSmallPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count all the calories each elf has
|
/**
|
||||||
// Params:
|
* @brief Gets a calibration value from a line
|
||||||
// - int num_of_elves: The number of elves in the input file.
|
* @param char* line containing the calibration value
|
||||||
// - struct elf *elves: The array with the data.
|
* @return int the calibration value
|
||||||
void count_elf_calories(struct elf **arr, int num_of_elves) {
|
*/
|
||||||
// Reference the array
|
int getVal(const char *str) {
|
||||||
struct elf *data = *arr;
|
int result = 0;
|
||||||
|
int result2 = -1;
|
||||||
// Go through each elf
|
for (int i = 0; i < strlen(str); i++) {
|
||||||
for (int i = 0; i < num_of_elves; i++) {
|
int num = getNum(&str[i]);
|
||||||
// Sum of the callories for the current elf
|
if (num >= 0) {
|
||||||
int sum = 0;
|
if (result == 0) {
|
||||||
|
result = num * 10;
|
||||||
// Go through the elve's calories
|
} else {
|
||||||
for (int j = 0; j < data[i].size; j++) {
|
result2 = num;
|
||||||
// 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 (result2 == -1) {
|
||||||
|
result += result / 10;
|
||||||
|
} else {
|
||||||
|
result += result2;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Argument parser
|
/**
|
||||||
char *argv_parser(int argc, char *argv[]) {
|
* @brief Main entry point
|
||||||
// This program has only one argument
|
* @param argc Number of command-line arguments.
|
||||||
if (argc != 2) {
|
* @param argv Array of command-line arguments.
|
||||||
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
|
*/
|
||||||
return NULL;
|
#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
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the argument as pos 1 (the filename)
|
// LCOV_EXCL_START
|
||||||
return argv[1];
|
if (file == NULL) {
|
||||||
}
|
if (argc > 1)
|
||||||
|
fprintf(stderr, "Could not open file '%s'\n", argv[1]);
|
||||||
int main(int argc, char *argv[]) {
|
else
|
||||||
// The array of elves
|
fprintf(stderr, "Couldn't open file\n");
|
||||||
struct elf *arr;
|
exit(EXIT_FAILURE);
|
||||||
// Get the filename
|
}
|
||||||
char *filename = argv_parser(argc, argv);
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
// Get the number of elves in the file
|
char *line = NULL;
|
||||||
int num_of_elves = get_num_of_elves(filename);
|
size_t len = 0;
|
||||||
// Check if the operation was successful
|
ssize_t read = 0;
|
||||||
if (num_of_elves == -1) {
|
int result = 0;
|
||||||
return 1;
|
while ((read = getline(&line, &len, file) != -1)) {
|
||||||
}
|
result += getVal(line);
|
||||||
|
}
|
||||||
// Alocate the memory for the array
|
|
||||||
arr = malloc(num_of_elves * sizeof(struct elf));
|
free(line);
|
||||||
|
fclose(file);
|
||||||
// Load all the elve's calorias
|
|
||||||
load_data(num_of_elves, filename, &arr);
|
printf("The sum of the calibration values is %d\n", result);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
83
01/tests/CMakeLists.txt
Normal file
83
01/tests/CMakeLists.txt
Normal 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()
|
@ -1,14 +0,0 @@
|
|||||||
1000
|
|
||||||
2000
|
|
||||||
3000
|
|
||||||
|
|
||||||
4000
|
|
||||||
|
|
||||||
5000
|
|
||||||
6000
|
|
||||||
|
|
||||||
7000
|
|
||||||
8000
|
|
||||||
9000
|
|
||||||
|
|
||||||
10000
|
|
17
01/tests/src/CMakeLists.txt
Normal file
17
01/tests/src/CMakeLists.txt
Normal 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
81
01/tests/src/test.cpp
Normal 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
14
02/.editorconfig
Normal 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
64
02/.gitignore
vendored
Normal 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
|
@ -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
52
02/CMakeLists.txt
Normal 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()
|
91
02/Makefile
91
02/Makefile
@ -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
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?
|
||||||
|
|
20
02/docs/CMakeLists.txt
Normal file
20
02/docs/CMakeLists.txt
Normal 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
2826
02/docs/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
16
02/include/CMakeLists.txt
Normal file
16
02/include/CMakeLists.txt
Normal 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
101
02/puzzle.input
Normal 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
17
02/src/CMakeLists.txt
Normal 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)
|
364
02/src/main.c
364
02/src/main.c
@ -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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/* Error codes:
|
const int MAX_RED = 12;
|
||||||
* 0 - no error
|
const int MAX_GREEN = 13;
|
||||||
* 1 - invalid number of arguments
|
const int MAX_BLUE = 14;
|
||||||
* 2 - invalid file
|
|
||||||
* 3 - invalid file format
|
typedef struct {
|
||||||
* 4 - invalid solution part
|
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:
|
while (curr != NULL) {
|
||||||
* The aliases for rock, paper, scissors are:
|
char *end_show = strchr(curr, ';');
|
||||||
* - A = X = rock
|
|
||||||
* - B = Y = paper
|
|
||||||
* - C = Z = scissors
|
|
||||||
* ------------------------------------------
|
|
||||||
* Scores:
|
|
||||||
* - Shape
|
|
||||||
* - Rock: 1
|
|
||||||
* - Paper: 2
|
|
||||||
* - Scissors: 3
|
|
||||||
* - Outcome
|
|
||||||
* - Win: 6
|
|
||||||
* - Draw: 3
|
|
||||||
* - Loss: 0
|
|
||||||
*/
|
|
||||||
|
|
||||||
int arg_parser(int argc, char *argv[], char **file_name, int *solution_part) {
|
if (end_show != NULL) {
|
||||||
if (argc != 3) {
|
*end_show = '\0';
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*file_name = argv[1];
|
while (curr != NULL) {
|
||||||
*solution_part = atoi(argv[2]);
|
int cube_count = atoi(curr);
|
||||||
|
|
||||||
return 0;
|
curr = strchr(curr, ' ');
|
||||||
}
|
curr += sizeof(char);
|
||||||
|
|
||||||
// Returns the score of the given shape
|
if (*curr == 'r') {
|
||||||
// 1 = rock, 2 = paper, 3 = scissors
|
if (cube_count > result.red)
|
||||||
int score_shapes(char shape) {
|
result.red = cube_count;
|
||||||
switch (shape) {
|
} else if (*curr == 'g') {
|
||||||
case 'A':
|
if (cube_count > result.green)
|
||||||
case 'X':
|
result.green = cube_count;
|
||||||
return 1;
|
} else if (*curr == 'b') {
|
||||||
case 'B':
|
if (cube_count > result.blue)
|
||||||
case 'Y':
|
result.blue = cube_count;
|
||||||
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;
|
|
||||||
} else {
|
} 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end_show != NULL) {
|
||||||
|
*end_show = ';';
|
||||||
|
curr = end_show + sizeof(char) * 2;
|
||||||
|
} else
|
||||||
|
curr = end_show;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int score_file(char **file_name) {
|
/**
|
||||||
FILE *file = fopen(*file_name, "r");
|
* @brief Count how many times were the cubes shown
|
||||||
if (file == NULL) {
|
* @return Number of shows or -1 when error occurs
|
||||||
printf("Error opening the file.\n");
|
*/
|
||||||
return -2;
|
bool is_game_possible(char *game) {
|
||||||
}
|
// char *curr = strchr(game, ':');
|
||||||
|
// curr += sizeof(char) * 2;
|
||||||
|
|
||||||
int my_score = 0;
|
// if (curr == NULL) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
// Read the file
|
GameShow show_counts = get_max_cube_counts(game);
|
||||||
while (!feof(file)) {
|
|
||||||
char opponent[1];
|
|
||||||
char me[1];
|
|
||||||
int res = fscanf(file, "%s %s", opponent, me);
|
|
||||||
|
|
||||||
if (res == EOF) {
|
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;
|
break;
|
||||||
}
|
|
||||||
// Check for blank line at the end of the file
|
int curr_game_id = atoi(line + sizeof("Game"));
|
||||||
else if (res == 1 && opponent[0] == '\n') {
|
|
||||||
continue;
|
// if (is_game_possible(line)) {
|
||||||
} else if (res != 2) {
|
if (is_game_possible(strchr(line, ':') + sizeof(char) * 2)) {
|
||||||
printf("Error: Bad file format.\n");
|
possible_game_ids_sum += curr_game_id;
|
||||||
return -3;
|
// printf("Game %d is possible\n", curr_game_id);
|
||||||
}
|
} // else
|
||||||
|
// printf("Game %d is impossible\n", curr_game_id);
|
||||||
my_score += round_score(*opponent, *me);
|
GameShow min_cubes =
|
||||||
}
|
get_max_cube_counts(strchr(line, ':') + sizeof(char) * 2);
|
||||||
fclose(file);
|
sum_of_powers += min_cubes.red * min_cubes.green * min_cubes.blue;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("Sum of possible game IDs: %d\n", possible_game_ids_sum);
|
||||||
|
printf("Sum of powers: %d\n", sum_of_powers);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
5
02/test.input
Normal file
5
02/test.input
Normal 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
83
02/tests/CMakeLists.txt
Normal 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()
|
@ -1,4 +0,0 @@
|
|||||||
A Y
|
|
||||||
B X
|
|
||||||
C Z
|
|
||||||
|
|
17
02/tests/src/CMakeLists.txt
Normal file
17
02/tests/src/CMakeLists.txt
Normal 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
31
02/tests/src/test.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
91
03/Makefile
91
03/Makefile
@ -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!
|
|
271
03/src/main.c
271
03/src/main.c
@ -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;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
vJrwpWtwJgWrhcsFMMfFFhFp
|
|
||||||
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
|
|
||||||
PmmdzqPrVvPwwTWBwg
|
|
||||||
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
|
|
||||||
ttgJtRGJQctTZtZT
|
|
||||||
CrZsJsPPZsGzwwsLwLmpwMDw
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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!
|
|
@ -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
14
C_Template/.editorconfig
Normal 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
82
C_Template/.gitignore
vendored
Normal 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
52
C_Template/CMakeLists.txt
Normal 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()
|
20
C_Template/docs/CMakeLists.txt
Normal file
20
C_Template/docs/CMakeLists.txt
Normal 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
2826
C_Template/docs/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
16
C_Template/include/CMakeLists.txt
Normal file
16
C_Template/include/CMakeLists.txt
Normal 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
0
C_Template/puzzle.input
Normal file
17
C_Template/src/CMakeLists.txt
Normal file
17
C_Template/src/CMakeLists.txt
Normal 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
25
C_Template/src/main.c
Normal 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;
|
||||||
|
}
|
83
C_Template/tests/CMakeLists.txt
Normal file
83
C_Template/tests/CMakeLists.txt
Normal 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()
|
17
C_Template/tests/src/CMakeLists.txt
Normal file
17
C_Template/tests/src/CMakeLists.txt
Normal 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
C_Template/tests/src/test.cpp
Normal file
31
C_Template/tests/src/test.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1,11 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="https://gitea.stefka.eu/jiriks74/AdventOfCode/raw/branch/main/assets/logo.png" />
|
||||||
|
</p>
|
||||||
|
|
||||||
# AdventOfCode
|
# AdventOfCode
|
||||||
|
|
||||||
This repository contains all my code I've made for [`Advent of code`](https://adventofcode.com)!
|
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
BIN
assets/logo-hr.xcf
Normal file
Binary file not shown.
BIN
assets/logo.png
Normal file
BIN
assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/logo.xcf
Normal file
BIN
assets/logo.xcf
Normal file
Binary file not shown.
12
default.nix
Normal file
12
default.nix
Normal 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
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user