diff --git a/README.md b/README.md index 51aef61..4d52617 100644 --- a/README.md +++ b/README.md @@ -16,3 +16,5 @@ My own solutions to [Advent of Code](https://adventofcode.com/). → [solutions in Python 3](https://github.com/loociano/advent-of-code/tree/master/aoc2022) * [Advent of Code 2023](https://adventofcode.com/2023) → [solutions in Python 3](https://github.com/loociano/advent-of-code/tree/master/aoc2023) +* [Advent of Code 2024](https://adventofcode.com/2024) + → [solutions in Python 3](https://github.com/loociano/advent-of-code/tree/master/aoc2024) diff --git a/aoc2024/README.md b/aoc2024/README.md new file mode 100644 index 0000000..2c7687a --- /dev/null +++ b/aoc2024/README.md @@ -0,0 +1,7 @@ +# Advent of Code 2024 + +My own solutions to [Advent of Code 2024](https://adventofcode.com/2024). + +> Advent of Code is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like. People use them as a speed contest, interview prep, company training, university coursework, practice problems, or to challenge each other. —Eric Wastl + +* [Day 1: Historian Hysteria](https://adventofcode.com/2023/day/1) → [Python3 solution](https://github.com/loociano/advent-of-code/blob/master/aoc2024/src/day01/python/solution.py) \ No newline at end of file diff --git a/aoc2024/__init__.py b/aoc2024/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aoc2024/src/__init__.py b/aoc2024/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aoc2024/src/day01/__init__.py b/aoc2024/src/day01/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aoc2024/src/day01/python/__init__.py b/aoc2024/src/day01/python/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aoc2024/src/day01/python/solution.py b/aoc2024/src/day01/python/solution.py new file mode 100644 index 0000000..6674092 --- /dev/null +++ b/aoc2024/src/day01/python/solution.py @@ -0,0 +1,77 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from collections import defaultdict +from typing import Sequence + +type LocationIds = Sequence[int] + +def _parse_input(input: Sequence[str]) -> tuple[LocationIds, LocationIds]: + """Converts puzzle input into 2 lists of location IDs. + + n = len(input) + Time complexity: O(n) + Space complexity: O(n) + O(n) = O(n) + + """ + location_ids1 = [] + location_ids2 = [] + # Parse input: + for line in input: # t:O(n) + # Line format is: '<int>\s\s\s<int>' + id1, id2 = map(int, line.split(' ')) # Assumes valid input. + location_ids1.append(id1) + location_ids2.append(id2) + return location_ids1, location_ids2 + +def calculate_distance(input: Sequence[str]) -> int: + """ + Calculates total distance between 2 sequences of location IDs. + + n = len(input) + Time complexity: O(n) + O(2nlogn) + O(n) = O(nlogn). + Space complexity: O(n) + O(n) = O(n) + + Args: + input: Sequence of location ID pairs. + Returns + Total distance. + """ + location_ids1, location_ids2 = _parse_input(input) # O(n) + # Calculate total distance: + location_ids1.sort() # t:O(nlogn) + location_ids2.sort() # t:O(nlogn) + return sum( + abs(location_ids1[i] - location_ids2[i]) + for i in range(0, len(location_ids1))) # t:O(n) + +def calculate_similarity_score(input: Sequence[str]) -> int: + """ + Calculates similarity score between 2 sequences of location IDs. + + n = len(input) + Time complexity: O(n) + O(n) + O(n) = O(n) + Space complexity: O(2n) + O(n) = O(n) + + Args: + input: Sequence of location ID pairs. + Returns + Total distance. + """ + location_ids1, location_ids2 = _parse_input(input) # t:O(n) + histogram = defaultdict(int) + # Generate histogram: + for id in location_ids2: # t:O(n) + histogram[id] += 1 + # Calculate similarity score: + return sum(id * histogram.get(id, 0) for id in location_ids1) # t:O(n) \ No newline at end of file diff --git a/aoc2024/test/__init__.py b/aoc2024/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aoc2024/test/day01/__init__.py b/aoc2024/test/day01/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aoc2024/test/day01/python/__init__.py b/aoc2024/test/day01/python/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aoc2024/test/day01/python/example1.txt b/aoc2024/test/day01/python/example1.txt new file mode 100644 index 0000000..dfca0b1 --- /dev/null +++ b/aoc2024/test/day01/python/example1.txt @@ -0,0 +1,6 @@ +3 4 +4 3 +2 5 +1 3 +3 9 +3 3 \ No newline at end of file diff --git a/aoc2024/test/day01/python/input.txt b/aoc2024/test/day01/python/input.txt new file mode 100644 index 0000000..7be7da0 --- /dev/null +++ b/aoc2024/test/day01/python/input.txt @@ -0,0 +1,1000 @@ +68878 98732 +24519 87903 +73275 70114 +87985 89419 +80485 75440 +98994 55979 +28041 41805 +50762 92905 +23796 72412 +71699 84915 +43168 71645 +12985 96078 +38491 34431 +30867 76208 +89794 10790 +59797 86225 +62401 50098 +90230 45208 +40596 36238 +52821 75949 +61994 85771 +62756 70340 +91145 33842 +57051 45050 +36257 80983 +36465 84670 +98498 23292 +49344 50098 +13100 22817 +82572 57598 +77578 36555 +99900 91029 +75949 26486 +50711 74711 +52402 27513 +69977 71045 +23803 41588 +57399 16399 +81372 45126 +98985 10547 +76606 99481 +86993 78240 +54958 27513 +23734 61444 +25189 10790 +11983 91029 +53266 91029 +31226 16399 +54686 86915 +60013 40760 +29568 52436 +97354 44827 +91545 40986 +15914 60707 +64854 49298 +30497 66916 +39169 92811 +13341 98568 +89066 41215 +89654 33815 +59655 66645 +89071 48550 +91777 41832 +28820 23803 +68277 10790 +24747 20641 +19058 68263 +50952 65659 +77247 71079 +79147 28383 +89104 79596 +26384 27513 +58111 79657 +61032 72412 +45514 49298 +37369 80983 +66897 96745 +42256 18346 +53662 67789 +18203 50098 +14178 24879 +16119 50862 +85457 55460 +74217 62672 +72612 50061 +30548 32091 +21631 49298 +55905 19836 +15340 92089 +44619 28383 +67975 95646 +22169 56053 +15778 32810 +63133 98314 +42385 35192 +51645 87903 +30068 80881 +44510 83025 +50757 59248 +31854 16399 +54593 27981 +16570 11600 +21295 99780 +70191 38799 +64847 16732 +30348 30596 +92301 49298 +66545 23803 +32957 27513 +49572 10507 +10790 65414 +85781 24738 +32819 50098 +22674 23803 +44321 40307 +39258 19836 +25314 27018 +98446 83025 +96722 15026 +96131 51435 +60029 46857 +22672 24485 +57347 40735 +55089 65268 +93093 57076 +46410 40686 +46719 49999 +48860 80891 +75752 40285 +32025 76676 +58831 14816 +93208 75949 +93404 87903 +91034 54811 +74178 40675 +99272 84920 +24617 59248 +31004 22425 +49824 79823 +50187 76234 +64360 55010 +40773 10935 +93193 28383 +24292 27513 +66603 96899 +94711 49904 +81183 59248 +38727 50143 +47093 34542 +94395 41907 +39003 89663 +40029 57072 +90456 84416 +75830 87903 +33466 27513 +16427 59248 +49490 33354 +52134 40307 +67069 80983 +35192 57341 +82716 11017 +74969 49298 +16596 30045 +30786 50769 +69766 39818 +88136 94929 +29630 70754 +98865 52818 +83025 52968 +38613 75675 +34339 87903 +20221 11583 +60785 21075 +42016 32352 +50862 54811 +91144 10790 +82759 92299 +34668 35814 +80045 80983 +17106 87903 +47417 28383 +62403 75949 +58496 77896 +98013 75949 +82894 34330 +93384 44962 +95803 10790 +76669 66543 +14186 80983 +40149 58549 +50049 40735 +62487 55256 +32816 59248 +84420 67838 +54052 83025 +91698 73884 +62982 26639 +34047 65346 +32974 19836 +36970 14966 +14307 18019 +26904 87903 +36343 72547 +43235 89108 +76676 72412 +55938 66916 +34071 16143 +72820 64337 +17369 17215 +46104 45050 +88124 73288 +31485 52329 +50048 87903 +11820 51419 +81418 69376 +45029 97736 +10581 25449 +49081 33618 +52159 99078 +81831 98314 +88990 32303 +43609 44962 +32213 40285 +40285 83782 +99022 50098 +53784 22929 +88877 40307 +50928 58596 +41715 92182 +88640 20046 +57029 69964 +47786 36174 +85810 15842 +11369 90510 +70368 27513 +94570 64489 +39889 80581 +13275 16427 +68274 27513 +77936 51774 +15466 29702 +44729 80983 +32438 16399 +41087 23803 +60462 49298 +65311 76326 +32702 40735 +82433 97292 +93862 90212 +33210 81930 +94761 90283 +42167 74463 +35098 48550 +27078 99873 +54429 12606 +27075 89108 +97224 73884 +56433 68263 +30526 59248 +40340 10790 +69964 48550 +58197 72412 +86344 18262 +28455 87594 +87168 57559 +73594 65764 +43616 54811 +36860 55905 +62313 46800 +63659 87903 +19649 40735 +63386 45583 +70670 96410 +25427 84151 +95907 50098 +90333 92116 +88441 40735 +52924 40735 +54606 93929 +53431 35192 +72778 94800 +32259 44962 +22837 15734 +41370 20407 +50667 91029 +23172 20736 +87478 78442 +18679 67415 +25132 27513 +35955 72412 +19951 42485 +92404 73884 +43932 75949 +89428 47755 +68629 23255 +18060 75949 +96741 67071 +46707 89108 +89112 92197 +55083 71071 +41640 66916 +17099 58116 +70851 16399 +23057 92148 +19836 92356 +25812 72833 +93063 23164 +45392 59203 +21796 69964 +97556 35192 +57076 97029 +58339 50098 +58116 62171 +91036 98314 +60829 59813 +22495 46432 +66493 29832 +15341 17977 +50093 59248 +20768 10238 +23220 40987 +51196 62761 +23277 80983 +37255 28383 +42832 93721 +60978 28336 +81525 16486 +75180 66916 +69316 49298 +29241 48253 +11596 50862 +34351 31482 +43881 52947 +18039 15790 +35090 47718 +37781 66916 +90037 44975 +58775 49298 +11066 92303 +35717 97563 +73565 49309 +26674 96015 +91767 35192 +20613 29701 +98660 26456 +19235 73884 +52519 61051 +40366 14356 +33606 59248 +67433 78913 +51982 98675 +21129 45050 +26259 59939 +41424 74011 +15544 18046 +85842 93362 +44238 54811 +50995 77228 +50211 45766 +88522 55008 +85664 10790 +83872 49541 +90863 66681 +12731 80983 +35092 44962 +89343 27513 +43030 59369 +14341 14679 +67832 54811 +65399 97833 +40649 53538 +99865 39569 +84679 16399 +37678 91006 +40703 80889 +36214 88977 +38351 87638 +41150 30413 +82746 40735 +34606 89108 +32107 18123 +35459 50816 +26610 23803 +18202 49298 +34659 23803 +89860 35192 +25591 72412 +11117 92839 +90319 83025 +36871 40735 +94581 72076 +56790 46209 +13136 81739 +12085 62323 +75208 37298 +80354 40735 +61593 39732 +21371 71180 +44422 19479 +37274 27513 +13294 41590 +12424 22554 +57230 40809 +95559 81507 +18733 43631 +95220 79915 +15071 92369 +70964 57296 +55914 83712 +57268 87903 +61644 20006 +14409 58116 +19343 90069 +79716 73884 +57337 79683 +35640 48701 +65868 66918 +21687 49298 +90364 90368 +81563 96307 +99862 35192 +50098 23985 +56421 33574 +87642 50862 +80261 57845 +80290 53468 +69199 73884 +52657 73884 +82897 13916 +55530 23966 +77782 54811 +60975 11030 +99943 66089 +14928 40735 +32910 50078 +73884 52473 +81361 58116 +13203 16427 +72163 80438 +82198 13938 +46030 38491 +33431 52909 +30199 40285 +58012 61365 +60604 88325 +66916 73884 +59248 10790 +52823 68263 +67584 38374 +35764 58969 +38010 35192 +53537 27513 +40680 90231 +77944 85142 +65080 80983 +15342 65310 +66994 49661 +46267 41636 +80983 95143 +78052 36273 +54944 49284 +37652 65872 +60311 89108 +51144 69333 +31653 48550 +55121 87873 +36739 66142 +20290 69352 +86844 80544 +90543 40885 +36289 61112 +42899 95984 +19910 73884 +16572 40307 +22864 91559 +68021 38491 +49918 73786 +93754 91029 +51211 96235 +98091 95113 +51208 26252 +12671 40285 +61367 89030 +58498 75949 +26520 61255 +16399 35061 +26388 40307 +20061 45050 +42577 59248 +46182 23803 +45833 22608 +75415 35192 +45131 27513 +78087 72412 +37845 59937 +73178 40307 +38346 10790 +36144 48550 +95728 35192 +24529 74785 +13457 62690 +80521 90830 +26709 87903 +96061 58362 +39901 75949 +59024 36414 +70572 73484 +26182 48550 +54289 44962 +77243 41357 +45652 63563 +61275 33760 +76258 58116 +87903 75949 +36803 72708 +34689 49298 +78499 69964 +97542 16399 +99456 23803 +31246 97810 +67707 66916 +53353 76845 +72413 81639 +77355 91427 +11696 37641 +38619 66916 +58279 27513 +32455 46733 +13767 10790 +53600 12534 +52611 86767 +69581 58116 +84766 44962 +25762 84153 +75405 27675 +94680 98620 +19072 83025 +64541 25303 +47436 48379 +55099 77486 +62938 40285 +85782 22822 +49496 68211 +26405 18321 +33543 53744 +98210 17305 +26641 70987 +78605 23803 +48550 91029 +91470 59527 +76437 48391 +26589 68552 +37984 42659 +47771 75949 +69492 69964 +30910 17034 +72127 48550 +20323 74549 +68586 54811 +85656 49347 +50811 29122 +91633 13067 +97829 94888 +64580 30618 +87031 50862 +16689 35192 +93352 21275 +91740 27513 +86775 66916 +63447 40735 +69321 85095 +21196 96099 +40135 24597 +94728 83025 +68263 78089 +49758 75949 +58570 40307 +70556 80983 +28954 87903 +23512 75949 +79621 26912 +23768 89108 +68025 71387 +94717 39913 +32934 38491 +25309 46226 +31117 91819 +28718 37008 +11096 80983 +82842 17899 +10104 44147 +15432 18566 +58103 81227 +36711 10790 +62998 76676 +56830 73884 +74532 40285 +10346 78375 +43025 31492 +31908 30023 +38840 96892 +42859 83025 +16034 68263 +56548 32521 +36514 95622 +93380 85880 +89108 49638 +14520 55668 +61195 65113 +59069 91029 +75276 89108 +94795 53666 +16658 43105 +23381 19836 +80772 80983 +22003 80790 +78628 73884 +53837 34325 +53845 85258 +87259 55484 +96036 28264 +43607 75949 +90261 55158 +97376 52565 +11241 46873 +13946 56491 +48838 35216 +26427 88573 +24683 38491 +61135 72412 +39381 47195 +66763 71602 +50727 16399 +26719 73008 +91561 57060 +27810 23803 +25003 80469 +87375 40479 +47591 80117 +15769 78617 +62428 95360 +58030 40285 +42184 59248 +16058 18264 +49021 66916 +60036 16399 +79735 64973 +28417 87903 +75666 34050 +45303 45905 +99666 58844 +83328 47904 +34405 27513 +40795 27513 +94482 57076 +73638 76842 +11760 72412 +18055 73884 +42382 73884 +74101 89766 +53388 22330 +80963 61832 +35307 75326 +24016 61479 +76700 69002 +11790 54811 +37543 40735 +23488 38262 +79409 73517 +84795 48550 +72611 72142 +24699 49298 +43748 48550 +89525 98314 +67690 26597 +77431 66916 +18256 65012 +47688 69964 +27275 54811 +28105 75949 +99231 47666 +10732 40307 +96670 82188 +67501 16141 +24786 95724 +72693 58116 +11436 11225 +44962 16427 +11976 57220 +23830 75949 +20155 29692 +49298 40758 +15879 38491 +46430 19053 +58886 32623 +38384 73884 +54723 67754 +40400 45721 +11657 16399 +45050 45050 +85338 35986 +83322 66916 +47722 83411 +16468 24658 +95873 81506 +41360 47035 +66342 36775 +87812 87399 +28383 39066 +91602 15602 +40405 89236 +77890 81548 +98616 49298 +22404 35192 +54032 44962 +52902 16399 +91840 98314 +63905 12686 +10098 54811 +11009 35192 +88737 23803 +64422 88518 +37474 95536 +41788 91339 +76027 15249 +17826 50042 +79264 64640 +98770 36874 +13862 57804 +38691 27513 +21357 78686 +32360 52496 +18251 48550 +38720 31160 +36065 75949 +35917 16399 +60979 18939 +91586 89952 +28849 67949 +40735 58746 +26437 19975 +86360 45050 +35949 19228 +83277 50098 +38624 10790 +52011 49393 +39123 39337 +27513 89108 +62673 15222 +94379 83025 +23909 90571 +77737 93244 +70404 70858 +62370 84696 +84827 44218 +53387 35250 +87556 89108 +80571 51193 +26409 91029 +13990 83025 +11278 34702 +16299 89667 +63994 65610 +86493 54811 +29416 78479 +17711 28383 +80358 80983 +56072 39436 +93254 73884 +91931 16399 +53072 98128 +24215 98633 +90482 97373 +21665 40735 +64002 80983 +84470 27470 +81717 67708 +41573 22587 +46883 16167 +19788 93408 +41097 23282 +80709 38138 +37670 69964 +49520 40544 +19523 42044 +83480 22439 +67124 88126 +90934 21464 +87043 65017 +50073 10790 +81378 61975 +51195 80983 +87524 10790 +54555 49298 +49730 84396 +91852 72412 +14863 93792 +74431 25266 +39883 80983 +99545 50098 +49954 39659 +50720 54616 +82282 66849 +27672 34776 +48615 88195 +16323 23803 +34687 30556 +84144 25955 +43893 16399 +58000 17912 +63630 93219 +42225 59248 +10697 50098 +84790 49298 +84555 50098 +11332 67228 +55152 91029 +17760 35192 +74448 78826 +72412 99596 +81795 65194 +28000 23577 +58978 75949 +97634 91029 +12089 74439 +21668 11140 +98314 59248 +27619 92514 +34387 40285 +64406 70596 +54811 36254 +28351 92362 +79006 46580 +49237 10460 +30856 46374 +59999 48734 +76251 98298 +14006 91029 +88588 33976 +97866 91029 +11813 10790 +91016 83025 +43424 32540 +83490 72412 +78507 89604 +91517 91029 +55040 21407 +21483 83837 +47039 75811 +97168 38491 +96466 28383 +66156 85652 +50285 91029 +14057 19440 +73017 79572 +33025 15856 +97174 15804 +65673 59248 +19216 34215 +44883 87903 +30254 40285 +31552 29668 +76764 16427 +60507 41588 +18078 39147 +46186 54811 +90898 23803 +23982 40735 +37504 80710 +72585 89108 +17791 84089 +79779 66916 +25517 57516 +54064 54811 +47343 59248 +11730 16399 +14957 23803 +30186 14989 +66079 89338 +82720 66916 +59760 44962 +23159 77329 +21390 50098 +12330 90747 +38607 53663 +96534 97111 +65278 58227 +48760 91626 +34518 47541 +79376 48439 +40307 36080 +59634 68532 +16764 51086 +20484 10950 +40175 72383 +12457 70481 +56023 34025 +63916 58517 +46289 70209 +91143 44935 +65424 70887 +39578 52243 +79985 22203 +72984 35192 +41823 76917 +98393 10103 +48951 40735 +51888 89069 +85621 44767 +49048 27513 +48878 87903 +91067 73884 +67152 73125 +80589 59248 +80824 52481 +65118 59248 +66648 83025 +17766 13909 +83672 35572 +81351 42040 +72780 87903 +87114 75949 +74871 29739 +62623 73816 +68716 49219 +72795 72092 +97700 40307 +80913 80983 +21100 37233 +49723 10790 +30881 80895 +42287 28982 +90849 50862 +13053 14799 +90689 50862 +91029 19117 +61953 43248 +67212 50164 +70587 31660 +50801 40285 +44701 68049 +67526 72412 +64537 98405 +10820 23823 +94953 57422 +93517 72412 +84240 45050 +72049 80983 +17021 10790 +41393 72559 +88520 57245 +63317 28383 +28723 74185 +64942 27513 +10994 34190 +57068 93681 +15289 53584 +20900 35192 +32744 41588 +18435 72823 +95710 35192 +14710 69585 +31598 87903 +63543 10790 +29870 91029 +20129 16427 +21868 49298 +76460 73884 +65538 72412 +84172 51085 +77952 35689 +26417 78889 +93014 89108 +66327 13137 +40867 10790 +65286 76246 +93712 91171 +73589 30084 +91733 49842 +55558 37212 +11506 83025 +59048 71853 +62575 73247 +96799 92730 +46068 93958 +32722 12454 +42557 26234 +83134 54811 +52665 73128 +38085 69964 +33365 22988 +74033 87903 +49743 38491 +47311 92414 +41588 38093 +78063 48550 +83201 80983 +57980 35192 +58451 71130 +81627 56209 \ No newline at end of file diff --git a/aoc2024/test/day01/python/test_solution.py b/aoc2024/test/day01/python/test_solution.py new file mode 100644 index 0000000..1140a3d --- /dev/null +++ b/aoc2024/test/day01/python/test_solution.py @@ -0,0 +1,38 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import unittest + +from aoc2024.src.day01.python.solution import calculate_distance, calculate_similarity_score +from common.python3.AdventOfCodeTestCase import AdventOfCodeTestCase + + +class TestDay01Solution(AdventOfCodeTestCase): + def __init__(self, *args, **kwargs): + super(TestDay01Solution, self).__init__(__file__, *args, **kwargs) + + def test_part1_withExample_calculatesDistance(self): + self.assertEqual(11, calculate_distance(self.examples[0])) + + def test_part1_withPuzzleInput_calculatesDistance(self): + self.assertEqual(1834060, calculate_distance(self.input)) + + def test_part2_withExample_calculatesSimilarityScore(self): + self.assertEqual(31, calculate_similarity_score(self.examples[0])) + + def test_part2_withPuzzleInput_calculatesSimilarityScore(self): + self.assertEqual(21607792, calculate_similarity_score(self.input)) + + +if __name__ == '__main__': + unittest.main()