From 6d44baa874c8bb46a09b6fe2abf34871cbe5c6be Mon Sep 17 00:00:00 2001 From: kzkedzierska <31040515+kzkedzierska@users.noreply.github.com> Date: Fri, 1 Dec 2023 16:30:34 +0000 Subject: [PATCH] :tada: Added 2023 with Day1 solved :white_check_mark: --- .gitignore | 3 +- 2022/answers.qmd | 88 +++++++++- 2023/Day1.ipynb | 426 +++++++++++++++++++++++++++++++++++++++++++++++ README.md | 13 +- 4 files changed, 526 insertions(+), 4 deletions(-) create mode 100644 2023/Day1.ipynb diff --git a/.gitignore b/.gitignore index 1132feb..0fe0e29 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ */.RData */.Ruserdata .Rproj.user -*/.quarto/ \ No newline at end of file +*/.quarto/ +*/inputs \ No newline at end of file diff --git a/2022/answers.qmd b/2022/answers.qmd index b5ae123..10f19f8 100644 --- a/2022/answers.qmd +++ b/2022/answers.qmd @@ -27,7 +27,7 @@ From [Wikipedia](https://en.wikipedia.org/wiki/Advent_of_Code): Advent of Code i ### Summary -I got busy and had to skip a week of answers - hence why not all problems are solved yet. +I got busy and now not all problems are solved yet. I'll be coming back here whenever I have a bit of time to catch up on AoC! ```{bash} #| label: generte-input-stars-summary @@ -1768,6 +1768,8 @@ scenic_view("inputs/08_input.txt") [Task outline](https://adventofcode.com/2022/day/9) + + ## Day 10: Cathode-Ray Tube ### Part one ⭐ @@ -1978,6 +1980,88 @@ get_level_monkey_business2("inputs/11_input.txt", cycles = 10000) **Outcome:** That's the right answer! You are **one gold star** ⭐ closer to collecting enough star fruit. + +## Day 13: Distress Signal + +### Part one + +```{python} +def compare_elements(packets_left, packets_right, debug=False): + if debug: + print(f"packets left: {packets_left}, packets right: {packets_right}") + + # if at the end + if len(packets_left) < 1: + return True + + if len(packets_right) < 1: + return False + + left = packets_left[0] + right = packets_right[0] + # two numbers + if isinstance(left, int) and isinstance(right, int): + if right < left: + return False + elif right > left: + return True + else: + return compare_elements(packets_left[1:], packets_right[1:]) + + # two lists + elif isinstance(left, list) or isinstance(right, list): + if debug: + print(f"left: {left}, right: {right}") + left = left if isinstance(left, list) else [left] + right = right if isinstance(right, list) else [right] + + if debug: + print(f"left: {left}, right: {right}") + + if len(right) == 0 and len(left) > 0: + return False + + elif len(left) == 0 and len(right) > 1: + return True + + else: + if len(left[1:]) == 0 and len(right[1:]) == 0: + return compare_elements(packets_left[1:], packets_right[1:]) + else: + return compare_elements(left, right) + + else: + print(f"Corner case - left: {left} and right: {right}") + +# define test +def test_case(cmd, result): + assert cmd == result, f"Should be {result}, is {cmd}" + + +def get_indices_in_order(file_path): + with open(file_path, "r+") as f: + lines = f.readlines() + + packets = [eval(line.strip()) for line in lines if line != "\n"] + pleft = packets[::2] + pright = packets[1::2] + + in_order = [compare_elements(pleft[i], pright[i]) for i in range(len(pleft))] + + return [i + 1 for i in range(len(in_order)) if in_order[i]] + + +test_case(sum(get_indices_in_order("inputs/13_test_case.txt")), 13) +``` + +Too small :( + +```{python} +get_indices_in_order("inputs/13_input.txt") +``` + + + ## Day 18: Boiling Boulders ### Part one ⭐ @@ -2040,3 +2124,5 @@ count_walls("inputs/18_input.txt") ``` **Outcome:** That's the right answer! You are **one gold star** ⭐ closer to collecting enough star fruit. + + diff --git a/2023/Day1.ipynb b/2023/Day1.ipynb new file mode 100644 index 0000000..a594111 --- /dev/null +++ b/2023/Day1.ipynb @@ -0,0 +1,426 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Day 1\n", + "\n", + "Sounds like Elfs are shooting us into the sky to check the global snow production. But the calibration of the shooting machine has been remade by a young, artistically gifted Elf. Now, to calibrate the machine we need to solve the tasks." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part One\n", + "\n", + "We need to take the input and get the numbers of from each line. This number is generated by the first and last digit from each line. Next, we need the sum across all line.\n", + "\n", + "For example:\n", + "\n", + "```\n", + "1abc2\n", + "pqr3stu8vwx\n", + "a1b2c3d4e5f\n", + "treb7uchet\n", + "```\n", + "In this example, the calibration values of these four lines are 12, 38, 15, and 77. Adding these together produces 142." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "55712" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "calibration_values = []\n", + "# read the input\n", + "with open(\"./inputs/day01.txt\") as f:\n", + " for line in f:\n", + " # get the digits only from the input\n", + " digits = [d for d in line.strip() if d.isdigit()]\n", + " # save the number from a line as first and last digit\n", + " calibration_values.append(int(digits[0] + digits[-1]))\n", + "\n", + "# sum the calibration values\n", + "sum(calibration_values)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That's the right answer! You are one gold star ⭐ closer to restoring snow operations." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part Two\n", + "\n", + "It looks like some of the digits are spelled in words. \n", + "\n", + "For example:\n", + "```\n", + "two1nine\n", + "eightwothree\n", + "abcone2threexyz\n", + "xtwone3four\n", + "4nineeightseven2\n", + "zoneight234\n", + "7pqrstsixteen\n", + "```\n", + "\n", + "In this example, the calibration values are 29, 83, 13, 24, 42, 14, and 76. Adding these together produces 281.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# create a dictionary for replacing the words with numbers\n", + "replace_dict = {\n", + " \"zero\": 0,\n", + " \"one\": 1,\n", + " \"two\": 2,\n", + " \"three\": 3,\n", + " \"four\": 4,\n", + " \"five\": 5,\n", + " \"six\": 6,\n", + " \"seven\": 7,\n", + " \"eight\": 8,\n", + " \"nine\": 9\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def get_digits(line):\n", + " line = line.strip()\n", + " # replace the words with numbers, reading character by character\n", + " # such that when digits overlap, the one that starts first is taken\n", + " # create a window, that slides through the line to identify the words \n", + " # to be replaced\n", + " window = \"\"\n", + " new_line = \"\"\n", + " for c in line:\n", + " # add the character to the window\n", + " window += c\n", + " # replace the word in the window with the number\n", + " for word, number in replace_dict.items():\n", + " if word in window:\n", + " window = window.replace(word, str(number))\n", + " new_line = new_line + window\n", + " window = \"\"\n", + " new_line = new_line + window\n", + " line = new_line\n", + " # get the digits only from the input\n", + " return [d for d in line if d.isdigit()]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[29, 83, 13, 24, 42, 14, 76]\n" + ] + } + ], + "source": [ + "# test on the example\n", + "example_input = \"two1nine\\neightwothree\\nabcone2threexyz\\nxtwone3four\\n4nineeightseven2\\nzoneight234\\n7pqrstsixteen\"\n", + "test_calibration_values = []\n", + " \n", + "for line in example_input.split(\"\\n\"):\n", + " digits = get_digits(line)\n", + " # save the number from a line as first and last digit\n", + " test_calibration_values.append(int(digits[0] + digits[-1]))\n", + "\n", + "print(test_calibration_values)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# test the calibration values\n", + "assert(test_calibration_values == [29, 83, 13, 24, 42, 14, 76])" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# sum the calibration values\n", + "assert(sum(test_calibration_values) == 281)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "55445" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "new_calibration_values = []\n", + "# read the input\n", + "with open(\"./inputs/day01.txt\") as f:\n", + " for line in f:\n", + " # get the digits only from the input\n", + " digits = get_digits(line)\n", + " # more detailed handling of lines, incl. warnings for no digits,\n", + " # should they occur\n", + " if len(digits) == 0:\n", + " print(f\"Warning: no digits in {line.strip()}\")\n", + " elif len(digits) == 1:\n", + " # print(f\"Warning: only one digit ({digits[0]}) in {line.strip()}\")\n", + " new_calibration_values.append(int(digits[0] + digits[-1]))\n", + " else:\n", + " new_calibration_values.append(int(digits[0] + digits[-1]))\n", + "\n", + "# sum the calibration values\n", + "sum(new_calibration_values)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is not a correct answer. \n", + "\n", + "I think it might get to do with overlapping numbers. For example, in line:\n", + "\n", + "```\n", + "1threegkhpq7nfrksvm69nxpvgvthfzoneighttc\n", + "``` \n", + "\n", + "in current version of the function I would take 1 from **oneight**. It might be worth changing the code, such that each occurence of the digit is recorded with it starting point, and based on that first and last digit is taken. " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['1', '2', '3', '1']" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import re\n", + "def get_digits_mod(line):\n", + " line = line.strip()\n", + " # for each occurrence of the digit, take its position\n", + " # and the digit itself\n", + " positions = []\n", + " digits = []\n", + " for w, d in replace_dict.items():\n", + " # find all occurrences of the digit and its position\n", + " ps = [m.start() for m in re.finditer(w, line)] + [m.start() for m in re.finditer(str(d), line)]\n", + " ds = [d]*len(ps)\n", + " positions.extend(ps)\n", + " digits.extend(ds)\n", + " # sort the digits by their position\n", + " positions, digits = zip(*sorted(zip(positions, digits)))\n", + " # get the digits only from the input and make sure they are strings\n", + " # for consistency\n", + " digits = [str(d) for d in digits]\n", + " return list(digits)\n", + "\n", + "get_digits_mod(\"one2threeone\")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "assert(get_digits_mod(\"two1nine\") == ['2', '1', '9'])" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "assert(get_digits_mod(\"1threegkhpq7nfrksvm69nxpvgvthfzoneighttc\") == ['1', '3', '7', '6', '9', '1', '8'])" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['0', '0', '1', '9']" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_digits_mod(\"zero019\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[29, 83, 13, 24, 42, 14, 76]\n" + ] + } + ], + "source": [ + "test_calibration_values = []\n", + "\n", + "for line in example_input.split(\"\\n\"):\n", + " digits = get_digits_mod(line)\n", + " # save the number from a line as first and last digit\n", + " test_calibration_values.append(int(digits[0] + digits[-1]))\n", + "\n", + "print(test_calibration_values)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "# test the calibration values\n", + "assert(test_calibration_values == [29, 83, 13, 24, 42, 14, 76])" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "# sum the calibration values\n", + "assert(sum(test_calibration_values) == 281)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "55413" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "new_calibration_values = []\n", + "# read the input\n", + "with open(\"./inputs/day01.txt\") as f:\n", + " for line in f:\n", + " # get the digits only from the input\n", + " digits = get_digits_mod(line)\n", + " # more detailed handling of lines, incl. warnings for no digits,\n", + " # should they occur\n", + " if len(digits) == 0:\n", + " print(f\"Warning: no digits in {line.strip()}\")\n", + " elif len(digits) == 1:\n", + " # for lines with just one digit, I repeat that digit\n", + " new_calibration_values.append(int(digits[0] + digits[-1]))\n", + " else:\n", + " new_calibration_values.append(int(digits[0] + digits[-1]))\n", + "\n", + "# sum the calibration values\n", + "sum(new_calibration_values)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That's the right answer! You are one gold star ⭐ closer to restoring snow operations." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/README.md b/README.md index 5d9abc4..23b7e4b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,17 @@ -# My Advent of Code (AOC) solutions +# My Advent of Code (AoC) solutions + +## 2023 + +For `AoC 2023` I am solving them in Python, in Jupyter notebooks (run in VS Code). I don't keep the inputs, as per the request of the creator of Advent of Code. + +| Day | Part 1 | Part 2 | +| --- | ------ | ------ | +| [1](2023/Day1.ipynb) | ⭐ | ⭐ | + ## 2022 -For `AOC 2022` I decided to solve the problems by writing up my solutions in Quarto Publication (so far using `Python`). You can look up the answers in the online version of the notebook [here](https://kzkedzierska.quarto.pub/advent-of-code-2022/). +For `AoC 2022` I decided to solve the problems by writing up my solutions in Quarto Publication (so far using `Python`). You can look up the answers in the online version of the notebook [here](https://kzkedzierska.quarto.pub/advent-of-code-2022/). [![Quarto Publication with my solutions, taken on 7/12](quarto_2022.png)](https://kzkedzierska.quarto.pub/advent-of-code-2022/)