diff --git a/.gitignore b/.gitignore index c6127b3..0e7fb71 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ +# Output folders +output/ + +# Vimspector +# .vimspector.json + # Prerequisites *.d diff --git a/01/.vimspector.json b/01/.vimspector.json new file mode 100644 index 0000000..c8baba7 --- /dev/null +++ b/01/.vimspector.json @@ -0,0 +1,39 @@ +{ + "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" + } + } + } +} diff --git a/01/Makefile b/01/Makefile new file mode 100644 index 0000000..3fb8222 --- /dev/null +++ b/01/Makefile @@ -0,0 +1,90 @@ +# +# '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! diff --git a/01/src/main.c b/01/src/main.c new file mode 100644 index 0000000..9813a3b --- /dev/null +++ b/01/src/main.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include + +struct elf { + int size; + int *calories; +}; + +int get_num_of_elves(const char *fileName) { + char line[300]; + int emptyLine = 0; + FILE *fp = fopen(fileName, "r"); + if (fp == NULL) { + printf("Error: Could not open specified file!\n"); + return -1; + } else { + 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; + } + } + } + fclose(fp); + return ++emptyLine; + } +} + +void load_data(int num_of_elves, char *filename, struct elf **arr) { + FILE *fp = fopen(filename, "r"); + if (fp == NULL) { + printf("Error: Could not open specified file!\n"); + return; + } + for (int i = 0; i < num_of_elves; i++) { + // Count number of lines until blank line + int num_of_lines = 0; + char line[300]; + int char_count = 0; + while (fgets(line, 300, fp)) { + int i = 0; + int len = strlen(line); + char_count += len; + for (i = 0; i < len; i++) { + if (line[i] != '\n' && line[i] != '\t' && line[i] != ' ') { + num_of_lines++; + break; + } + } + if (line[0] == '\n') { + break; + } + } + // Check for blank line at EOF + if(line[0] == EOF) { + break; + } + + if (num_of_lines == 0) { + i--; + continue; + } + + // Go back to start of current elf's data + fseek(fp, -char_count, SEEK_CUR); + + struct elf *data = *arr; + // Allocate memory for array + data[i].size = num_of_lines; + data[i].calories = malloc(num_of_lines * sizeof(int)); + + // Load the data + for (int j = 0; j < num_of_lines; j++) { + int res = fscanf(fp, "%d", &data[i].calories[j]); + if (res != 1){ + printf("Error, bad file format!"); + return; + } + } + } + fclose(fp); +} + +void count_elf_calories(struct elf **arr, int num_of_elves){ + struct elf *data = *arr; + for (int i = 0; i < num_of_elves; i++){ + int sum = 0; + for (int j = 0; j < data[i].size; j++){ + sum += data[i].calories[j]; + data[i].calories[j] = 0; + } + data[i].calories[0] = sum; + } +} + +char *argv_parser(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return NULL; + } + return argv[1]; +} + +int main(int argc, char *argv[]) { + struct elf *arr; + char *filename = argv_parser(argc, argv); + + if (filename == NULL) { + return 1; + } + + int num_of_elves = get_num_of_elves(filename); + if (num_of_elves == -1) { + return 1; + } + + arr = malloc(num_of_elves * sizeof(struct elf)); + + load_data(num_of_elves, filename, &arr); + + count_elf_calories(&arr, num_of_elves); + + // Print 3 elfs carrying 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 (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; + } + } + 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(arr); + return 0; +} diff --git a/01/tests/calories_test.dat b/01/tests/calories_test.dat new file mode 100644 index 0000000..2094f91 --- /dev/null +++ b/01/tests/calories_test.dat @@ -0,0 +1,14 @@ +1000 +2000 +3000 + +4000 + +5000 +6000 + +7000 +8000 +9000 + +10000 diff --git a/C_Tempate/.vimspector.json b/C_Tempate/.vimspector.json new file mode 100644 index 0000000..d24574a --- /dev/null +++ b/C_Tempate/.vimspector.json @@ -0,0 +1,26 @@ +{ + "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" + } + } + } +} diff --git a/C_Tempate/Makefile b/C_Tempate/Makefile new file mode 100644 index 0000000..0b969f8 --- /dev/null +++ b/C_Tempate/Makefile @@ -0,0 +1,91 @@ +# +# '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 := cluster.exe +SOURCEDIRS := $(SRC) +INCLUDEDIRS := $(INCLUDE) +LIBDIRS := $(LIB) +FIXPATH = $(subst /,\,$1) +RM := del /q /f +MD := mkdir +else +MAIN := cluster +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!