diff --git a/src/AoC_2023/Dazbo's_Advent_of_Code_2023.ipynb b/src/AoC_2023/Dazbo's_Advent_of_Code_2023.ipynb index b7e4a2ab..b10a3450 100644 --- a/src/AoC_2023/Dazbo's_Advent_of_Code_2023.ipynb +++ b/src/AoC_2023/Dazbo's_Advent_of_Code_2023.ipynb @@ -913,7 +913,7 @@ "id": "5FT4HLZLwevr" }, "source": [ - "## Day 1: title" + "## Day 1: Trebuchet?!" ] }, { @@ -930,6 +930,15 @@ "display(Markdown(day_link))" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(locations)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -954,7 +963,7 @@ " logger.error(e)\n", "\n", "with open(locations.input_file, mode=\"rt\") as f:\n", - " input_data = f.read().strip()\n", + " input_data = f.read().splitlines()\n", "\n", "logger.info(\"Input data:\\n%s\", top_and_tail(input_data))" ] @@ -967,7 +976,36 @@ "source": [ "### Day 1 Part 1\n", "\n", - "Overview..." + "And we're off!! Welcome to the first day of Advent of Code 2023!!\n", + "\n", + "Today was a troublesome start for me. My Internet was out. (Thanks, Virgin Media.) So, after unsuccessful restarts of the router and home network, I switched over to mobile hotspot.\n", + "\n", + "Part 1 is pretty trivial, as we've come to expect. You need to identify the first and last digits of each line of a string, and add them together.\n", + "\n", + "**My Solution**\n", + "\n", + "- For each line, I simply loop through each char in the line, and use the `isdigit()` method to determine if it is a digit.\n", + "- Then repeat, but this time, looping from the end using the Python construct `[::-1]` which just means: start from the end, and then step with increments of `-1`. I.e. move backwards.\n", + "- Finally, concatenate the two digits (still as strings), to update a two digit number. Then convert it to an int.\n", + "- Store all these ints in a list. And at the end, return the sum of the list." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "num_words = {\"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", + " }" ] }, { @@ -979,8 +1017,43 @@ }, "outputs": [], "source": [ - "def solve_part1(data):\n", - " pass" + "def solve(data, with_spelled_nums=False):\n", + " calibration_vals = []\n", + " for line in data:\n", + " logger.debug(line)\n", + " \n", + " first_posn = 1e6 \n", + " last_posn = -1\n", + " first = last = \"\"\n", + "\n", + " for posn, char in enumerate(line): # read from start\n", + " if char.isdigit():\n", + " first_posn = posn\n", + " first = char\n", + " break\n", + " \n", + " for posn, char in enumerate(line[::-1]): # read from the end\n", + " if char.isdigit():\n", + " last_posn = len(line) - posn - 1 # remember, we're now counting from the end!!\n", + " last = char\n", + " break\n", + "\n", + " if with_spelled_nums:\n", + " for num_word in num_words:\n", + " posn = line.find(num_word)\n", + " if 0 <= posn < first_posn:\n", + " first_posn = posn\n", + " first = str(num_words[num_word]) # map it back to int\n", + " \n", + " posn = line.rfind(num_word)\n", + " if posn > last_posn:\n", + " last_posn = posn\n", + " last = str(num_words[num_word]) # map to the int\n", + " \n", + " calibration_vals.append(int(first + last))\n", + " \n", + " return sum(calibration_vals) \n", + " " ] }, { @@ -993,13 +1066,13 @@ "outputs": [], "source": [ "%%time\n", - "sample_inputs = [\"abcdef\"]\n", - "sample_answers = [\"uvwxyz\"]\n", + "sample_inputs = [[\"1abc2\", \"pqr3stu8vwx\", \"a1b2c3d4e5f\", \"treb7uchetabcdef\"]]\n", + "sample_answers = [142]\n", "\n", "for curr_input, curr_ans in zip(sample_inputs, sample_answers):\n", - " validate(solve_part1(curr_input), curr_ans) # test with sample data\n", + " validate(solve(curr_input), curr_ans) # test with sample data\n", "\n", - "soln = solve_part1(input_data)\n", + "soln = solve(input_data)\n", "logger.info(f\"Part 1 soln={soln}\")" ] }, @@ -1011,20 +1084,19 @@ "source": [ "### Day 1 Part 2\n", "\n", - "Sum all the digits that match a digit that is exactly halfway along." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "uju3nPBKx9RW", - "tags": [] - }, - "outputs": [], - "source": [ - "def solve_part2(data):\n", - " pass" + "For Day 1, this wasn't quite as trivial as I was expecting! Now we have to also find the positions of any \"spelled\" versions of the digits 0-9.\n", + "\n", + "**My solution:**\n", + "\n", + "- Create a `dict` to store the spelled versions of 1-9, and map them to their respective int values.\n", + "- Now, with each line, perform the same code as we did for Part 1 to find the first and last positions of the digit representation. \n", + " - But this time, store the positions found, as well as the values. I use the [`enumerate()`](https://aoc.just2good.co.uk/python/enumerate) to give me the current position of each char in my line.\n", + " - Be really careful when storing the position when counting from the end. This tripped me up for a couple of minutes!! When we're looping through chars from the end, backwards, we want to store the position in the string, not the current enumeration value. \n", + "- Then, run another loop that looks for each spelled number in our dict of spelled numbers.\n", + " - To search for our current spelled number in our line from the start, using the `find()` method.\n", + " - To search for our current spelled number in our line from the end, using the `rfind()` method.\n", + " - Whenever we find a spelled number, check whether we found it at a position that is earlier / later (as required) than the digit we found before.\n", + " - Whenever I find such a spelled number, I convert the int value in the dict to a string, so that I can concatenate the string values, just as we did before." ] }, { @@ -1037,14 +1109,20 @@ "outputs": [], "source": [ "%%time\n", - "sample_inputs = [\"abcdef\"]\n", - "sample_answers = [\"uvwxyz\"]\n", + "sample_inputs = [[\"two1nine\", \n", + " \"eightwothree\", \n", + " \"abcone2threexyz\", \n", + " \"xtwone3four\", \n", + " \"4nineeightseven2\", \n", + " \"zoneight234\", \n", + " \"7pqrstsixteen\"]]\n", + "sample_answers = [281]\n", "\n", "for curr_input, curr_ans in zip(sample_inputs, sample_answers):\n", - " validate(solve_part1(curr_input), curr_ans) # test with sample data\n", + " validate(solve(curr_input, with_spelled_nums=True), curr_ans) # test with sample data\n", "\n", - "soln = solve_part1(input_data)\n", - "logger.info(f\"Part 1 soln={soln}\")" + "soln = solve(input_data, with_spelled_nums=True)\n", + "logger.info(f\"Part 2 soln={soln}\")" ] }, { diff --git a/src/AoC_2023/d01/input/input.txt b/src/AoC_2023/d01/input/input.txt new file mode 100644 index 00000000..d1a5032c Binary files /dev/null and b/src/AoC_2023/d01/input/input.txt differ