advent-of-code-2021

My solutions for AoC 2021
git clone https://git.sr.ht/~jbauer/advent-of-code-2021
Log | Files | Refs | README | LICENSE

commit 61120a7518c015c1f29222c70917cc3f5f75171d
Author: Jake Bauer <jbauer@paritybit.ca>
Date:   Wed, 30 Nov 2022 18:39:23 -0500

Initial commit

Diffstat:
ALICENSE | 15+++++++++++++++
AREADME.md | 3+++
Aday1/main1.c | 46++++++++++++++++++++++++++++++++++++++++++++++
Aday1/main2.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aday2/main1.c | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Aday2/main2.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Aday3/main1.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aday3/main2.c | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aday4/input.txt | 19+++++++++++++++++++
Aday4/main.c | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aday5/input.txt | 10++++++++++
Aday5/main.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aday6/main.c | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aday7/main.c | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aday8/input.txt | 10++++++++++
Aday8/main.c | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16 files changed, 1134 insertions(+), 0 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright 2021 Jake Bauer <jbauer@paritybit.ca> + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/README.md b/README.md @@ -0,0 +1,3 @@ +# Advent of Code 2021 + +My solutions for Advent of Code 2021, written in C. diff --git a/day1/main1.c b/day1/main1.c @@ -0,0 +1,46 @@ +#include <stdio.h> +#include <stdlib.h> + +FILE * +openInputFile(void) +{ + FILE *fp = fopen("input.txt","r"); + if (fp == NULL) + { + printf("Could not open file: input.txt\n"); + exit(EXIT_FAILURE); + } + return fp; +} + +int +main(void) +{ + char *line = NULL; + int increases = 0; + int currentValue = 0; + int previousValue = -1; + size_t len = 0; + ssize_t read; + + FILE *fp = openInputFile(); + + while ((read = getline(&line, &len, fp)) != -1) + { + if (previousValue < 0) + previousValue = atoi(line); + + currentValue = atoi(line); + + if (currentValue > previousValue) + increases++; + + previousValue = currentValue; + } + + fclose(fp); + if (line) + free(line); + printf("%d\n", increases); + exit(EXIT_SUCCESS); +} diff --git a/day1/main2.c b/day1/main2.c @@ -0,0 +1,68 @@ +#include <stdio.h> +#include <stdlib.h> + +#define ARR_SIZE 3 + +FILE * +openInputFile(void) +{ + FILE *fp = fopen("input.txt","r"); + if (fp == NULL) + { + printf("Could not open file: input.txt\n"); + exit(EXIT_FAILURE); + } + return fp; +} + +int +sumArray(int *array, int size) +{ + int sum = 0; + for (int i = 0; i < size; i++) + sum += array[i]; + return sum; +} + +int +main(void) +{ + FILE *fp = openInputFile(); + int increases = 0; + + int array[ARR_SIZE] = { 0 }; + int arrayPosition = 0; + int currentSum = 0; + int previousSum = 0; + int firstFill = 1; + + char *line = NULL; + size_t len = 0; + ssize_t read; + while ((read = getline(&line, &len, fp)) != -1) + { + if (arrayPosition == ARR_SIZE) { + if (firstFill) + previousSum = currentSum; + firstFill = 0; + arrayPosition = 0; + } + + currentSum = sumArray(array, ARR_SIZE); + array[arrayPosition++] = atoi(line); + + // Don't do comparisons until we've filled the array + if (firstFill) + continue; + + if (currentSum > previousSum) + increases++; + previousSum = currentSum; + } + + fclose(fp); + if (line) + free(line); + printf("%d\n", increases); + exit(EXIT_SUCCESS); +} diff --git a/day2/main1.c b/day2/main1.c @@ -0,0 +1,49 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +FILE * +openInputFile(void) +{ + FILE *fp = fopen("input.txt","r"); + if (fp == NULL) + { + printf("Could not open file: input.txt\n"); + exit(EXIT_FAILURE); + } + return fp; +} + +int +main(void) +{ + FILE *fp = openInputFile(); + + int position = 0; + int depth = 0; + + char *line = NULL; + size_t len = 0; + ssize_t read; + while ((read = getline(&line, &len, fp)) != -1) + { + char *direction = strtok(line, " "); + int magnitude = atoi(strtok(NULL, " ")); + + if (strcmp("forward", direction) == 0) + position += magnitude; + else if (strcmp ("down", direction) == 0) + depth += magnitude; + else + depth -= magnitude; + } + + printf("Final position: %d\n", position); + printf("Final depth: %d\n", depth); + printf("Product: %d\n", position * depth); + + fclose(fp); + if (line) + free(line); + exit(EXIT_SUCCESS); +} diff --git a/day2/main2.c b/day2/main2.c @@ -0,0 +1,53 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +FILE * +openInputFile(void) +{ + FILE *fp = fopen("input.txt","r"); + if (fp == NULL) + { + printf("Could not open file: input.txt\n"); + exit(EXIT_FAILURE); + } + return fp; +} + +int +main(void) +{ + FILE *fp = openInputFile(); + + int position = 0; + int depth = 0; + int aim = 0; + + char *line = NULL; + size_t len = 0; + ssize_t read; + while ((read = getline(&line, &len, fp)) != -1) + { + char *direction = strtok(line, " "); + int magnitude = atoi(strtok(NULL, " ")); + + if (strcmp("forward", direction) == 0) + { + position += magnitude; + depth += aim * magnitude; + } + else if (strcmp ("down", direction) == 0) + aim += magnitude; + else + aim -= magnitude; + } + + printf("Final position: %d\n", position); + printf("Final depth: %d\n", depth); + printf("Product: %d\n", position * depth); + + fclose(fp); + if (line) + free(line); + exit(EXIT_SUCCESS); +} diff --git a/day3/main1.c b/day3/main1.c @@ -0,0 +1,117 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define ENTRY_LENGTH 12 + +FILE * +openInputFile(void) +{ + FILE *fp = fopen("input.txt","r"); + if (fp == NULL) + { + printf("Could not open file: input.txt\n"); + exit(EXIT_FAILURE); + } + return fp; +} + +struct list { + size_t used; + size_t size; + int *contents; +}; + +int +createList(struct list *list, size_t initialSize) +{ + list->contents = (int *) malloc(initialSize * sizeof(int)); + if (list->contents == NULL) + return 1; + list->used = 0; + list->size = initialSize; + return 0; +} + +int +insertIntoList(struct list *list, int item) +{ + if (list->used == list->size) + { + list->size *= 2; + list->contents = (int *) realloc(list->contents, list->size * sizeof(int)); + if (list->contents == NULL) + return 1; + } + list->contents[list->used++] = item; + return 0; +} + +void +freeList(struct list *list) +{ + free(list->contents); +} + +// Just computes most common value from a set of 1 or 0 because nothing more is +// needed for this challenge +int +mostCommonValue(struct list *list) +{ + int numZeros = 0; + int numOnes = 0; + for (int i = 0; i < list->used; i++) + { + if (list->contents[i] == 0) + numZeros++; + else + numOnes++; + } + if (numZeros > numOnes) + return 0; + else + return 1; +} + +int +main(void) +{ + FILE *fp = openInputFile(); + + struct list bits[ENTRY_LENGTH]; + for (int i = 0; i < ENTRY_LENGTH; i ++) + if (createList(&bits[i], 1) != 0) + exit(EXIT_FAILURE); + + char *line = NULL; + size_t len = 0; + ssize_t read; + while ((read = getline(&line, &len, fp)) != -1) + { + for (int i = 0; i < ENTRY_LENGTH; i ++) + insertIntoList(&bits[i], line[i] - '0'); + } + + int gamma = 0; + + for (int i = 0; i < ENTRY_LENGTH; i++) + { + printf("%d: %d\n", i, mostCommonValue(&bits[i])); + if (mostCommonValue(&bits[i])) + gamma = gamma | (1 << (ENTRY_LENGTH - i - 1)) ; + printf("Gamma is: %x\n", gamma); + } + + int epsilon = ~gamma & ((1 << ENTRY_LENGTH) - 1); + + printf(" Gamma %d\n", gamma); + printf("Epsilon %d\n", epsilon); + printf("Product %d\n", gamma * epsilon); + + fclose(fp); + if (line) + free(line); + for (int i = 0; i < ENTRY_LENGTH; i++) + freeList(&bits[i]); + exit(EXIT_SUCCESS); +} diff --git a/day3/main2.c b/day3/main2.c @@ -0,0 +1,133 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define ENTRY_LENGTH 12 + +FILE * +openInputFile(void) +{ + FILE *fp = fopen("input.txt","r"); + if (fp == NULL) + { + printf("Could not open file: input.txt\n"); + exit(EXIT_FAILURE); + } + return fp; +} + +struct list { + size_t used; + size_t size; + int *contents; +}; + +int +createList(struct list *list, size_t initialSize) +{ + list->contents = (int *) malloc(initialSize * sizeof(int)); + if (list->contents == NULL) + return 1; + list->used = 0; + list->size = initialSize; + return 0; +} + +int +insertIntoList(struct list *list, int item) +{ + if (list->used == list->size) + { + list->size *= 2; + list->contents = (int *) realloc(list->contents, list->size * sizeof(int)); + if (list->contents == NULL) + return 1; + } + list->contents[list->used++] = item; + return 0; +} + +void +freeList(struct list *list) +{ + free(list->contents); +} + +//TODO Make a function that handles deleting an element from the list by index + +//TODO Make a function that duplicates a list + +// Just computes most common value from a set of 1 or 0 because nothing more is +// needed for this challenge +int +mostCommonValue(struct list *list) +{ + int numZeros = 0; + int numOnes = 0; + for (int i = 0; i < list->used; i++) + { + if (list->contents[i] == 0) + numZeros++; + else + numOnes++; + } + if (numZeros > numOnes) + return 0; + else + return 1; +} + +int +main(void) +{ + FILE *fp = openInputFile(); + + struct list bits[ENTRY_LENGTH]; + for (int i = 0; i < ENTRY_LENGTH; i ++) + if (createList(&bits[i], 1) != 0) + exit(EXIT_FAILURE); + + // TODO For Part 2: + // Add each _line_ into a list as a list of strings (not ints) + // (Duplicate the list for the second calculation) + // Iterate over each element, picking the nth bit and add that to a list + // of ints + // Compute the most common number (1 or 0) + // Iterate over each element again and remove the entries which don't + // start with the most common number + // Repeat until one number remains -> this is the result value + // Do the same for the second calculation, but take the least common + // number instead of the most common + + char *line = NULL; + size_t len = 0; + ssize_t read; + while ((read = getline(&line, &len, fp)) != -1) + { + for (int i = 0; i < ENTRY_LENGTH; i ++) + insertIntoList(&bits[i], line[i] - '0'); + } + + int gamma = 0; + + for (int i = 0; i < ENTRY_LENGTH; i++) + { + printf("%d: %d\n", i, mostCommonValue(&bits[i])); + if (mostCommonValue(&bits[i])) + gamma = gamma | (1 << (ENTRY_LENGTH - i - 1)) ; + printf("Gamma is: %x\n", gamma); + } + + int epsilon = ~gamma & ((1 << ENTRY_LENGTH) - 1); + + printf(" Gamma %d\n", gamma); + printf("Epsilon %d\n", epsilon); + printf("Product %d\n", gamma * epsilon); + + fclose(fp); + if (line) + free(line); + for (int i = 0; i < ENTRY_LENGTH; i++) + freeList(&bits[i]); + exit(EXIT_SUCCESS); +} diff --git a/day4/input.txt b/day4/input.txt @@ -0,0 +1,19 @@ +7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 + +22 13 17 11 0 + 8 2 23 4 24 +21 9 14 16 7 + 6 10 3 18 5 + 1 12 20 15 19 + + 3 15 0 2 22 + 9 18 13 17 5 +19 8 7 25 23 +20 11 10 24 4 +14 21 16 12 6 + +14 21 17 24 4 +10 16 15 9 19 +18 8 23 26 20 +22 11 13 6 5 + 2 0 12 3 7 diff --git a/day4/main.c b/day4/main.c @@ -0,0 +1,104 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +struct bingocard +{ + char *card[5][5]; + int hits[5][5]; + char *name; +}; + +static int +getline(char* line, FILE* fp, int length) +{ + for (int i = 0; i < length; i++) + { + line[i] = fgetc(fp); + if (line[i] == EOF) + return -1; + } + line[length-1] = '\0'; + + return 0; +} + +static int +getlinelength(FILE *fp) +{ + int linelength = 0; + long offset = ftell(fp); + for (;;) + { + if (fgetc(fp) == '\n') + { + linelength += 1; + break; + } + else + { + linelength += 1; + } + } + fseek(fp, offset, SEEK_SET); // seek back to beginning of line + return linelength; +} + +int +main(void) +{ + printf("Opening input.txt\n"); + FILE *fp = fopen("input.txt","r"); + if (fp == NULL) + { + printf("Could not open file: input.txt\n"); + exit(EXIT_FAILURE); + } + + // First line of file is all the numbers drawn + char *drawsline = (char *) malloc(getlinelength(fp)+1); + getline(drawsline, fp, getlinelength(fp)+1); + + // Figure out how many numbers are drawn in total + int numelements = 0; + for (size_t i = 0; i < strlen(drawsline); i ++) + if (strncmp(&drawsline[i], ",", 1) || drawsline[i] == '\0') + numelements += 1; + printf("There are %d numbers drawn\n", numelements); + + // Create an array from that string + char **draws = (char **) malloc(numelements * sizeof(char)); + if (draws == NULL) + { + printf("Unable to allocate memory for drawn values.\n"); + exit(EXIT_FAILURE); + } + + // THIS BREAKS THINGS ON WINDOWS FOR SOME REASON??? + // NOT INFINITE LOOP, PROGRAM EXITS BUT DOESN'T PRINT + // ANYMORE + // ... Maybe I should write my own strtok + char *token = strtok(drawsline, ","); + int index; + while (token != NULL) + { + draws[index++] = token; + printf("Consumed: %s\n", token); + token = strtok(NULL, ","); + } + + printf("["); + for (int i = 0; i < numelements; i++) + printf("%s,", draws[i]); + printf("]\n"); + + // Now parse bingo cards + + fclose(fp); + if (draws) + { + free(draws); + } + + exit(EXIT_SUCCESS); +} diff --git a/day5/input.txt b/day5/input.txt @@ -0,0 +1,10 @@ +0,9 -> 5,9 +8,0 -> 0,8 +9,4 -> 3,4 +2,2 -> 2,1 +7,0 -> 7,4 +6,4 -> 2,0 +0,9 -> 2,9 +3,4 -> 1,4 +0,0 -> 8,8 +5,5 -> 8,2 diff --git a/day5/main.c b/day5/main.c @@ -0,0 +1,101 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define ENTRY_LENGTH 10 + +int seafloor[10][10] = { + {0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0}, +}; + +static int +getline(char* line, FILE* fp, int length) +{ + for (int i = 0; i < length; i++) + { + line[i] = fgetc(fp); + if (line[i] == EOF) + return -1; + } + line[length-1] = '\0'; + + return 0; +} + +int +main(void) +{ + FILE *fp = fopen("input.txt","r"); + if (fp == NULL) + { + printf("Could not open file: input.txt\n"); + exit(EXIT_FAILURE); + } + + char *line = (char *)malloc(ENTRY_LENGTH + 2); + while ((getline(line, fp, ENTRY_LENGTH + 1)) != -1) + { + // printf("Got line: %s", line); + int x1 = line[0] - '0'; + int y1 = line[2] - '0'; + int x2 = line[7] - '0'; + int y2 = line[9] - '0'; + + + if (x1 == x2) + { + printf("Coordinates: (%d,%d) -> (%d,%d)\n", x1, y1, x2, y2); + if (y1 < y2) + for (int i = 0; i <= y2-y1; i++) + seafloor[y1+i][x1] += 1; + else + for (int i = 0; i <= y1-y2; i++) + seafloor[y1-i][x1] += 1; + } + else if (y1 == y2) + { + printf("Coordinates: (%d,%d) -> (%d,%d)\n", x1, y1, x2, y2); + if (x1 < x2) + for (int i = 0; i <= x2-x1; i++) + seafloor[y1][x1+i] += 1; + else + for (int i = 0; i <= x1-x2; i++) + seafloor[y1][x1-i] += 1; + } + else + { + continue; + } + + printf (" 0 1 2 3 4 5 6 7 8 9\n"); + for (int i = 0; i < 10; i++) + { + printf(" %d ", i); + for (int j = 0; j < 10; j++) + printf("%d ", seafloor[i][j]); + printf("\n"); + } + } + fclose(fp); + if (line) + free(line); + + int dangerzones = 0; + for (int i = 0; i < 10; i++) + for (int j = 0; j < 10; j++) + if (seafloor[i][j] > 1) + dangerzones += 1; + + printf("There are %d dangerous zones!\n", dangerzones); + exit(EXIT_SUCCESS); +} diff --git a/day6/main.c b/day6/main.c @@ -0,0 +1,157 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <locale.h> + +// List contains elements of type char which cuts memory utilization down to a +// quarter compared to using ints. Max value we need to track is 8, which fits +// handily into a char and doesn't require 4 Bytes. +// (Could pack values into a nibble, or even pack eight values into three bytes +// but that seems a bit extreme and complicated); +struct list { + size_t used; + size_t size; + char *contents; +}; + +int +createList(struct list *list) +{ + list->used = 0; + list->size = 1; + list->contents = (char *) malloc(1 * sizeof(char)); + if (list->contents == NULL) + return 1; + return 0; +} + +int +insertIntoList(struct list *list, char item) +{ + // Grow list (double its size) when full + if (list->used == list->size) + { + list->size *= 2; + list->contents = (char *) realloc(list->contents, list->size * sizeof(char)); + + // Print new mem usage + float mem_used = (float) list->size * sizeof(char); + if (mem_used / 1073741824.0 > 1 ) + printf("Size of list: %.2f GiB.\n", mem_used / 1073741824.0); + else if (mem_used / 1048576.0 > 1) + printf("Size of list: %.2f MiB.\n", mem_used / 1048576.0); + else if (mem_used / 1024.0 > 1) + printf("Size of list: %.2f KiB.\n", mem_used / 1024.0); + else + printf("Size of list: %.2f Bytes.\n", mem_used); + + if (list->contents == NULL) + return 1; + } + list->contents[list->used++] = item; + return 0; +} + +void +freeList(struct list *list) +{ + free(list->contents); +} + +int +main(int argc, char **argv) +{ + setlocale(LC_NUMERIC, ""); + int quiet = 0; + + if (argc < 2) + { + printf("Error. At least one argument expected: num_days.\n"); + exit(EXIT_FAILURE); + } + + // Convert num_days to integer + char *end; + int num_days = strtol(argv[1], &end, 10); + + if (num_days < 0) + { + printf("Error. num_days must be greater than zero.\n"); + exit(EXIT_FAILURE); + } + + // Print state each iteration? + if (argc >= 3 && strncmp(argv[2], "-q", 2) == 0) + quiet = 1; + + struct list lanternfish; + if (createList(&lanternfish)) + { + printf("Failed to allocate memory for list.\n"); + exit(EXIT_FAILURE); + } + printf("Initial Lanternfish Spawned\n"); + + // Initial population + insertIntoList(&lanternfish, 3); + insertIntoList(&lanternfish, 4); + insertIntoList(&lanternfish, 3); + insertIntoList(&lanternfish, 1); + insertIntoList(&lanternfish, 2); + + // Print out initial state + if (quiet) + goto simulation; + printf("Initial state: ["); + for (int i = 0; i < lanternfish.used; i++) + { + if (i == lanternfish.used-1) + printf("%d", lanternfish.contents[i]); + else + printf("%d,", lanternfish.contents[i]); + } + printf("]\n"); + + simulation: + for (int i = 1; i <= num_days; i++) + { + int newfish = 0; + // Iterate over lanternfish, subtracting days until next spawn + // or tracking new spawns and resetting days + for (int i = 0; i < lanternfish.used; i++) + { + if (lanternfish.contents[i] == 0) + { + lanternfish.contents[i] = 6; + newfish += 1; + } + else + { + lanternfish.contents[i] -= 1; + } + } + + // Add any new fish that have just spawned + for (int i = 0; i < newfish; i++) + insertIntoList(&lanternfish, 8); + + if (quiet) + continue; + // Print current state of lanternfish + printf("After %2d days: [", i); + for (int i = 0; i < lanternfish.used; i++) + { + if (i == lanternfish.used-1) + printf("%d", lanternfish.contents[i]); + else + printf("%d,", lanternfish.contents[i]); + } + printf("]\n"); + } + + printf("[FINISHED SIMULATION] After %d days, there are %d lanternfish.\n", num_days, lanternfish.used); + printf("Final list utilization: %.2f\n", ((float)lanternfish.used / (float)lanternfish.size) * 100.0); + + exit(EXIT_SUCCESS); +} diff --git a/day7/main.c b/day7/main.c @@ -0,0 +1,134 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +struct list { + size_t used; + size_t size; + char *contents; +}; + +int +createList(struct list *list) +{ + list->used = 0; + list->size = 1; + list->contents = (char *) malloc(1 * sizeof(char)); + if (list->contents == NULL) + return 1; + return 0; +} + +int +insertIntoList(struct list *list, char item) +{ + // Grow list (double its size) when full + if (list->used == list->size) + { + list->size *= 2; + list->contents = (char *) realloc(list->contents, list->size * sizeof(char)); + if (list->contents == NULL) + return 1; + } + list->contents[list->used++] = item; + return 0; +} + +int +isInList (struct list *list, int number) +{ + for (int i = 0; i < list->used; i++) + if (list->contents[i] == number) + return 1; + return 0; +} + +void +printList(struct list *list) +{ + printf("["); + for (int i = 0; i < list->used; i++) + { + if (i == list->used-1) + printf("%d", list->contents[i]); + else + printf("%d, ", list->contents[i]); + } + printf("]\n"); +} + +int +abs (int number) +{ + if (number < 0) + return number * -1; + return number; +} + +void +freeList(struct list *list) +{ + free(list->contents); +} + +int +main(int argc, char **argv) +{ + struct list positions; + if (createList(&positions)) + { + printf("Failed to allocate memory for list.\n"); + exit(EXIT_FAILURE); + } + + // Initial list of positions + // Would be best read from a file and parsed with strtok but that seems + // to be broken with MinGW? (at least a program stops printing when + // using strtok) + insertIntoList(&positions, 16); + insertIntoList(&positions, 1); + insertIntoList(&positions, 2); + insertIntoList(&positions, 0); + insertIntoList(&positions, 4); + insertIntoList(&positions, 2); + insertIntoList(&positions, 7); + insertIntoList(&positions, 1); + insertIntoList(&positions, 2); + insertIntoList(&positions, 14); + + printf("Initial positions loaded.\n"); + printList(&positions); + + // An optimal position will always have at least one of the initial + // positions (because then at least one has fuel use = 0) + struct list possiblePositions; + if (createList(&possiblePositions)) + { + printf("Failed to allocate memory for list.\n"); + exit(EXIT_FAILURE); + } + for (int i = 0; i < positions.used; i++) + if (! isInList(&possiblePositions, positions.contents[i])) + insertIntoList(&possiblePositions, positions.contents[i]); + printf("Determined possible optimal positions.\n"); + printList(&possiblePositions); + + // Determine the position that will have the lowest fuel usage + int optimalPosition = -1; + int lowestFuelUse = 99999; // Not max int but good enough for this + for (int i = 0; i < possiblePositions.used; i++) + { + int fuelCount = 0; + for (int j = 0; j < positions.used; j++) + fuelCount += abs(possiblePositions.contents[i] - positions.contents[j]); + if (fuelCount < lowestFuelUse) + { + lowestFuelUse = fuelCount; + optimalPosition = i; + } + } + + printf("The optimal position is %d, using %d fuel.\n", optimalPosition, lowestFuelUse); + exit(EXIT_SUCCESS); +} diff --git a/day8/input.txt b/day8/input.txt @@ -0,0 +1,10 @@ +be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe +edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc +fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg +fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb +aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea +fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb +dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe +bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef +egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb +gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce diff --git a/day8/main.c b/day8/main.c @@ -0,0 +1,115 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// half done +// Need to only count number of segments in output (after | key) +// Should only split on string after | key, throw out inputs for part 1 + +void +printArrayOfStrings(char **array, int length) +{ + printf("["); + for (int i = 0; i < length; i++) + { + printf("%s", array[i]); + if (i + 1 != length) + printf(", "); + } + printf("]\n"); +} + +int +getNumTokens(char* string, char delimiter) +{ + int numTokens = 1; // Start at one because there will always be at least one element + for (int i = 0; i < strlen(string); i++) + if (string[i] == delimiter) + numTokens += 1; + return numTokens; +} + +void +splitString(char *string, char **array, char delimiter) +{ + int index = 0; + int charCount = 0; + for (int i = 0; i < strlen(string); i++) + { + if (string[i] == '\n') + { + continue; + } + else if (string[i] == delimiter) + { + index++; + i++; + array[index][charCount] = '\0'; + charCount = 0; + } + array[index][charCount] = string[i]; + charCount++; + } + return; +} + +int +main(int argc, char **argv) +{ + size_t size = 512; + int digitcount[] = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}; // Indices correspond to digits 0-9 + + FILE *fp = fopen("input.txt","r"); + if (fp == NULL) + { + printf("Could not open file: input.txt\n"); + exit(EXIT_FAILURE); + } + + char *line = (char *)malloc(size); + while (getline(&line, &size, fp) != -1) + { + printf("Current line: %s", line); + int numTokens = getNumTokens(line, ' '); + printf("NumTokens = %d\n", numTokens); + char **entry = (char **)malloc(numTokens*sizeof(char *)); + for (int i = 0; i < numTokens; i++) + entry[i] = (char *)malloc(512*sizeof(char)); + splitString(line, entry, ' '); + printf("Current entry: "); + printArrayOfStrings(entry, 14); + + for (int i = 0; i < 14; i++) + { + printf("String %s - %ld chars\n", entry[i], strlen(entry[i])); + switch (strlen(entry[i])) + { + case 2: + digitcount[1]++; + break; + case 3: + digitcount[7]++; + break; + case 4: + digitcount[4]++; + break; + case 7: + digitcount[8]++; + break; + } + } + } + + printf("Number frequency:\n"); + for (int i = 0; i < 10; i++) + printf("%d: %d\n", i, digitcount[i]); + + printf("Total number of digits which use a unique number of segments: %d\n", + digitcount[1] + digitcount[7] + digitcount[4] + digitcount[8]); + + if (line) + free(line); + + exit(EXIT_SUCCESS); +}