Compare commits

...

479 commits

Author SHA1 Message Date
Bruno BELANYI 43650ade44 nix: migrate to 'ruff' formatting
Having just the one tool is better.

Incidentally, this fixes the ternary formatting, which was messed up in
recent `black` versions.
2024-11-23 18:50:16 +00:00
Bruno BELANYI 94befa4d1b nix: bump flake inputs 2024-11-23 18:50:16 +00:00
Bruno BELANYI 601b40e7d4 2023: d25: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI c02a05a0ff 2023: d25: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI fb13cf95c3 2023: d25: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8424bbb2bb 2023: d25: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI ee84fa576d 2023: d24: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI df75f1c5d2 2023: d24: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 5ebf620992 2023: d24: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI fa6c3351b0 2023: d24: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7b0a967765 2023: d23: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1a6bc7c2c7 2023: d23: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 314e894367 2023: d23: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI f07d58e9f2 2023: d23: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI a1c64e606e 2023: d22: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 789b19ad0c 2023: d22: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI fa9ba51cd4 2023: d22: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 27e5a815ba 2023: d22: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 23fb211e92 2023: d21: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0605f5e47f 2023: d21: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI bd30ae97ed 2023: d21: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ba345ca59d 2023: d21: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI e4c930c2fa 2023: d20: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8e31abf2b2 2023: d20: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 4ccebd33ab 2023: d20: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 5a11d5ca5c 2023: d20: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 49dc83b67f 2023: d19: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 03f8a5567b 2023: d19: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI b1bfdee330 2023: d19: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI aedb2c4c14 2023: d19: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI d4aa8d246f 2023: d18: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI b806f8dc39 2023: d18: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI ce0bfe769f 2023: d18: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI bfe11a50f7 2023: d18: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7bbf3d0261 2023: d17: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI faf382cb44 2023: d17: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0e237d6752 2023: d17: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1adbc956ac 2023: d17: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2869e96841 2023: d16: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d5bf9f3c9f 2023: d16: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 36f84c4324 2023: d16: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6c0e372228 2023: d16: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI d35af3ede7 2023: d15: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI e253096a7e 2023: d15: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9407e73b44 2023: d15: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI f1c8a7693b 2023: d15: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 26d37fbe0e 2023: d14: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d39bc20a21 2023: d14: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI c0c824513e 2023: d14: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 58eaa4ea5d 2023: d14: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI e7892e9014 2023: d13: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6a3c87ef2e 2023: d13: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 48175ec659 2023: d13: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7349222bee 2023: d13: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 28faa62410 2023: d12: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI fa6fcf635b 2023: d12: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1ac549afe3 2023: d12: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 65cc5b2e7c 2023: d12: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 30d45a6021 2023: d11: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 73884e9936 2023: d11: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 396aaf22ac 2023: d11: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9168b6850d 2023: d11: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI d471d8f643 2023: d10: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 4309339016 2023: d10: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 151630332e 2023: d10: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 974524b1f1 2023: d10: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI bc41afab0f 2023: d09: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7c7df880ed 2023: d09: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI ffd47cdea7 2023: d09: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7c29d7d889 2023: d09: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 01ecc496a5 2023: d08: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9fa50a7aad 2023: d08: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 140cf8549d 2023: d08: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 59e2d4abcf 2023: d08: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI d4078c91bf 2023: d07: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9b4506da33 2023: d07: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI bb9dff359d 2023: d07: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6917623406 2023: d07: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6b8dbbd938 2023: d06: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 10fb8ca2d1 2023: d06: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1081a4fc8d 2023: d06: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 60da30ee6c 2023: d06: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7d4377d6a2 2023: d05: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ffb2c5346b 2023: d05: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 052d0116fd 2023: d05: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2583ad84d6 2023: d05: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 018cc4a904 2023: d04: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8292a5f323 2023: d04: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI d84554d965 2023: d04: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1490fe1309 2023: d04: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 20d7292d10 2023: d03: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 146529433c 2023: d03: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI c2167dbfc9 2023: d03: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 05f80dc3de 2023: d03: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 3aa39588ed 2023: d02: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6ebbcdeb11 2023: d02: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 355b4f457b 2023: d02: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7a7691c891 2023: d02: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 5b94cedebc 2023: d01: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d0c97d8793 2023: d01: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 771b7f7d25 2023: d01: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8d8f2b1fb1 2023: d01: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 85d39b0f8a nix: bump flake inputs 2024-11-23 18:50:16 +00:00
Bruno BELANYI d392ae4f4a nix: use 'main' branch for 'flake-utils' 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9a3109466b 2022: d25: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI a843028f15 2022: d25: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI bc91ad5dad 2022: d25: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d20e79e2b0 2022: d25: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 5254f96e15 2022: d24: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 83bbd2c36c 2022: d24: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 3389478097 2022: d24: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0f1454045d 2022: d24: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI aa26b73644 2022: d23: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 384d9dcd50 2022: d23: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI e796cc3342 2022: d23: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0bed52bf64 2022: d23: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 23a88b18af 2022: d22: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI bf7ed284c9 2022: d22: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 15a33215f3 2022: d22: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 17f2ffb0ef 2022: d22: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 786f88c001 2022: d21: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6055c7ac23 2022: d21: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI c3a9572407 2022: d21: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI c7f7e2a590 2022: d21: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8d2b7be327 2022: d20: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 815b5a028f 2022: d20: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2c0fbf53c3 2022: d20: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI c7ffb3be10 2022: d20: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 5cd4f7dfd7 2022: d19: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 97222c32ab 2022: d19: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI b1ef193da9 2022: d19: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d8b22599cf 2022: d19: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 43d4b031f5 2022: d18: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 5fc8c07cfd 2022: d18: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI eb007342f2 2022: d18: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ca6a3885b0 2022: d18: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI d2aad80116 2022: d17: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d2fd3abe24 2022: d17: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 4b7ee749a0 2022: d17: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI cc4910cca9 2022: d17: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 10d563b357 2022: d16: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7f36b288e3 2022: d16: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 22b823e283 2022: d16: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9b7ecb60a8 2022: d16: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9c35ca0630 2022: d15: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 18f87be63c 2022: d15: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 58f530c3d1 2022: d15: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI a996fee1d7 2022: d15: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 336a67a2ca 2022: d14: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7b56fdd706 2022: d14: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI ff1de34ee5 2022: d14: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8db6023086 2022: d14: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1551c5ad8e 2022: d13: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0cf1acfecf 2022: d13: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 529a66e33b 2022: d13: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI aba5dfc57b 2022: d13: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 51527eee9d 2022: d12: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 532fb31b03 2022: d12: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 258472ef6a 2022: d12: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 50dd65e63b 2022: d12: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 004a632125 2022: d11: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI a3951a5a47 2022: d11: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI cd577dc37d 2022: d11: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 354d6087a6 2022: d11: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI c01254a5ca 2022: d10: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 96b1ebeb61 2022: d10: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9285442688 2022: d10: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 340b0b4c67 2022: d10: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 420d37b25f 2022: d09: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d1037cd7e5 2022: d09: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 48b9633dfb 2022: d09: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9bbb3e0066 2022: d09: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7d160342d9 2022: d08: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6deca8b1d3 2022: d08: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI d793a7441c 2022: d08: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI e75cb939d7 2022: d08: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7dbf22de6b 2022: d07: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8d8feac390 2022: d07: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 35fad0bd82 2022: d07: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI e995443027 2022: d07: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 4c09d5caa5 2022: d06: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 73ea22bb58 2022: d06: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI aba16a2556 2022: d06: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6dc7baa4a8 2022: d06: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2ea00cec0a 2022: d05: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 50dfee46e6 2022: d05: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 624ccdd863 2022: d05: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 157522996f 2022: d05: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 64a9d16216 2022: d04: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI affe5cd89b 2022: d04: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 742de9ade3 2022: d04: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 197c7060db 2022: d04: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 30ff9c5266 2022: d03: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI edeae4d9f4 2022: d03: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI ef2a4c0700 2022: d03: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6c496ec591 2022: d03: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI b79109ed37 2022: d02: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 439a4362d1 2022: d02: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI ed2497a67c 2022: d02: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0df109da5b 2022: d02: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 06fee9ad24 2022: d01: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 80ee0fddb5 2022: d01: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7054b00043 2022: d01: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 99d677590f 2022: d01: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI a9e68c07d6 nix: use 'nixpkgs-unstable' 2024-11-23 18:50:16 +00:00
Bruno BELANYI c5861c0b22 nix: bump flake inputs 2024-11-23 18:50:16 +00:00
Bruno BELANYI 4efa9d74e3 nix: fix 'pyright' 2024-11-23 18:50:16 +00:00
Bruno BELANYI f65d22ece5 2021: d25: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2fa3ffadeb 2021: d25: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI afb38fba2c 2021: d25: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 4447a4da44 2021: d25: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 18d91fee78 2021: d24: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI f4cd01f6a0 2021: d24: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI ed49448d04 2021: d24: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 4a691b8dd2 2021: d24: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0d3efefaa5 nix: add z3 to python environment 2024-11-23 18:50:16 +00:00
Bruno BELANYI f42b43d8bc nix: use proper python environment 2024-11-23 18:50:16 +00:00
Bruno BELANYI 637c597525 2021: d23: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d04c77d40c 2021: d23: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 42979f727b 2021: d23: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0daf3f7e03 2021: d23: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 14cfc776b7 2021: d22: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 17f903385c 2021: d22: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI ce432cf461 2021: d22: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2dfd17a6de 2021: d22: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0e47d63758 2021: d21: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2975f1f898 2021: d21: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI ead3395a83 2021: d21: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d4d6bbe742 2021: d21: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI da979f53d0 2021: d20: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 52da7aafe9 2021: d20: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 62f0a786c2 2021: d20: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7a502bdc9c 2021: d20: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI a83f108eeb 2021: d19: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ab3bbd0005 2021: d19: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI da2a08ffbe 2021: d19: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 45d5954659 2021: d19: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI a33665b459 2021: d18: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 61d721c57e 2021: d18: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 950af51d0d 2021: d18: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 4f5357a388 2021: d18: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI a34dccc5d6 2021: d17: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 15d5b0ddad 2021: d17: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 54c92ff0fe 2021: d17: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0889e490ee 2021: d17: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9403676d36 2021: d16: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6aaefd6d6f 2021: d16: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI e4e9042c0f 2021: d16: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 918aa91aba 2021: d16: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI fcce87c199 2021: d15: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8c09efb227 2021: d15: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI a4b81dac45 2021: d15: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7c0034e8af 2021: d15: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2730bcf359 2021: d14: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1ed52f1113 2021: d14: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 5ad6df511b 2021: d14: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI df55bc9993 2021: d14: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 006e9e3ac6 nix: add tools to devShell 2024-11-23 18:50:16 +00:00
Bruno BELANYI 39c5d2e59a 2019: d07: ex1: quieten Mypy 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0532cbeac3 2021: d13: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 07d150e796 2021: d13: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI b9860d1f32 2021: d13: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI f314b9d753 2021: d13: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9f4688d8c0 2021: d12: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI bf519c8eab 2021: d12: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI d4907958ac 2021: d12: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 53489b62d6 2021: d12: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 00e984420c 2021: d11: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 4e7552b34e 2021: d11: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI c2cb30c7df 2021: d11: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 60f8aca9dd 2021: d11: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI bf6881bacb 2021: d10: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 85630222fc 2021: d10: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 295309a0f7 2021: d10: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 43621f22b2 2021: d10: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 75a9a4710c 2021: d09: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d06866158f 2021: d09: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 137a98e936 2021: d09: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 20f7e96cc5 2021: d09: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI b5824be5ba 2021: d08: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7c89ca9499 2021: d08: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 77741100e6 2021: d08: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2ec356e556 2021: d08: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7e63d778f4 2021: d07: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 5eda15460b 2021: d07: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI fa4ea4511a 2021: d07: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6cc0dc453b 2021: d07: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8cb61c6323 2021: d06: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI b00e4768fc 2021: d06: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI fb40ea0517 2021: d06: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 660748c6ab 2021: d06: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 245e9dc998 2021: d05: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI a3d1c6b0a9 2021: d05: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 09ea244442 2021: d05: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9f8ab70690 2021: d05: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 003071a57b 2021: d04: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2c11ec6866 2021: d04: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1d61133661 2021: d04: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9624c49a35 2021: d04: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI d1122ab561 2021: d03: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ef8d402a3d 2021: d03: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 95ae7df24e 2021: d03: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 94788946a3 2021: d03: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 94b43da45c 2021: d02: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI fe0d20ad03 2021: d02: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 82b8354edc 2021: d02: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ec1558efe2 2021: d02: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2646a1609d 2021: d01: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 05afd2ea64 2021: d01: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 74e43afa72 2021: d01: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI dcd66ec6f4 2021: d01: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 87a8b8a3d3 git: ignore generated files 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9159553e6b nix: add direnv integration 2024-11-23 18:50:16 +00:00
Bruno BELANYI 75b16e08b1 isort: use 'black' compatible style 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0547c87c24 nix: add flake 2024-11-23 18:50:16 +00:00
Bruno BELANYI e69a451189 2020: d25: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 079e7358de 2020: d25: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 68a8ae07fa 2020: d25: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 40cf84e081 2020: d25: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 856efa526e 2020: d24: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI c9f0b0b1ba 2020: d24: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI f5c1b03ddd 2020: d24: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI cbdbc36563 2020: d24: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI c4b6536598 2020: d23: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d0e1d5b427 2020: d23: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI e9c449ee09 2020: d23: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI b7e3101d3a 2020: d23: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9be6801527 2020: d22: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI b49e09cf9f 2020: d22: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 21fd56d96d 2020: d22: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 56fe76bbaf 2020: d22: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9f0f9be2d1 2020: d21: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d412cac964 2020: d21: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6551796830 2020: d21: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2302d6e0ae 2020: d21: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9eb34faac0 2020: d20: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI a550355ebe 2020: d20: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 87376fc0ee 2020: d20: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 10e84ed48f 2020: d20: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 49a934f8f6 2020: d19: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1d4ec885a4 2020: d19: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI f39187ba8a 2020: d19: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 3b049944e2 2020: d19: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 874ab7acad 2020: d18: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8dd7c465de 2020: d18: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI b438c7f822 2020: d18: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI c2a38319af 2020: d18: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI ed3fa75fb9 2020: d17: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8f8d4e6b85 2020: d17: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2eb9429f69 2020: d17: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 69f0ba61c0 2020: d17: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 85ed83d9a8 2020: d16: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 275234df8d 2020: d16: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 773150f281 2020: d16: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI e59c6d4d1b 2020: d16: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2c67bb79bd 2020: d15: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 61b0b76019 2020: d15: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI a84e93e8a0 2020: d15: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7177c0f2b2 2020: d15: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9d60496ca5 2020: d15: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI fc7ea5bc2b 2020: d15: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1f2d646838 2020: d14: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1c07b0c59e 2020: d14: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 81780a4b72 2020: d13: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI eccc4f3583 2020: d13: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI a34941dbd9 2020: d13: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI c2d2c14696 2020: d13: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 2c31559722 2020: d12: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0edcccdd02 2020: d12: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 139f3db14f 2020: d12: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 0947c9eb77 2020: d12: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI e4a0d61ebc 2020: d11: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 26fc4a365e 2020: d11: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1425fd5c4c 2020: d11: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d86e1f8701 2020: d11: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 56aea0db79 2020: d10: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1f36ec0cd1 2020: d10: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 386c912dbe 2020: d10: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ed5cdb1a95 2020: d10: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI b24b690a61 2020: d09: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ec31ee08e7 2020: d09: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI efe0bb2b4b 2020: d09: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI e8bda4380d 2020: d09: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI c81bc2c5d8 2020: d08: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI e07ca6ed2e 2020: d08: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1aa6199879 2020: d08: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI bc0ee515ba 2020: d08: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI e6396d4606 2020: d07: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI d6d7c4cd0c 2020: d07: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 6c160a5350 2020: d07: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI c0bd3a54d0 2020: d07: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI bdcd821ea5 2020: d06: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 09be17972e 2020: d06: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 56e70c444d 2020: d06: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 45571a06d3 2020: d06: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 57a50ec803 2020: d05: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 32597cd01a 2020: d05: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 39d5509da5 2020: d05: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 83e4e426ab 2020: d05: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI f8afee351c 2020: d04: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 586e95d353 2020: d04: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI cdbfc2b973 2020: d04: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI a76a244779 2020: d04: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 721750965b 2020: d03: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI b9bed5c506 2020: d03: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8efe93e278 2020: d03: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 3fbdb62a6d 2020: d03: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI f9852eac25 2019: d19: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ddf4217147 2019: d19: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 3ad3b9df5d 2019: d19: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 5c8bee8741 2019: d19: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 09b8e80ca2 2019: d18: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ebeebbe5ea 2019: d18: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 30fe0f5786 2019: d18: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI a268eb1f1e 2019: d18: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 04329c9fd3 2020: d02: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 28ee1e006d 2020: d02: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 4f8c876f2d 2020: d02: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 84ea3e2325 2020: d02: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI a1578499a1 2020: d01: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI a5e4bf1715 2020: d01: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 186c3981c2 2020: d01: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ec30c78511 2020: d01: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 70d7ffc8c6 2019: d17: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 27995b2bb9 2019: d17: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI f416b7c366 2019: d17: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI a895dc761a 2019: d17: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 576769e648 2019: d16: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 9e0b69d56e 2019: d16: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8ad65f864f 2019: d16: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 36dfeb9fc2 2019: d16: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI c1047501a6 2019: d15: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 3217af1859 2019: d15: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 90cc65bb3a 2019: d15: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 65cb0c224b 2019: d15: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 947a6e9970 2019: d14: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 68df040691 2019: d14: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI f4bd381a1a 2019: d14: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI e85fa35b30 2019: d14: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI eebd801537 2019: d13: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI bb41df8709 2019: d13: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 223851a430 2019: d13: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8713082ed6 2019: d13: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 3c10941835 2019: d12: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI b2ea586869 2019: d12: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI d6d0f1a94f 2019: d12: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ca46ca6de8 2019: d12: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 699792cf12 2019: d11: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 3f55e37b82 2019: d11: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8de251a301 2019: d11: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 5f776c6880 2019: d11: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1242388be7 2019: d10: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 59af5aae07 2019: d10: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 47f702ec2e 2019: d10: ex1: clean-up solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI cf42aaa2b0 2019: d10: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 72a07f9ac4 2019: d10: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 3106914906 2019: d09: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ad8a08e494 2019: d09: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI fc2aa2df6d 2019: d09: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI c5e3cac6ed 2019: d09: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI b15c967b8d 2019: d08: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 8335513623 2019: d08: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 1b5bd3faf5 2019: d08: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI a37ef81ec3 2019: d08: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI df3542b7d8 2019: d07: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 77bcb1e560 2019: d07: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI cb6025af46 2019: d07: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 74847ab4d8 2019: d07: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 24062ea43a 2019: d06: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI e411c20e5a 2019: d06: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 5d88e60832 2019: d06: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 4b549d4b23 2019: d06: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI e12a9c9333 2019: d05: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 35cf0da3dc 2019: d05: ex2: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 7b27a4a2fa 2019: d05: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI ab3a8a8247 2019: d05: ex1: add input 2024-11-23 18:50:16 +00:00
Bruno BELANYI 67a5bb9695 2019: d04: ex2: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 00ec65e9b0 2019: d04: ex1: add solution 2024-11-23 18:50:16 +00:00
Bruno BELANYI 59fafe6140 2019: d03: ex2: add solution 2024-11-23 18:50:16 +00:00
467 changed files with 129075 additions and 0 deletions

7
.envrc Normal file
View file

@ -0,0 +1,7 @@
use_flake() {
watch_file flake.nix
watch_file flake.lock
eval "$(nix print-dev-env)"
}
use flake

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
# Generated by Nix
/.pre-commit-config.yaml

108
2019/d03/ex2/ex2.py Executable file
View file

@ -0,0 +1,108 @@
#!/usr/bin/env python
import sys
from fractions import Fraction
from typing import List, NamedTuple, Optional
class Point(NamedTuple):
x: int
y: int
class Line(NamedTuple):
p1: Point
p2: Point
def manhattan_dist(p1: Point, p2: Point = Point(0, 0)) -> int:
dx = p2.x - p1.x if p1.x < p2.x else p1.x - p2.x
dy = p2.y - p1.y if p1.y < p2.y else p1.y - p2.y
return dx + dy
def intersect(l1: Line, l2: Line) -> Optional[Point]:
(x1, y1), (x2, y2) = l1.p1, l1.p2
(x3, y3), (x4, y4) = l2.p1, l2.p2
den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
if den == 0: # Parallel lines
return None
t = Fraction((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4), den)
if t < 0 or t > 1: # Out of l1
return None
u = -Fraction((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3), den)
if u < 0 or u > 1: # Out of l2
return None
dx = t * (x2 - x1)
dy = t * (y2 - y1)
assert int(dx) == dx and int(dy) == dy # Sanity checks
ix = x1 + int(dx)
iy = y1 + int(dy)
return Point(ix, iy)
def is_on(p: Point, l: Line) -> bool:
# Assume that l is horizontal or vertical
if l.p1.x == l.p2.x:
if l.p1.y < l.p2.y:
return p.x == l.p1.x and l.p1.y <= p.y <= l.p2.y
elif l.p2.y < l.p1.y:
return p.x == l.p1.x and l.p2.y <= p.y <= l.p1.y
elif l.p1.y == l.p2.y:
if l.p1.x < l.p2.x:
return p.y == l.p1.y and l.p1.x <= p.x <= l.p2.x
elif l.p2.x < l.p1.x:
return p.y == l.p1.y and l.p2.x <= p.x <= l.p1.x
assert False # Sanity checks
def parse_line(directions: str) -> List[Line]:
prev = Point(0, 0)
ans = []
for inst in directions.split(","):
direction, length = inst[0], int(inst[1:])
new_x, new_y = prev
if direction == "U":
new_y += length
elif direction == "R":
new_x += length
if direction == "D":
new_y -= length
elif direction == "L":
new_x -= length
new = Point(new_x, new_y)
ans.append(Line(prev, new))
prev = new
return ans
def compute_delay(p: Point, lines: List[Line]) -> int:
dist = 0
for l in lines:
if is_on(p, l):
return dist + manhattan_dist(l.p1, p)
dist += manhattan_dist(l.p1, l.p2)
assert False # Sanity check
def main() -> None:
wire1, wire2 = tuple(parse_line(l) for l in sys.stdin)
intersections = [intersect(l1, l2) for l1 in wire1 for l2 in wire2]
print(
min(
compute_delay(x, wire1) + compute_delay(x, wire2)
for x in intersections
if x is not None and x != Point(0, 0) # Discard origin
)
)
if __name__ == "__main__":
main()

34
2019/d04/ex1/ex1.py Executable file
View file

@ -0,0 +1,34 @@
#!/usr/bin/env python
from typing import Iterator
def is_valid_password(p: int) -> bool:
digits = str(p)
def has_adjacent_digit():
for a, b in zip(digits, digits[1:]):
if a == b:
return True
return False
def digits_never_decrease():
return all(a == b for a, b in zip(sorted(digits), digits))
return has_adjacent_digit() and digits_never_decrease()
def compute_pass(begin: int, end: int) -> Iterator[int]:
for p in range(begin, end + 1):
if is_valid_password(p):
yield p
def main() -> None:
begin = 264793
end = 803935
print(sum(1 for p in compute_pass(begin, end)))
if __name__ == "__main__":
main()

35
2019/d04/ex2/ex2.py Executable file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env python
from typing import Iterator
def is_valid_password(p: int) -> bool:
digits = str(p)
def has_unique_adjacent_digit():
counts = {d: 0 for d in range(10)}
for a, b in zip(digits, digits[1:]):
if a == b:
counts[int(a)] += 1
return any(count == 1 for count in counts.values())
def digits_never_decrease():
return all(a == b for a, b in zip(sorted(digits), digits))
return has_unique_adjacent_digit() and digits_never_decrease()
def compute_pass(begin: int, end: int) -> Iterator[int]:
for p in range(begin, end + 1):
if is_valid_password(p):
yield p
def main() -> None:
begin = 264793
end = 803935
print(sum(1 for p in compute_pass(begin, end)))
if __name__ == "__main__":
main()

101
2019/d05/ex1/ex1.py Executable file
View file

@ -0,0 +1,101 @@
#!/usr/bin/env python
from enum import IntEnum
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
def do_addition(instr: Instruction, memory: List[int]) -> int:
lhs, rhs, dest = memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = memory[lhs]
if instr.p2_mode == ParameterMode.POSITION:
rhs = memory[rhs]
assert instr.p3_mode != ParameterMode.IMMEDIATE # Sanity check
memory[dest] = lhs + rhs
return 4 # Length of the instruction
def do_multiplication(instr: Instruction, memory: List[int]) -> int:
lhs, rhs, dest = memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = memory[lhs]
if instr.p2_mode == ParameterMode.POSITION:
rhs = memory[rhs]
assert instr.p3_mode != ParameterMode.IMMEDIATE # Sanity check
memory[dest] = lhs * rhs
return 4 # Length of the instruction
def do_input(instr: Instruction, memory: List[int]) -> int:
value = int(input())
param = memory[instr.address + 1]
assert instr.p1_mode == ParameterMode.POSITION # Sanity check
memory[param] = value
return 2 # Length of the instruction
def do_output(instr: Instruction, memory: List[int]) -> int:
value = memory[instr.address + 1]
if instr.p1_mode == ParameterMode.POSITION:
value = memory[value]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
print(value)
return 2 # Length of the instruction
def run_op(memory: List[int]) -> None:
index = 0
while True:
instr = lookup_ops(index, memory)
if instr.op == 99: # Halt
return
elif instr.op == 1: # Sum
index += do_addition(instr, memory)
elif instr.op == 2: # Multiplication
index += do_multiplication(instr, memory)
elif instr.op == 3: # Load from input
index += do_input(instr, memory)
elif instr.op == 4: # Store to output
index += do_output(instr, memory)
def main() -> None:
with open("input") as mem_f:
memory = [int(n) for n in mem_f.read().split(",")]
run_op(memory)
if __name__ == "__main__":
main()

1
2019/d05/ex1/input Normal file
View file

@ -0,0 +1 @@
3,225,1,225,6,6,1100,1,238,225,104,0,1002,114,46,224,1001,224,-736,224,4,224,1002,223,8,223,1001,224,3,224,1,223,224,223,1,166,195,224,1001,224,-137,224,4,224,102,8,223,223,101,5,224,224,1,223,224,223,1001,169,83,224,1001,224,-90,224,4,224,102,8,223,223,1001,224,2,224,1,224,223,223,101,44,117,224,101,-131,224,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,1101,80,17,225,1101,56,51,225,1101,78,89,225,1102,48,16,225,1101,87,78,225,1102,34,33,224,101,-1122,224,224,4,224,1002,223,8,223,101,7,224,224,1,223,224,223,1101,66,53,224,101,-119,224,224,4,224,102,8,223,223,1001,224,5,224,1,223,224,223,1102,51,49,225,1101,7,15,225,2,110,106,224,1001,224,-4539,224,4,224,102,8,223,223,101,3,224,224,1,223,224,223,1102,88,78,225,102,78,101,224,101,-6240,224,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1107,226,677,224,102,2,223,223,1006,224,329,101,1,223,223,1108,226,677,224,1002,223,2,223,1005,224,344,101,1,223,223,8,226,677,224,102,2,223,223,1006,224,359,1001,223,1,223,1007,226,677,224,1002,223,2,223,1005,224,374,101,1,223,223,1008,677,677,224,1002,223,2,223,1005,224,389,1001,223,1,223,1108,677,226,224,1002,223,2,223,1006,224,404,1001,223,1,223,1007,226,226,224,1002,223,2,223,1005,224,419,1001,223,1,223,1107,677,226,224,1002,223,2,223,1006,224,434,101,1,223,223,108,677,677,224,1002,223,2,223,1005,224,449,1001,223,1,223,1107,677,677,224,102,2,223,223,1005,224,464,1001,223,1,223,108,226,226,224,1002,223,2,223,1006,224,479,1001,223,1,223,1008,226,226,224,102,2,223,223,1005,224,494,101,1,223,223,108,677,226,224,102,2,223,223,1005,224,509,1001,223,1,223,8,677,226,224,1002,223,2,223,1006,224,524,101,1,223,223,7,226,677,224,1002,223,2,223,1006,224,539,101,1,223,223,7,677,226,224,102,2,223,223,1006,224,554,1001,223,1,223,7,226,226,224,1002,223,2,223,1006,224,569,101,1,223,223,107,677,677,224,102,2,223,223,1006,224,584,101,1,223,223,1108,677,677,224,102,2,223,223,1006,224,599,1001,223,1,223,1008,677,226,224,1002,223,2,223,1005,224,614,1001,223,1,223,8,677,677,224,1002,223,2,223,1006,224,629,1001,223,1,223,107,226,677,224,1002,223,2,223,1006,224,644,101,1,223,223,1007,677,677,224,102,2,223,223,1006,224,659,101,1,223,223,107,226,226,224,1002,223,2,223,1006,224,674,1001,223,1,223,4,223,99,226

199
2019/d05/ex2/ex2.py Executable file
View file

@ -0,0 +1,199 @@
#!/usr/bin/env python
from dataclasses import dataclass
from enum import IntEnum
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
def run(self):
while True:
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
return
elif instr.op == 1: # Sum
self.do_addition(instr)
elif instr.op == 2: # Multiplication
self.do_multiplication(instr)
elif instr.op == 3: # Load from input
self.do_input(instr)
elif instr.op == 4: # Store to output
self.do_output(instr)
elif instr.op == 5: # Jump if true
self.do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self.do_jump_if_false(instr)
elif instr.op == 7: # Less than
self.do_less_than(instr)
elif instr.op == 8: # Equal to
self.do_equal_to(instr)
else:
assert False # Sanity check
def do_addition(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs + rhs
self.rip += 4 # Length of the instruction
def do_multiplication(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs * rhs
self.rip += 4 # Length of the instruction
def do_input(self, instr: Instruction) -> None:
value = int(input())
param = self.memory[instr.address + 1]
assert instr.p1_mode == ParameterMode.POSITION # Sanity check
self.memory[param] = value
self.rip += 2 # Length of the instruction
def do_output(self, instr: Instruction) -> None:
value = self.memory[instr.address + 1]
if instr.p1_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
print(value)
self.rip += 2 # Length of the instruction
def do_jump_if_true(self, instr: Instruction) -> None:
cond, value = self.memory[instr.address + 1 : instr.address + 3]
if instr.p1_mode == ParameterMode.POSITION:
cond = self.memory[cond]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def do_jump_if_false(self, instr: Instruction) -> None:
cond, value = self.memory[instr.address + 1 : instr.address + 3]
if instr.p1_mode == ParameterMode.POSITION:
cond = self.memory[cond]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def do_less_than(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs < rhs else 0
self.rip += 4 # Length of the instruction
def do_equal_to(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs == rhs else 0
self.rip += 4 # Length of the instruction
def main() -> None:
with open("input") as mem_f:
memory = [int(n) for n in mem_f.read().split(",")]
computer = Computer(memory)
computer.run()
if __name__ == "__main__":
main()

1
2019/d05/ex2/input Normal file
View file

@ -0,0 +1 @@
3,225,1,225,6,6,1100,1,238,225,104,0,1002,114,46,224,1001,224,-736,224,4,224,1002,223,8,223,1001,224,3,224,1,223,224,223,1,166,195,224,1001,224,-137,224,4,224,102,8,223,223,101,5,224,224,1,223,224,223,1001,169,83,224,1001,224,-90,224,4,224,102,8,223,223,1001,224,2,224,1,224,223,223,101,44,117,224,101,-131,224,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,1101,80,17,225,1101,56,51,225,1101,78,89,225,1102,48,16,225,1101,87,78,225,1102,34,33,224,101,-1122,224,224,4,224,1002,223,8,223,101,7,224,224,1,223,224,223,1101,66,53,224,101,-119,224,224,4,224,102,8,223,223,1001,224,5,224,1,223,224,223,1102,51,49,225,1101,7,15,225,2,110,106,224,1001,224,-4539,224,4,224,102,8,223,223,101,3,224,224,1,223,224,223,1102,88,78,225,102,78,101,224,101,-6240,224,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1107,226,677,224,102,2,223,223,1006,224,329,101,1,223,223,1108,226,677,224,1002,223,2,223,1005,224,344,101,1,223,223,8,226,677,224,102,2,223,223,1006,224,359,1001,223,1,223,1007,226,677,224,1002,223,2,223,1005,224,374,101,1,223,223,1008,677,677,224,1002,223,2,223,1005,224,389,1001,223,1,223,1108,677,226,224,1002,223,2,223,1006,224,404,1001,223,1,223,1007,226,226,224,1002,223,2,223,1005,224,419,1001,223,1,223,1107,677,226,224,1002,223,2,223,1006,224,434,101,1,223,223,108,677,677,224,1002,223,2,223,1005,224,449,1001,223,1,223,1107,677,677,224,102,2,223,223,1005,224,464,1001,223,1,223,108,226,226,224,1002,223,2,223,1006,224,479,1001,223,1,223,1008,226,226,224,102,2,223,223,1005,224,494,101,1,223,223,108,677,226,224,102,2,223,223,1005,224,509,1001,223,1,223,8,677,226,224,1002,223,2,223,1006,224,524,101,1,223,223,7,226,677,224,1002,223,2,223,1006,224,539,101,1,223,223,7,677,226,224,102,2,223,223,1006,224,554,1001,223,1,223,7,226,226,224,1002,223,2,223,1006,224,569,101,1,223,223,107,677,677,224,102,2,223,223,1006,224,584,101,1,223,223,1108,677,677,224,102,2,223,223,1006,224,599,1001,223,1,223,1008,677,226,224,1002,223,2,223,1005,224,614,1001,223,1,223,8,677,677,224,1002,223,2,223,1006,224,629,1001,223,1,223,107,226,677,224,1002,223,2,223,1006,224,644,101,1,223,223,1007,677,677,224,102,2,223,223,1006,224,659,101,1,223,223,107,226,226,224,1002,223,2,223,1006,224,674,1001,223,1,223,4,223,99,226

53
2019/d06/ex1/ex1.py Executable file
View file

@ -0,0 +1,53 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from typing import Dict, List
@dataclass
class OrbitGraph:
name: str
children: List["OrbitGraph"] = field(default_factory=list)
def make_orbits(description: List[str]) -> OrbitGraph:
orbits: Dict[str, OrbitGraph] = {}
def find_or_add(name: str) -> OrbitGraph:
if name in orbits:
return orbits[name]
orbit = OrbitGraph(name)
orbits[name] = orbit
return orbit
for l in description:
parent, child = map(find_or_add, map(lambda x: x.strip(), l.split(")")))
parent.children.append(child)
return orbits["COM"] # Assume common root is named 'COM'
def count_orbits(root: OrbitGraph) -> int:
ans = 0
stack = 0 # Count the number of direct and indirect orbits to the current root
def helper(root: OrbitGraph):
nonlocal ans
nonlocal stack
ans += stack # Count the number of orbits to this node
stack += 1 # Add the current root to stack of parents
for child in root.children:
helper(child) # Count those orbits for each child
stack -= 1 # Remove the current root from the stack of parents
helper(root)
return ans
def main() -> None:
print(count_orbits(make_orbits(sys.stdin.readlines())))
if __name__ == "__main__":
main()

1069
2019/d06/ex1/input Normal file

File diff suppressed because it is too large Load diff

86
2019/d06/ex2/ex2.py Executable file
View file

@ -0,0 +1,86 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from typing import Dict, List, Optional
@dataclass
class OrbitGraph:
name: str
children: List["OrbitGraph"] = field(default_factory=list)
def make_orbits(description: List[str]) -> OrbitGraph:
orbits: Dict[str, OrbitGraph] = {}
def find_or_add(name: str) -> OrbitGraph:
if name in orbits:
return orbits[name]
orbit = OrbitGraph(name)
orbits[name] = orbit
return orbit
for l in description:
parent, child = map(find_or_add, map(lambda x: x.strip(), l.split(")")))
parent.children.append(child)
return orbits["COM"] # Assume common root is named 'COM'
def count_orbits_hop(root: OrbitGraph) -> int:
nodes: List[OrbitGraph] = []
def ind_node(node: OrbitGraph) -> int:
return nodes.index(node)
def fill_nodes(root: OrbitGraph) -> None:
nodes.append(root)
for child in root.children:
fill_nodes(child)
fill_nodes(root)
n = len(nodes)
dist: List[List[int]] = [[2 * n] * len(nodes) for __ in range(len(nodes))]
next_nodes: List[List[Optional[OrbitGraph]]] = [[None] * n for __ in range(n)]
def fill_mat(root: OrbitGraph) -> None:
# From root to itself
dist[ind_node(root)][ind_node(root)] = 0
next_nodes[ind_node(root)][ind_node(root)] = root
for child in root.children:
# From root to child
dist[ind_node(root)][ind_node(child)] = 1
next_nodes[ind_node(root)][ind_node(child)] = child
# The other way
dist[ind_node(child)][ind_node(root)] = 1
next_nodes[ind_node(child)][ind_node(root)] = root
# Do it again
fill_mat(child)
fill_mat(root)
for k in range(n):
print(f"{k} / {n} rounds")
for i in range(n):
for j in range(n):
new_dist = dist[i][k] + dist[k][j]
if dist[i][j] > new_dist:
dist[i][j] = new_dist
next_nodes[i][j] = next_nodes[i][k]
useful_indices: Dict[str, int] = {}
for index, node in enumerate(nodes):
if node.name in ("YOU", "SAN"):
useful_indices[node.name] = index
return (
dist[useful_indices["YOU"]][useful_indices["SAN"]] - 2
) # Because we are in orbit
def main() -> None:
print(count_orbits_hop(make_orbits(sys.stdin.readlines())))
if __name__ == "__main__":
main()

1069
2019/d06/ex2/input Normal file

File diff suppressed because it is too large Load diff

263
2019/d07/ex1/ex1.py Executable file
View file

@ -0,0 +1,263 @@
#!/usr/bin/env python
# Mypy has issues with assigning Callable to fields of objects
# See https://github.com/python/mypy/issues/708
# type: ignore
import itertools
import sys
from copy import deepcopy
from dataclasses import dataclass
from enum import IntEnum
from typing import Callable, List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
read_input: Callable[[], str] = input
print_output: Callable[[int], None] = print
def run(self) -> None:
is_halted = self.run_single()
while not is_halted:
is_halted = self.run_single()
def run_single(self) -> bool: # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
return True # Halted
elif instr.op == 1: # Sum
self.do_addition(instr)
elif instr.op == 2: # Multiplication
self.do_multiplication(instr)
elif instr.op == 3: # Load from input
self.do_input(instr)
elif instr.op == 4: # Store to output
self.do_output(instr)
elif instr.op == 5: # Jump if true
self.do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self.do_jump_if_false(instr)
elif instr.op == 7: # Less than
self.do_less_than(instr)
elif instr.op == 8: # Equal to
self.do_equal_to(instr)
else:
assert False # Sanity check
return False # Not halted
def do_addition(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs + rhs
self.rip += 4 # Length of the instruction
def do_multiplication(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs * rhs
self.rip += 4 # Length of the instruction
def do_input(self, instr: Instruction) -> None:
value = int(self.read_input())
param = self.memory[instr.address + 1]
assert instr.p1_mode == ParameterMode.POSITION # Sanity check
self.memory[param] = value
self.rip += 2 # Length of the instruction
def do_output(self, instr: Instruction) -> None:
value = self.memory[instr.address + 1]
if instr.p1_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
self.print_output(value)
self.rip += 2 # Length of the instruction
def do_jump_if_true(self, instr: Instruction) -> None:
cond, value = self.memory[instr.address + 1 : instr.address + 3]
if instr.p1_mode == ParameterMode.POSITION:
cond = self.memory[cond]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def do_jump_if_false(self, instr: Instruction) -> None:
cond, value = self.memory[instr.address + 1 : instr.address + 3]
if instr.p1_mode == ParameterMode.POSITION:
cond = self.memory[cond]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def do_less_than(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs < rhs else 0
self.rip += 4 # Length of the instruction
def do_equal_to(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs == rhs else 0
self.rip += 4 # Length of the instruction
def main() -> None:
def get_input_fun(phase: int, last_output: List[int]) -> Callable[[], str]:
has_been_called = False
def _input() -> str:
nonlocal has_been_called
if has_been_called:
return str(last_output.pop(0))
has_been_called = True
return str(phase)
return _input
memory = [int(n) for n in sys.stdin.read().split(",")]
max = 0
ans = tuple(-1 for __ in range(5))
for a, b, c, d, e in itertools.permutations(range(5)):
amp1 = Computer(deepcopy(memory))
amp1_output: List[int] = []
amp1.read_input = get_input_fun(a, [0])
amp1.print_output = lambda x: amp1_output.append(int(x))
amp2 = Computer(deepcopy(memory))
amp2_output: List[int] = []
amp2.read_input = get_input_fun(b, amp1_output)
amp2.print_output = lambda x: amp2_output.append(int(x))
amp3 = Computer(deepcopy(memory))
amp3_output: List[int] = []
amp3.read_input = get_input_fun(c, amp2_output)
amp3.print_output = lambda x: amp3_output.append(int(x))
amp4 = Computer(deepcopy(memory))
amp4_output: List[int] = []
amp4.read_input = get_input_fun(d, amp3_output)
amp4.print_output = lambda x: amp4_output.append(int(x))
amp5 = Computer(deepcopy(memory))
amp5_output: List[int] = []
amp5.read_input = get_input_fun(e, amp4_output)
amp5.print_output = lambda x: amp5_output.append(int(x))
amp1.run()
amp2.run()
amp3.run()
amp4.run()
amp5.run()
res = amp5_output.pop(0)
if res > max:
max = res
ans = (a, b, c, d, e)
print(f"Max: {max}, res: {ans}")
print(f"Final one: {max}, with {ans}")
if __name__ == "__main__":
main()

1
2019/d07/ex1/input Normal file
View file

@ -0,0 +1 @@
3,8,1001,8,10,8,105,1,0,0,21,46,55,76,89,106,187,268,349,430,99999,3,9,101,4,9,9,1002,9,2,9,101,5,9,9,1002,9,2,9,101,2,9,9,4,9,99,3,9,1002,9,5,9,4,9,99,3,9,1001,9,2,9,1002,9,4,9,101,2,9,9,1002,9,3,9,4,9,99,3,9,1001,9,3,9,1002,9,2,9,4,9,99,3,9,1002,9,4,9,1001,9,4,9,102,5,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,99

196
2019/d07/ex2/ex2.py Executable file
View file

@ -0,0 +1,196 @@
#!/usr/bin/env python
import itertools
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import IntEnum
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
else:
assert False # Sanity check
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs + rhs
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs * rhs
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
assert instr.p1_mode == ParameterMode.POSITION # Sanity check
self.memory[param] = value
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs < rhs else 0
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs == rhs else 0
self.rip += 4 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
max = 0
ans = tuple(-1 for __ in range(5))
for perm in itertools.permutations(range(5, 10)):
amps = [Computer(deepcopy(memory), input_list=[phase]) for phase in perm]
amp1 = amps[0] # Keep track of this guy for the output solution
amp1.input_list.append(0) # Initial input
while not all(amp.is_halted for amp in amps):
# Put a non halted comuter to the front
while amps[0].is_halted:
amps.append(amps.pop(0))
# Run it until exhaustion or input/output interrupt
try:
amps[0].run()
except InputInterrupt:
amps.append(amps.pop(0))
except OutputInterrupt:
amps[1].input_list.append(amps[0].output_list.pop())
res = amp1.input_list.pop(0) # Amplifier 5 output to amplifier 1 at the end
if res > max:
max = res
ans = perm
print(f"Max: {max}, res: {ans}")
print(f"Final one: {max}, with {ans}")
if __name__ == "__main__":
main()

1
2019/d07/ex2/input Normal file
View file

@ -0,0 +1 @@
3,8,1001,8,10,8,105,1,0,0,21,46,55,76,89,106,187,268,349,430,99999,3,9,101,4,9,9,1002,9,2,9,101,5,9,9,1002,9,2,9,101,2,9,9,4,9,99,3,9,1002,9,5,9,4,9,99,3,9,1001,9,2,9,1002,9,4,9,101,2,9,9,1002,9,3,9,4,9,99,3,9,1001,9,3,9,1002,9,2,9,4,9,99,3,9,1002,9,4,9,1001,9,4,9,102,5,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,99

25
2019/d08/ex1/ex1.py Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env python
import sys
def main() -> None:
COLUMNS = 25
ROWS = 6
digits = [int(d) for d in str(int(sys.stdin.read()))]
assert len(digits) % (COLUMNS * ROWS) == 0 # Sanity check
LAYERS = int(len(digits) / (COLUMNS * ROWS))
layers = [
[digits.pop(0) for __ in range(COLUMNS) for __ in range(ROWS)]
for __ in range(LAYERS)
]
least_zeros = min(layers, key=lambda l: sum(1 for d in l if d == 0))
print(sum(1 for d in least_zeros if d == 1) * sum(1 for d in least_zeros if d == 2))
if __name__ == "__main__":
main()

1
2019/d08/ex1/input Normal file

File diff suppressed because one or more lines are too long

32
2019/d08/ex2/ex2.py Executable file
View file

@ -0,0 +1,32 @@
#!/usr/bin/env python
import sys
def main() -> None:
COLUMNS = 25
ROWS = 6
digits = [int(d) for d in str(int(sys.stdin.read()))]
assert len(digits) % (COLUMNS * ROWS) == 0 # Sanity check
LAYERS = int(len(digits) / (COLUMNS * ROWS))
layers = [
[digits.pop(0) for __ in range(COLUMNS) for __ in range(ROWS)]
for __ in range(LAYERS)
]
ans = []
for pixels in zip(*(layer for layer in layers)):
ans.append(next(color for color in pixels if color != 2))
print(
"\n".join(
"".join("" if ans.pop(0) == 0 else " " for __ in range(COLUMNS))
for __ in range(ROWS)
)
)
if __name__ == "__main__":
main()

1
2019/d08/ex2/input Normal file

File diff suppressed because one or more lines are too long

210
2019/d09/ex1/ex1.py Executable file
View file

@ -0,0 +1,210 @@
#!/usr/bin/env python
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import IntEnum
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
computer = Computer(deepcopy(memory), input_list=[1])
computer.run_no_output_interrupt()
print(computer.output_list.pop())
assert len(computer.output_list) == 0 # Sanity check
if __name__ == "__main__":
main()

1
2019/d09/ex1/input Normal file
View file

@ -0,0 +1 @@
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,1,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,26,1,1005,1101,0,24,1019,1102,1,32,1007,1101,0,704,1027,1102,0,1,1020,1101,0,348,1029,1102,28,1,1002,1101,34,0,1016,1102,29,1,1008,1102,1,30,1013,1102,25,1,1012,1101,0,33,1009,1102,1,37,1001,1101,31,0,1017,1101,245,0,1022,1102,39,1,1000,1101,27,0,1011,1102,770,1,1025,1101,0,22,1015,1102,1,1,1021,1101,711,0,1026,1101,20,0,1004,1101,0,23,1018,1101,242,0,1023,1102,21,1,1003,1101,38,0,1010,1101,0,35,1014,1101,0,36,1006,1101,0,357,1028,1102,1,775,1024,109,-3,2102,1,9,63,1008,63,36,63,1005,63,203,4,187,1105,1,207,1001,64,1,64,1002,64,2,64,109,8,21101,40,0,5,1008,1010,41,63,1005,63,227,1106,0,233,4,213,1001,64,1,64,1002,64,2,64,109,16,2105,1,2,1105,1,251,4,239,1001,64,1,64,1002,64,2,64,109,1,21107,41,40,-4,1005,1018,271,1001,64,1,64,1105,1,273,4,257,1002,64,2,64,109,-18,1207,0,21,63,1005,63,295,4,279,1001,64,1,64,1105,1,295,1002,64,2,64,109,-3,1207,0,36,63,1005,63,311,1105,1,317,4,301,1001,64,1,64,1002,64,2,64,109,6,2108,20,-3,63,1005,63,339,4,323,1001,64,1,64,1106,0,339,1002,64,2,64,109,28,2106,0,-7,4,345,1001,64,1,64,1106,0,357,1002,64,2,64,109,-18,1206,4,373,1001,64,1,64,1105,1,375,4,363,1002,64,2,64,109,-6,2107,31,-4,63,1005,63,397,4,381,1001,64,1,64,1105,1,397,1002,64,2,64,109,1,21102,42,1,-1,1008,1011,39,63,1005,63,421,1001,64,1,64,1106,0,423,4,403,1002,64,2,64,109,-2,2108,26,-2,63,1005,63,439,1106,0,445,4,429,1001,64,1,64,1002,64,2,64,109,6,21102,43,1,-5,1008,1011,43,63,1005,63,467,4,451,1105,1,471,1001,64,1,64,1002,64,2,64,109,6,21101,44,0,-3,1008,1019,44,63,1005,63,493,4,477,1105,1,497,1001,64,1,64,1002,64,2,64,109,-9,1206,7,511,4,503,1105,1,515,1001,64,1,64,1002,64,2,64,109,14,1205,-7,531,1001,64,1,64,1106,0,533,4,521,1002,64,2,64,109,-27,1201,0,0,63,1008,63,39,63,1005,63,555,4,539,1105,1,559,1001,64,1,64,1002,64,2,64,109,10,2101,0,-5,63,1008,63,24,63,1005,63,583,1001,64,1,64,1105,1,585,4,565,1002,64,2,64,109,-11,2107,21,5,63,1005,63,601,1105,1,607,4,591,1001,64,1,64,1002,64,2,64,109,10,1208,0,36,63,1005,63,627,1001,64,1,64,1106,0,629,4,613,1002,64,2,64,109,15,21108,45,45,-9,1005,1015,647,4,635,1105,1,651,1001,64,1,64,1002,64,2,64,109,-19,2101,0,-4,63,1008,63,37,63,1005,63,677,4,657,1001,64,1,64,1106,0,677,1002,64,2,64,109,22,1205,-6,695,4,683,1001,64,1,64,1105,1,695,1002,64,2,64,109,-10,2106,0,10,1001,64,1,64,1105,1,713,4,701,1002,64,2,64,109,-9,1201,-8,0,63,1008,63,36,63,1005,63,733,1105,1,739,4,719,1001,64,1,64,1002,64,2,64,109,7,21107,46,47,0,1005,1015,757,4,745,1106,0,761,1001,64,1,64,1002,64,2,64,109,14,2105,1,-5,4,767,1105,1,779,1001,64,1,64,1002,64,2,64,109,-34,2102,1,6,63,1008,63,39,63,1005,63,799,1105,1,805,4,785,1001,64,1,64,1002,64,2,64,109,25,21108,47,49,-4,1005,1016,825,1001,64,1,64,1106,0,827,4,811,1002,64,2,64,109,-6,1208,-8,36,63,1005,63,845,4,833,1106,0,849,1001,64,1,64,1002,64,2,64,109,-10,1202,2,1,63,1008,63,36,63,1005,63,875,4,855,1001,64,1,64,1105,1,875,1002,64,2,64,109,-5,1202,10,1,63,1008,63,30,63,1005,63,895,1106,0,901,4,881,1001,64,1,64,4,64,99,21101,27,0,1,21101,0,915,0,1105,1,922,21201,1,65916,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,942,0,0,1105,1,922,21201,1,0,-1,21201,-2,-3,1,21102,1,957,0,1105,1,922,22201,1,-1,-2,1106,0,968,22102,1,-2,-2,109,-3,2105,1,0

210
2019/d09/ex2/ex2.py Executable file
View file

@ -0,0 +1,210 @@
#!/usr/bin/env python
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import IntEnum
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
computer = Computer(deepcopy(memory), input_list=[2])
computer.run_no_output_interrupt()
print(computer.output_list.pop())
assert len(computer.output_list) == 0 # Sanity check
if __name__ == "__main__":
main()

1
2019/d09/ex2/input Normal file
View file

@ -0,0 +1 @@
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,1,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,26,1,1005,1101,0,24,1019,1102,1,32,1007,1101,0,704,1027,1102,0,1,1020,1101,0,348,1029,1102,28,1,1002,1101,34,0,1016,1102,29,1,1008,1102,1,30,1013,1102,25,1,1012,1101,0,33,1009,1102,1,37,1001,1101,31,0,1017,1101,245,0,1022,1102,39,1,1000,1101,27,0,1011,1102,770,1,1025,1101,0,22,1015,1102,1,1,1021,1101,711,0,1026,1101,20,0,1004,1101,0,23,1018,1101,242,0,1023,1102,21,1,1003,1101,38,0,1010,1101,0,35,1014,1101,0,36,1006,1101,0,357,1028,1102,1,775,1024,109,-3,2102,1,9,63,1008,63,36,63,1005,63,203,4,187,1105,1,207,1001,64,1,64,1002,64,2,64,109,8,21101,40,0,5,1008,1010,41,63,1005,63,227,1106,0,233,4,213,1001,64,1,64,1002,64,2,64,109,16,2105,1,2,1105,1,251,4,239,1001,64,1,64,1002,64,2,64,109,1,21107,41,40,-4,1005,1018,271,1001,64,1,64,1105,1,273,4,257,1002,64,2,64,109,-18,1207,0,21,63,1005,63,295,4,279,1001,64,1,64,1105,1,295,1002,64,2,64,109,-3,1207,0,36,63,1005,63,311,1105,1,317,4,301,1001,64,1,64,1002,64,2,64,109,6,2108,20,-3,63,1005,63,339,4,323,1001,64,1,64,1106,0,339,1002,64,2,64,109,28,2106,0,-7,4,345,1001,64,1,64,1106,0,357,1002,64,2,64,109,-18,1206,4,373,1001,64,1,64,1105,1,375,4,363,1002,64,2,64,109,-6,2107,31,-4,63,1005,63,397,4,381,1001,64,1,64,1105,1,397,1002,64,2,64,109,1,21102,42,1,-1,1008,1011,39,63,1005,63,421,1001,64,1,64,1106,0,423,4,403,1002,64,2,64,109,-2,2108,26,-2,63,1005,63,439,1106,0,445,4,429,1001,64,1,64,1002,64,2,64,109,6,21102,43,1,-5,1008,1011,43,63,1005,63,467,4,451,1105,1,471,1001,64,1,64,1002,64,2,64,109,6,21101,44,0,-3,1008,1019,44,63,1005,63,493,4,477,1105,1,497,1001,64,1,64,1002,64,2,64,109,-9,1206,7,511,4,503,1105,1,515,1001,64,1,64,1002,64,2,64,109,14,1205,-7,531,1001,64,1,64,1106,0,533,4,521,1002,64,2,64,109,-27,1201,0,0,63,1008,63,39,63,1005,63,555,4,539,1105,1,559,1001,64,1,64,1002,64,2,64,109,10,2101,0,-5,63,1008,63,24,63,1005,63,583,1001,64,1,64,1105,1,585,4,565,1002,64,2,64,109,-11,2107,21,5,63,1005,63,601,1105,1,607,4,591,1001,64,1,64,1002,64,2,64,109,10,1208,0,36,63,1005,63,627,1001,64,1,64,1106,0,629,4,613,1002,64,2,64,109,15,21108,45,45,-9,1005,1015,647,4,635,1105,1,651,1001,64,1,64,1002,64,2,64,109,-19,2101,0,-4,63,1008,63,37,63,1005,63,677,4,657,1001,64,1,64,1106,0,677,1002,64,2,64,109,22,1205,-6,695,4,683,1001,64,1,64,1105,1,695,1002,64,2,64,109,-10,2106,0,10,1001,64,1,64,1105,1,713,4,701,1002,64,2,64,109,-9,1201,-8,0,63,1008,63,36,63,1005,63,733,1105,1,739,4,719,1001,64,1,64,1002,64,2,64,109,7,21107,46,47,0,1005,1015,757,4,745,1106,0,761,1001,64,1,64,1002,64,2,64,109,14,2105,1,-5,4,767,1105,1,779,1001,64,1,64,1002,64,2,64,109,-34,2102,1,6,63,1008,63,39,63,1005,63,799,1105,1,805,4,785,1001,64,1,64,1002,64,2,64,109,25,21108,47,49,-4,1005,1016,825,1001,64,1,64,1106,0,827,4,811,1002,64,2,64,109,-6,1208,-8,36,63,1005,63,845,4,833,1106,0,849,1001,64,1,64,1002,64,2,64,109,-10,1202,2,1,63,1008,63,36,63,1005,63,875,4,855,1001,64,1,64,1105,1,875,1002,64,2,64,109,-5,1202,10,1,63,1008,63,30,63,1005,63,895,1106,0,901,4,881,1001,64,1,64,4,64,99,21101,27,0,1,21101,0,915,0,1105,1,922,21201,1,65916,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,942,0,0,1105,1,922,21201,1,0,-1,21201,-2,-3,1,21102,1,957,0,1105,1,922,22201,1,-1,-2,1106,0,968,22102,1,-2,-2,109,-3,2105,1,0

51
2019/d10/ex1/ex1.py Executable file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env python
import sys
from math import gcd
from typing import NamedTuple, Set
class Position(NamedTuple):
x: int
y: int
def main() -> None:
asteroids = [
Position(x, y)
for y, line in enumerate(sys.stdin.readlines())
for x, c in enumerate(line.rstrip())
if c == "#"
]
def count_spotted(x: int, y: int) -> int:
seen: Set[Position] = set()
ans = 0
radius = 1
while True:
def is_r_away(pos: Position) -> bool:
return max(abs(pos.x - x), abs(pos.y - y)) == radius
to_visit = list(filter(is_r_away, asteroids))
radius += 1
if len(to_visit) == 0:
break
for pos in to_visit:
rel = (pos.x - x, pos.y - y)
common = gcd(*rel)
rel = Position(*(a // common for a in rel))
if rel in seen:
continue # Already have an asteroid on this path
seen.add(rel)
ans += 1
return ans
ans, x, y = max((count_spotted(*pos), *pos) for pos in asteroids)
print(f"({x}, {y}): {ans}")
if __name__ == "__main__":
main()

31
2019/d10/ex1/input Normal file
View file

@ -0,0 +1,31 @@
#...##.####.#.......#.##..##.#.
#.##.#..#..#...##..##.##.#.....
#..#####.#......#..#....#.###.#
...#.#.#...#..#.....#..#..#.#..
.#.....##..#...#..#.#...##.....
##.....#..........##..#......##
.##..##.#.#....##..##.......#..
#.##.##....###..#...##...##....
##.#.#............##..#...##..#
###..##.###.....#.##...####....
...##..#...##...##..#.#..#...#.
..#.#.##.#.#.#####.#....####.#.
#......###.##....#...#...#...##
.....#...#.#.#.#....#...#......
#..#.#.#..#....#..#...#..#..##.
#.....#..##.....#...###..#..#.#
.....####.#..#...##..#..#..#..#
..#.....#.#........#.#.##..####
.#.....##..#.##.....#...###....
###.###....#..#..#.....#####...
#..##.##..##.#.#....#.#......#.
.#....#.##..#.#.#.......##.....
##.##...#...#....###.#....#....
.....#.######.#.#..#..#.#.....#
.#..#.##.#....#.##..#.#...##..#
.##.###..#..#..#.###...#####.#.
#...#...........#.....#.......#
#....##.#.#..##...#..####...#..
#.####......#####.....#.##..#..
.#...#....#...##..##.#.#......#
#..###.....##.#.......#.##...##

86
2019/d10/ex2/ex2.py Executable file
View file

@ -0,0 +1,86 @@
#!/usr/bin/env python
import sys
from cmath import phase
from itertools import groupby
from math import gcd, pi
from typing import NamedTuple, Set, Tuple
class Position(NamedTuple):
x: int
y: int
def pos_to_angle_dist(pos: Position) -> Tuple[float, float]:
cartesian = complex(*pos)
angle = phase(cartesian)
if angle < -pi / 2:
angle += 2.5 * pi
else:
angle += pi / 2
return (angle, abs(cartesian))
def main() -> None:
asteroids = [
Position(x, y)
for y, line in enumerate(sys.stdin.readlines())
for x, c in enumerate(line.rstrip())
if c == "#"
]
def count_spotted(x: int, y: int) -> int:
seen: Set[Position] = set()
ans = 0
radius = 1
while True:
def is_r_away(pos: Position) -> bool:
return max(abs(pos.x - x), abs(pos.y - y)) == radius
to_visit = list(filter(is_r_away, asteroids))
radius += 1
if len(to_visit) == 0:
break
for pos in to_visit:
rel = (pos.x - x, pos.y - y)
common = gcd(*rel)
rel = Position(*(a // common for a in rel))
if rel in seen:
continue # Already have an asteroid on this path
seen.add(rel)
ans += 1
return ans
# We need to find the observatory's position as a prerequisite
ans, orig = max((count_spotted(*pos), pos) for pos in asteroids)
print(f"({orig.x}, {orig.y}): {ans}")
def to_rel(p: Position) -> Position:
return Position(*(a - o for (a, o) in zip(p, orig)))
angle_dists = sorted(
(pos_to_angle_dist(to_rel(p)), p) for p in asteroids if p != orig
)
grouped_angle_dists = [
[val[1] for val in group]
for __, group in groupby(angle_dists, key=lambda x: x[0][0])
]
def find_n_th(n: int) -> Position:
assert 0 < n < len(asteroids) # Sanity check
while n >= len(grouped_angle_dists):
for group in grouped_angle_dists:
group.pop(0)
n -= 1
return grouped_angle_dists[n - 1][0]
x, y = find_n_th(200)
print(x * 100 + y)
if __name__ == "__main__":
main()

31
2019/d10/ex2/input Normal file
View file

@ -0,0 +1,31 @@
#...##.####.#.......#.##..##.#.
#.##.#..#..#...##..##.##.#.....
#..#####.#......#..#....#.###.#
...#.#.#...#..#.....#..#..#.#..
.#.....##..#...#..#.#...##.....
##.....#..........##..#......##
.##..##.#.#....##..##.......#..
#.##.##....###..#...##...##....
##.#.#............##..#...##..#
###..##.###.....#.##...####....
...##..#...##...##..#.#..#...#.
..#.#.##.#.#.#####.#....####.#.
#......###.##....#...#...#...##
.....#...#.#.#.#....#...#......
#..#.#.#..#....#..#...#..#..##.
#.....#..##.....#...###..#..#.#
.....####.#..#...##..#..#..#..#
..#.....#.#........#.#.##..####
.#.....##..#.##.....#...###....
###.###....#..#..#.....#####...
#..##.##..##.#.#....#.#......#.
.#....#.##..#.#.#.......##.....
##.##...#...#....###.#....#....
.....#.######.#.#..#..#.#.....#
.#..#.##.#....#.##..#.#...##..#
.##.###..#..#..#.###...#####.#.
#...#...........#.....#.......#
#....##.#.#..##...#..####...#..
#.####......#####.....#.##..#..
.#...#....#...##..##.#.#......#
#..###.....##.#.......#.##...##

243
2019/d11/ex1/ex1.py Executable file
View file

@ -0,0 +1,243 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Dict, List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Position(NamedTuple):
x: int
y: int
# Up, Right, Down, Left offsets
offsets = [Position(1, 0), Position(0, 1), Position(-1, 0), Position(0, -1)]
class Color(IntEnum):
BLACK = 0
WHITE = 1
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
painter = Computer(memory)
pos = Position(0, 0)
orientation = 0
painted: Dict[Position, Color] = {}
has_painted = False
while not painter.is_halted:
try:
painter.run()
except InputInterrupt:
painter.input_list.append(int(painted.get(pos, Color.BLACK)))
except OutputInterrupt:
if has_painted:
orientation += 1 if painter.output_list.pop(0) == 1 else -1
if orientation < 0:
orientation += len(offsets)
else:
orientation = orientation % len(offsets)
offset = offsets[orientation]
pos = Position(pos.x + offset.x, pos.y + offset.y)
else:
painted[pos] = Color(painter.output_list.pop(0))
has_painted = not has_painted
print(len(painted))
if __name__ == "__main__":
main()

1
2019/d11/ex1/input Normal file
View file

@ -0,0 +1 @@
3,8,1005,8,330,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,102,1,8,29,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,51,1,1103,2,10,1006,0,94,1006,0,11,1,1106,13,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,1001,8,0,87,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,109,2,1105,5,10,2,103,16,10,1,1103,12,10,2,105,2,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,146,1006,0,49,2,1,12,10,2,1006,6,10,1,1101,4,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,1001,8,0,183,1,6,9,10,1006,0,32,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,213,2,1101,9,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,239,1006,0,47,1006,0,4,2,6,0,10,1006,0,58,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,102,1,8,274,2,1005,14,10,1006,0,17,1,104,20,10,1006,0,28,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1002,8,1,309,101,1,9,9,1007,9,928,10,1005,10,15,99,109,652,104,0,104,1,21101,0,937263411860,1,21102,347,1,0,1105,1,451,21101,932440724376,0,1,21102,1,358,0,1105,1,451,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,29015167015,1,21101,0,405,0,1106,0,451,21102,1,3422723163,1,21101,0,416,0,1106,0,451,3,10,104,0,104,0,3,10,104,0,104,0,21101,0,868389376360,1,21101,0,439,0,1105,1,451,21102,825544712960,1,1,21102,1,450,0,1106,0,451,99,109,2,21201,-1,0,1,21101,0,40,2,21102,482,1,3,21102,1,472,0,1106,0,515,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,477,478,493,4,0,1001,477,1,477,108,4,477,10,1006,10,509,1101,0,0,477,109,-2,2106,0,0,0,109,4,2101,0,-1,514,1207,-3,0,10,1006,10,532,21102,1,0,-3,22101,0,-3,1,22102,1,-2,2,21102,1,1,3,21101,551,0,0,1106,0,556,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,579,2207,-4,-2,10,1006,10,579,22102,1,-4,-4,1106,0,647,21201,-4,0,1,21201,-3,-1,2,21202,-2,2,3,21102,1,598,0,1106,0,556,22101,0,1,-4,21101,1,0,-1,2207,-4,-2,10,1006,10,617,21102,0,1,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,639,21201,-1,0,1,21102,639,1,0,105,1,514,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0

253
2019/d11/ex2/ex2.py Executable file
View file

@ -0,0 +1,253 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Dict, List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Position(NamedTuple):
x: int
y: int
# Up, Right, Down, Left offsets
offsets = [Position(1, 0), Position(0, 1), Position(-1, 0), Position(0, -1)]
class Color(IntEnum):
BLACK = 0
WHITE = 1
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
painter = Computer(memory)
pos = Position(0, 0)
orientation = 0
painted: Dict[Position, Color] = {pos: Color.WHITE}
has_painted = False
while not painter.is_halted:
try:
painter.run()
except InputInterrupt:
painter.input_list.append(int(painted.get(pos, Color.BLACK)))
except OutputInterrupt:
if has_painted:
orientation += 1 if painter.output_list.pop(0) == 1 else -1
if orientation < 0:
orientation += len(offsets)
else:
orientation = orientation % len(offsets)
offset = offsets[orientation]
pos = Position(pos.x + offset.x, pos.y + offset.y)
else:
painted[pos] = Color(painter.output_list.pop(0))
has_painted = not has_painted
maxx, maxy = max(p.x for p in painted), max(p.y for p in painted)
minx, miny = min(p.x for p in painted), min(p.y for p in painted)
ans: List[List[str]] = []
for x in range(minx, maxx + 1):
ans.append([])
for y in range(miny, maxy + 1):
color = painted.get(Position(x, y), Color.BLACK)
ans[-1].append("" if color == Color.WHITE else " ")
lines = ["".join(l) for l in ans]
print("\n".join(reversed(lines))) # Seems like my coordinates are reversed
if __name__ == "__main__":
main()

1
2019/d11/ex2/input Normal file
View file

@ -0,0 +1 @@
3,8,1005,8,330,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,102,1,8,29,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,51,1,1103,2,10,1006,0,94,1006,0,11,1,1106,13,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,1001,8,0,87,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,109,2,1105,5,10,2,103,16,10,1,1103,12,10,2,105,2,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,146,1006,0,49,2,1,12,10,2,1006,6,10,1,1101,4,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,1001,8,0,183,1,6,9,10,1006,0,32,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,213,2,1101,9,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,239,1006,0,47,1006,0,4,2,6,0,10,1006,0,58,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,102,1,8,274,2,1005,14,10,1006,0,17,1,104,20,10,1006,0,28,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1002,8,1,309,101,1,9,9,1007,9,928,10,1005,10,15,99,109,652,104,0,104,1,21101,0,937263411860,1,21102,347,1,0,1105,1,451,21101,932440724376,0,1,21102,1,358,0,1105,1,451,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,29015167015,1,21101,0,405,0,1106,0,451,21102,1,3422723163,1,21101,0,416,0,1106,0,451,3,10,104,0,104,0,3,10,104,0,104,0,21101,0,868389376360,1,21101,0,439,0,1105,1,451,21102,825544712960,1,1,21102,1,450,0,1106,0,451,99,109,2,21201,-1,0,1,21101,0,40,2,21102,482,1,3,21102,1,472,0,1106,0,515,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,477,478,493,4,0,1001,477,1,477,108,4,477,10,1006,10,509,1101,0,0,477,109,-2,2106,0,0,0,109,4,2101,0,-1,514,1207,-3,0,10,1006,10,532,21102,1,0,-3,22101,0,-3,1,22102,1,-2,2,21102,1,1,3,21101,551,0,0,1106,0,556,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,579,2207,-4,-2,10,1006,10,579,22102,1,-4,-4,1106,0,647,21201,-4,0,1,21201,-3,-1,2,21202,-2,2,3,21102,1,598,0,1106,0,556,22101,0,1,-4,21101,1,0,-1,2207,-4,-2,10,1006,10,617,21102,0,1,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,639,21201,-1,0,1,21102,639,1,0,105,1,514,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0

50
2019/d12/ex1/ex1.py Executable file
View file

@ -0,0 +1,50 @@
#!/usr/bin/env python
import re
import sys
from dataclasses import dataclass
@dataclass
class Position:
x: int
y: int
z: int
def line_to_pos(l: str) -> Position:
"<x=4, y=1, z=1>"
regex = r"<x=(?P<x>[^,]*), y=(?P<y>[^,]*), z=(?P<z>[^,]*)>"
match = re.search(regex, l)
assert match is not None # Sanity check
return Position(*(int(match.group(g)) for g in ("x", "y", "z")))
def main() -> None:
asteroids = [line_to_pos(line) for line in sys.stdin.readlines()]
velocities = [Position(0, 0, 0) for __ in asteroids]
for __ in range(1000):
for orig, v in zip(asteroids, velocities):
for other in asteroids:
if orig.x != other.x:
v.x += 1 if orig.x < other.x else -1
if orig.y != other.y:
v.y += 1 if orig.y < other.y else -1
if orig.z != other.z:
v.z += 1 if orig.z < other.z else -1
for asteroid, v in zip(asteroids, velocities):
asteroid.x += v.x
asteroid.y += v.y
asteroid.z += v.z
pot = (abs(p.x) + abs(p.y) + abs(p.z) for p in asteroids)
kin = (abs(v.x) + abs(v.y) + abs(v.z) for v in velocities)
print(sum(p * k for p, k in zip(pot, kin)))
if __name__ == "__main__":
main()

4
2019/d12/ex1/input Normal file
View file

@ -0,0 +1,4 @@
<x=4, y=1, z=1>
<x=11, y=-18, z=-1>
<x=-2, y=-10, z=-4>
<x=-7, y=-2, z=14>

77
2019/d12/ex2/ex2.py Executable file
View file

@ -0,0 +1,77 @@
#!/usr/bin/env python
import re
import sys
from copy import deepcopy
from dataclasses import dataclass
from math import gcd
from typing import List
@dataclass
class Position:
x: int
y: int
z: int
def line_to_pos(l: str) -> Position:
"<x=4, y=1, z=1>"
regex = r"<x=(?P<x>[^,]*), y=(?P<y>[^,]*), z=(?P<z>[^,]*)>"
match = re.search(regex, l)
assert match is not None # Sanity check
return Position(*(int(match.group(g)) for g in ("x", "y", "z")))
def lcm(a: int, b: int, c: int) -> int:
def lcm_2(a: int, b: int) -> int:
return abs(a * b) // gcd(a, b)
return lcm_2(lcm_2(a, b), c)
def main() -> None:
asteroids = [line_to_pos(line) for line in sys.stdin.readlines()]
velocities = [Position(0, 0, 0) for __ in asteroids]
cycles: List[int] = []
for attr in ("x", "y", "z"):
all_prev_pos = [deepcopy(asteroids)]
all_prev_vel = [deepcopy(velocities)]
i = 0
found = False
while not found:
i += 1
for orig, v in zip(asteroids, velocities):
for other in asteroids:
if orig.x != other.x:
v.x += 1 if orig.x < other.x else -1
if orig.y != other.y:
v.y += 1 if orig.y < other.y else -1
if orig.z != other.z:
v.z += 1 if orig.z < other.z else -1
for asteroid, v in zip(asteroids, velocities):
asteroid.x += v.x
asteroid.y += v.y
asteroid.z += v.z
for old_pos, old_vel in zip(all_prev_pos, all_prev_vel):
if all(
n.__getattribute__(attr) == o.__getattribute__(attr)
for n, o in zip(asteroids, old_pos)
) and all(
n.__getattribute__(attr) == o.__getattribute__(attr)
for n, o in zip(velocities, old_vel)
):
found = True
cycles.append(i)
print(lcm(*cycles))
if __name__ == "__main__":
main()

4
2019/d12/ex2/input Normal file
View file

@ -0,0 +1,4 @@
<x=4, y=1, z=1>
<x=11, y=-18, z=-1>
<x=-2, y=-10, z=-4>
<x=-7, y=-2, z=14>

213
2019/d13/ex1/ex1.py Executable file
View file

@ -0,0 +1,213 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Iterable, List, NamedTuple, Tuple, TypeVar
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
game = Computer(memory)
game.run_no_output_interrupt()
T = TypeVar("T")
def grouped(l: Iterable[T], n: int) -> Iterable[Tuple[T, ...]]:
return zip(*[iter(l)] * n)
print(sum(1 for __, __, tile in grouped(game.output_list, 3) if tile == 2))
if __name__ == "__main__":
main()

1
2019/d13/ex1/input Normal file

File diff suppressed because one or more lines are too long

249
2019/d13/ex2/ex2.py Executable file
View file

@ -0,0 +1,249 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Iterable, List, NamedTuple, Tuple, TypeVar
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Tile(IntEnum):
EMPTY = 0
WALL = 1
BLOCK = 2
PADDLE = 3
BALL = 4
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
memory[0] = 2 # Play for free
game = Computer(memory)
T = TypeVar("T")
def grouped(l: Iterable[T], n: int) -> Iterable[Tuple[T, ...]]:
return zip(*[iter(l)] * n)
paddle_pos = None
ball_pos = None
score = None
output_num = 0
while not game.is_halted:
try:
game.run()
except OutputInterrupt:
output_num += 1
if output_num < 3: # Not processable yet
continue
x, y = game.output_list[0:2]
if x == -1 and y == 0: # Score display
score = game.output_list[2]
else:
tile_type = Tile(game.output_list[2])
if tile_type == Tile.PADDLE:
paddle_pos = x
elif tile_type == Tile.BALL:
ball_pos = x
game.output_list.clear() # Remove processed tiles
output_num = 0 # Reset count for next output
except InputInterrupt:
assert paddle_pos is not None and ball_pos is not None # Sanity check
offset = ball_pos - paddle_pos
game.input_list.append(0 if offset == 0 else offset // abs(offset))
assert score is not None # Sanity check
print(score)
if __name__ == "__main__":
main()

1
2019/d13/ex2/input Normal file

File diff suppressed because one or more lines are too long

89
2019/d14/ex1/ex1.py Executable file
View file

@ -0,0 +1,89 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass
from math import ceil
from typing import Dict, List
@dataclass
class Ingredient:
name: str
quantity: int
@dataclass
class ReactionEquation:
quantity: int
inputs: List[Ingredient]
Reactions = Dict[str, ReactionEquation]
def solve_for(n: int, reactions: Reactions) -> int:
ore_needed = 0
wanted = [("FUEL", n)]
excess: Dict[str, int] = {}
def provide_ingredient(name: str, wanted_quantity: int) -> None:
nonlocal ore_needed
nonlocal excess
nonlocal wanted
if name == "ORE":
ore_needed += wanted_quantity # There's no recipy for this one
return
if name in excess:
# Take from excess
if excess[name] > wanted_quantity:
excess[name] -= wanted_quantity
return # Nothing left to do
wanted_quantity -= excess[name]
del excess[name] # Took everything
if wanted_quantity == 0: # In case we provided just enough by excess
return
equation = reactions[name]
reaction_num = ceil(wanted_quantity / equation.quantity)
for ingredient in equation.inputs:
needed_quantity = ingredient.quantity * reaction_num
provide_ingredient(ingredient.name, needed_quantity)
produced_quantity = equation.quantity * reaction_num
excess_quantity = produced_quantity - wanted_quantity
if excess_quantity > 0:
if name in excess:
excess[name] += excess_quantity
else:
excess[name] = excess_quantity
while len(wanted) != 0:
provide_ingredient(*(wanted.pop()))
return ore_needed
def main() -> None:
reactions: Reactions = {}
def parse_react(l: str) -> None:
def parse_ingredient(i: str) -> Ingredient:
quantity, name = i.strip().split(" ")
return Ingredient(name, int(quantity))
input_list, output_str = l.split("=>")
inputs = [i for i in map(parse_ingredient, input_list.split(", "))]
output = parse_ingredient(output_str)
reactions[output.name] = ReactionEquation(output.quantity, inputs)
for line in sys.stdin.readlines():
parse_react(line)
print(solve_for(1, reactions))
if __name__ == "__main__":
main()

59
2019/d14/ex1/input Normal file
View file

@ -0,0 +1,59 @@
10 LSZLT, 29 XQJK => 4 BMRQJ
22 HCKS => 1 GQKCZ
1 HCKS, 8 WZWRV, 18 HVZR => 7 BGFR
1 LSZLT, 1 WRKJ, 3 LJFP, 3 RNLPB, 1 NZGK, 3 LDSV, 5 RJDN, 8 HGFGC => 3 QZTXD
1 BRSGQ, 1 XGLF, 1 ZHSK, 20 LSZLT, 16 WFCPT, 3 KTWV, 1 QRJC => 4 XPKX
1 DCLR, 6 RNLPB => 5 HCKS
1 HFHFV => 3 SHLMF
2 LTMZQ, 21 FGCXN => 6 QKFKV
3 BGFR => 7 WRKJ
3 KHSB => 2 XQJL
3 SHLMF => 2 LPLG
12 SVHWT, 20 BXPSZ => 9 NBMF
2 FGCXN, 32 DCSVN => 8 TBDWZ
1 KHSB, 3 HGFGC => 6 WZWRV
27 WFCPT, 4 KTWV, 14 BRSGQ, 1 MFNK, 1 WRKJ, 2 NZGK, 24 FBFLK => 5 TRLCK
2 SVHWT => 3 QRJC
1 MNVR, 1 FKBMW => 2 FGCXN
4 GJXW => 9 JXFS
3 XQJK => 5 WNJM
1 WZVWZ, 1 XQJL => 9 SHKJV
2 DCSVN => 4 HDVC
2 GJXW => 2 RNLPB
1 QKFKV, 1 PBRWB => 5 WTZQ
14 QKFKV => 6 RDFTD
166 ORE => 1 QDSXV
2 DCSVN => 5 BXPSZ
113 ORE => 6 LTMZQ
13 MNVR => 7 RJDN
2 NZGK, 9 XQJK, 18 WRKJ => 9 KTWV
1 NZGK => 8 XQJK
6 RZCGN, 6 HDVC, 1 DLKR => 9 DSLXW
18 HVZR => 8 LJFP
7 XQJL => 1 NPDS
15 DLKR, 1 DSLXW, 26 MJFVP => 3 FBFLK
125 ORE => 9 MNVR
3 RJDN => 4 HFHFV
1 TBDWZ, 1 DCLR => 2 HVZR
2 SHKJV => 5 GJXW
7 LTMZQ, 1 QDSXV, 1 FKBMW => 3 DCSVN
9 LPLG, 11 JXFS => 3 BRSGQ
5 JXFS, 1 ZHSK, 25 XGLF => 4 MFNK
5 PBRWB => 2 SVHWT
15 SHKJV => 5 XGLF
1 XQJL, 2 NPDS => 4 DLKR
39 JXFS => 5 KSHF
6 GJXW, 1 FBFLK => 7 HGFGC
3 JXFS => 1 LSZLT
3 NBMF, 1 BMRQJ => 2 LDSV
1 JXFS, 25 GJXW, 10 HGFGC => 4 NZGK
8 QZTXD, 26 KSHF, 60 WNJM, 6 GJXW, 9 TRLCK, 20 XPKX, 21 FGCXN, 57 GQKCZ, 6 WRKJ => 1 FUEL
4 SVHWT, 1 RZCGN => 3 ZHSK
1 BXPSZ => 7 DCLR
8 RDFTD, 1 SHKJV, 1 HFHFV => 6 MJFVP
1 LTMZQ => 9 KHSB
5 WTZQ, 4 HGFGC, 4 HCKS => 9 WFCPT
184 ORE => 4 FKBMW
4 XQJL => 3 WZVWZ
12 QDSXV => 9 RZCGN
1 FBFLK, 7 HVZR => 9 PBRWB

106
2019/d14/ex2/ex2.py Executable file
View file

@ -0,0 +1,106 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass
from math import ceil
from typing import Dict, List
@dataclass
class Ingredient:
name: str
quantity: int
@dataclass
class ReactionEquation:
quantity: int
inputs: List[Ingredient]
Reactions = Dict[str, ReactionEquation]
def solve_for(n: int, reactions: Reactions) -> int:
ore_needed = 0
wanted = [("FUEL", n)]
excess: Dict[str, int] = {}
def provide_ingredient(name: str, wanted_quantity: int) -> None:
nonlocal ore_needed
nonlocal excess
nonlocal wanted
if name == "ORE":
ore_needed += wanted_quantity # There's no recipy for this one
return
if name in excess:
# Take from excess
if excess[name] > wanted_quantity:
excess[name] -= wanted_quantity
return # Nothing left to do
wanted_quantity -= excess[name]
del excess[name] # Took everything
if wanted_quantity == 0: # In case we provided just enough by excess
return
equation = reactions[name]
reaction_num = ceil(wanted_quantity / equation.quantity)
for ingredient in equation.inputs:
needed_quantity = ingredient.quantity * reaction_num
provide_ingredient(ingredient.name, needed_quantity)
produced_quantity = equation.quantity * reaction_num
excess_quantity = produced_quantity - wanted_quantity
if excess_quantity > 0:
if name in excess:
excess[name] += excess_quantity
else:
excess[name] = excess_quantity
while len(wanted) != 0:
provide_ingredient(*(wanted.pop()))
return ore_needed
def main() -> None:
reactions: Reactions = {}
def parse_react(l: str) -> None:
def parse_ingredient(i: str) -> Ingredient:
quantity, name = i.strip().split(" ")
return Ingredient(name, int(quantity))
input_list, output_str = l.split("=>")
inputs = [i for i in map(parse_ingredient, input_list.split(", "))]
output = parse_ingredient(output_str)
reactions[output.name] = ReactionEquation(output.quantity, inputs)
for line in sys.stdin.readlines():
parse_react(line)
for_one = solve_for(1, reactions)
target = 1000000000000
# Educated guesses about minimum and maximum fuel needed to use 'target' ORE
min_fuel_needed = target // for_one
max_fuel_needed = 2 * min_fuel_needed
while min_fuel_needed < max_fuel_needed:
# We already know that minimum value is valid, offset it by one for the search
mid = ceil((min_fuel_needed + max_fuel_needed) / 2)
mid_res = solve_for(mid, reactions)
if mid_res > target:
# Exclude the maximum that was already searched
max_fuel_needed = mid - 1
else:
# Keep the valid minimum value
min_fuel_needed = mid
print(max_fuel_needed)
if __name__ == "__main__":
main()

59
2019/d14/ex2/input Normal file
View file

@ -0,0 +1,59 @@
10 LSZLT, 29 XQJK => 4 BMRQJ
22 HCKS => 1 GQKCZ
1 HCKS, 8 WZWRV, 18 HVZR => 7 BGFR
1 LSZLT, 1 WRKJ, 3 LJFP, 3 RNLPB, 1 NZGK, 3 LDSV, 5 RJDN, 8 HGFGC => 3 QZTXD
1 BRSGQ, 1 XGLF, 1 ZHSK, 20 LSZLT, 16 WFCPT, 3 KTWV, 1 QRJC => 4 XPKX
1 DCLR, 6 RNLPB => 5 HCKS
1 HFHFV => 3 SHLMF
2 LTMZQ, 21 FGCXN => 6 QKFKV
3 BGFR => 7 WRKJ
3 KHSB => 2 XQJL
3 SHLMF => 2 LPLG
12 SVHWT, 20 BXPSZ => 9 NBMF
2 FGCXN, 32 DCSVN => 8 TBDWZ
1 KHSB, 3 HGFGC => 6 WZWRV
27 WFCPT, 4 KTWV, 14 BRSGQ, 1 MFNK, 1 WRKJ, 2 NZGK, 24 FBFLK => 5 TRLCK
2 SVHWT => 3 QRJC
1 MNVR, 1 FKBMW => 2 FGCXN
4 GJXW => 9 JXFS
3 XQJK => 5 WNJM
1 WZVWZ, 1 XQJL => 9 SHKJV
2 DCSVN => 4 HDVC
2 GJXW => 2 RNLPB
1 QKFKV, 1 PBRWB => 5 WTZQ
14 QKFKV => 6 RDFTD
166 ORE => 1 QDSXV
2 DCSVN => 5 BXPSZ
113 ORE => 6 LTMZQ
13 MNVR => 7 RJDN
2 NZGK, 9 XQJK, 18 WRKJ => 9 KTWV
1 NZGK => 8 XQJK
6 RZCGN, 6 HDVC, 1 DLKR => 9 DSLXW
18 HVZR => 8 LJFP
7 XQJL => 1 NPDS
15 DLKR, 1 DSLXW, 26 MJFVP => 3 FBFLK
125 ORE => 9 MNVR
3 RJDN => 4 HFHFV
1 TBDWZ, 1 DCLR => 2 HVZR
2 SHKJV => 5 GJXW
7 LTMZQ, 1 QDSXV, 1 FKBMW => 3 DCSVN
9 LPLG, 11 JXFS => 3 BRSGQ
5 JXFS, 1 ZHSK, 25 XGLF => 4 MFNK
5 PBRWB => 2 SVHWT
15 SHKJV => 5 XGLF
1 XQJL, 2 NPDS => 4 DLKR
39 JXFS => 5 KSHF
6 GJXW, 1 FBFLK => 7 HGFGC
3 JXFS => 1 LSZLT
3 NBMF, 1 BMRQJ => 2 LDSV
1 JXFS, 25 GJXW, 10 HGFGC => 4 NZGK
8 QZTXD, 26 KSHF, 60 WNJM, 6 GJXW, 9 TRLCK, 20 XPKX, 21 FGCXN, 57 GQKCZ, 6 WRKJ => 1 FUEL
4 SVHWT, 1 RZCGN => 3 ZHSK
1 BXPSZ => 7 DCLR
8 RDFTD, 1 SHKJV, 1 HFHFV => 6 MJFVP
1 LTMZQ => 9 KHSB
5 WTZQ, 4 HGFGC, 4 HCKS => 9 WFCPT
184 ORE => 4 FKBMW
4 XQJL => 3 WZVWZ
12 QDSXV => 9 RZCGN
1 FBFLK, 7 HVZR => 9 PBRWB

315
2019/d15/ex1/ex1.py Executable file
View file

@ -0,0 +1,315 @@
#!/usr/bin/env python
import heapq
import sys
from dataclasses import dataclass, field
from enum import Enum, IntEnum, auto
from typing import List, NamedTuple, Optional, Set
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Movement(IntEnum):
NORTH = 1
SOUTH = 2
WEST = 3
EAST = 4
class StatusCode(IntEnum):
BLOCKED = 0
SUCCESS = 1
ON_TANK = 2
class BlockType(Enum):
WALL = auto()
HALLWAY = auto()
OXYGEN_TANK = auto()
class Coordinate(NamedTuple):
x: int
y: int
@dataclass
class GraphNode:
memory_state: Optional[List[int]] # Only walls have no need for the memory state
block_type: BlockType
parent: Optional[Coordinate] # Only the root of the exploration has no parent
def coord_plus_dir(c: Coordinate, d: Movement) -> Coordinate:
offset = {
Movement.NORTH: Coordinate(0, 1),
Movement.SOUTH: Coordinate(0, -1),
Movement.WEST: Coordinate(-1, 0),
Movement.EAST: Coordinate(1, 0),
}
return Coordinate(*(a + b for (a, b) in zip(c, offset[d])))
def move_to_opposite(d: Movement) -> Movement:
if d == Movement.NORTH:
return Movement.SOUTH
elif d == Movement.SOUTH:
return Movement.NORTH
elif d == Movement.WEST:
return Movement.EAST
else:
return Movement.WEST
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
droid = Computer(memory)
block_map = {Coordinate(0, 0): BlockType.HALLWAY}
def dfs(p: Coordinate, direction: Movement) -> None:
end_coord = coord_plus_dir(p, direction)
if end_coord in block_map:
return # Nothing to do
droid.input_list.append(int(direction))
try:
droid.run()
except OutputInterrupt:
status = StatusCode(droid.output_list.pop(0))
if status == StatusCode.BLOCKED:
block_map[end_coord] = BlockType.WALL
return # Don't need to backtrack
block_map[end_coord] = (
BlockType.OXYGEN_TANK
if status == StatusCode.ON_TANK
else BlockType.HALLWAY
)
for d in Movement:
dfs(end_coord, d)
droid.input_list.append(int(move_to_opposite(direction)))
try:
droid.run()
except OutputInterrupt:
droid.output_list.pop(0)
for direction in Movement:
dfs(Coordinate(0, 0), direction)
assert len(droid.input_list) == 0 and len(droid.output_list) == 0 # Sanity check
block_map = {p: t for p, t in block_map.items() if t != BlockType.WALL}
oxygen_gen = (
pos for pos, block in block_map.items() if block == BlockType.OXYGEN_TANK
)
oxygen_pos = next(oxygen_gen)
assert next(oxygen_gen, None) is None # Sanity check
seen: Set[Coordinate] = set()
to_visit = [(0, oxygen_pos)]
def find_shortest() -> int:
while True:
dist, pos = heapq.heappop(to_visit)
if pos == Coordinate(0, 0):
return dist
if pos in seen:
continue
if pos not in block_map:
continue
seen.add(pos)
for d in Movement:
new_pos = coord_plus_dir(pos, d)
heapq.heappush(to_visit, (dist + 1, new_pos))
print(find_shortest())
if __name__ == "__main__":
main()

1
2019/d15/ex1/input Normal file
View file

@ -0,0 +1 @@
3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,101,0,1034,1039,1001,1036,0,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1105,1,124,1002,1034,1,1039,1001,1036,0,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1106,0,124,1001,1034,-1,1039,1008,1036,0,1041,101,0,1035,1040,1001,1038,0,1043,1002,1037,1,1042,1105,1,124,1001,1034,1,1039,1008,1036,0,1041,1002,1035,1,1040,101,0,1038,1043,1001,1037,0,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,33,1032,1006,1032,165,1008,1040,33,1032,1006,1032,165,1101,2,0,1044,1106,0,224,2,1041,1043,1032,1006,1032,179,1101,0,1,1044,1106,0,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,68,1044,1106,0,224,1101,0,0,1044,1105,1,224,1006,1044,247,1002,1039,1,1034,102,1,1040,1035,1001,1041,0,1036,1002,1043,1,1038,1001,1042,0,1037,4,1044,1105,1,0,67,55,37,80,63,12,30,78,95,7,20,63,83,54,86,58,97,11,84,24,11,77,42,78,22,54,89,52,44,28,93,30,81,60,58,78,87,60,54,59,78,96,17,82,74,85,66,41,89,96,54,40,82,17,22,89,65,96,71,55,81,34,90,11,85,44,58,83,79,93,30,76,62,80,16,73,20,43,40,73,69,39,39,15,93,39,99,8,74,33,97,84,24,50,91,5,71,34,81,76,22,98,50,93,80,36,76,16,76,43,19,71,63,41,21,99,40,75,55,27,82,80,83,54,66,75,61,86,14,10,74,38,92,31,49,97,20,98,15,71,59,96,53,86,35,60,6,73,71,59,79,10,84,69,23,82,14,7,76,99,45,19,96,92,14,63,55,71,46,71,34,74,73,22,95,89,10,24,59,69,17,42,96,12,92,94,66,1,69,91,36,90,94,13,17,33,46,20,89,90,24,12,94,92,83,42,73,43,70,83,55,17,92,66,23,74,99,1,92,82,54,71,96,1,22,78,74,94,66,78,40,87,13,87,73,74,89,26,26,70,42,79,3,9,84,72,55,98,56,27,73,74,57,85,66,76,88,55,58,30,97,40,71,76,6,10,55,71,43,36,99,46,59,34,37,84,61,85,90,62,98,18,39,46,84,23,70,93,9,71,5,71,94,5,59,40,71,26,90,12,45,57,74,5,92,86,32,99,20,92,82,22,44,88,29,41,89,7,86,81,72,76,9,94,94,3,8,94,71,12,93,6,82,91,91,20,86,86,38,85,95,42,86,85,19,57,90,17,85,6,84,17,81,42,77,63,26,59,9,24,85,22,31,35,93,64,90,4,16,91,67,83,23,43,63,75,3,88,93,52,14,84,85,36,95,12,51,79,54,1,16,72,1,76,79,88,63,95,77,6,91,86,23,92,54,91,51,82,45,14,98,89,74,47,52,82,80,65,74,44,58,90,14,98,42,91,6,50,88,29,81,96,25,1,97,62,62,73,61,48,82,76,93,98,49,14,74,6,97,30,47,73,77,8,89,10,17,65,21,74,95,43,83,89,72,96,27,59,20,58,80,10,70,86,42,92,26,50,98,85,3,62,20,93,86,78,19,78,91,23,90,37,71,66,97,97,95,86,40,46,79,70,37,14,98,51,91,81,4,9,77,93,19,53,70,87,40,11,95,25,93,90,17,98,39,76,92,55,57,93,39,76,13,99,58,92,26,88,80,65,34,71,62,72,17,64,38,97,85,32,4,88,69,82,51,63,61,71,77,33,90,59,74,49,76,8,76,93,55,36,71,84,7,67,47,3,85,98,9,99,32,8,79,18,28,55,77,10,30,79,77,4,1,99,82,66,90,41,64,22,82,33,20,87,24,29,80,53,72,27,17,85,84,70,16,94,11,81,92,48,85,61,47,83,21,45,92,92,38,61,75,98,52,73,80,29,82,94,29,85,61,69,59,35,84,86,60,98,63,83,69,39,10,15,64,18,85,88,63,97,95,56,13,43,75,93,13,34,85,57,37,96,39,65,60,73,73,82,11,81,80,38,88,76,23,88,19,70,2,93,46,28,79,92,91,18,6,92,96,50,77,56,45,77,36,64,83,91,64,75,48,72,71,17,69,40,82,7,6,92,70,25,23,72,9,23,84,16,17,75,76,70,60,61,99,86,21,27,85,63,80,81,55,87,93,97,53,78,53,97,14,97,49,85,65,91,72,72,5,93,34,81,10,85,86,81,19,87,61,84,11,99,96,94,8,78,13,84,9,70,0,0,21,21,1,10,1,0,0,0,0,0,0

318
2019/d15/ex2/ex2.py Executable file
View file

@ -0,0 +1,318 @@
#!/usr/bin/env python
import heapq
import sys
from dataclasses import dataclass, field
from enum import Enum, IntEnum, auto
from typing import List, NamedTuple, Optional, Set
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Movement(IntEnum):
NORTH = 1
SOUTH = 2
WEST = 3
EAST = 4
class StatusCode(IntEnum):
BLOCKED = 0
SUCCESS = 1
ON_TANK = 2
class BlockType(Enum):
WALL = auto()
HALLWAY = auto()
OXYGEN_TANK = auto()
class Coordinate(NamedTuple):
x: int
y: int
@dataclass
class GraphNode:
memory_state: Optional[List[int]] # Only walls have no need for the memory state
block_type: BlockType
parent: Optional[Coordinate] # Only the root of the exploration has no parent
def coord_plus_dir(c: Coordinate, d: Movement) -> Coordinate:
offset = {
Movement.NORTH: Coordinate(0, 1),
Movement.SOUTH: Coordinate(0, -1),
Movement.WEST: Coordinate(-1, 0),
Movement.EAST: Coordinate(1, 0),
}
return Coordinate(*(a + b for (a, b) in zip(c, offset[d])))
def move_to_opposite(d: Movement) -> Movement:
if d == Movement.NORTH:
return Movement.SOUTH
elif d == Movement.SOUTH:
return Movement.NORTH
elif d == Movement.WEST:
return Movement.EAST
else:
return Movement.WEST
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
droid = Computer(memory)
block_map = {Coordinate(0, 0): BlockType.HALLWAY}
def dfs(p: Coordinate, direction: Movement) -> None:
end_coord = coord_plus_dir(p, direction)
if end_coord in block_map:
return # Nothing to do
droid.input_list.append(int(direction))
try:
droid.run()
except OutputInterrupt:
status = StatusCode(droid.output_list.pop(0))
if status == StatusCode.BLOCKED:
block_map[end_coord] = BlockType.WALL
return # Don't need to backtrack
block_map[end_coord] = (
BlockType.OXYGEN_TANK
if status == StatusCode.ON_TANK
else BlockType.HALLWAY
)
for d in Movement:
dfs(end_coord, d)
droid.input_list.append(int(move_to_opposite(direction)))
try:
droid.run()
except OutputInterrupt:
droid.output_list.pop(0)
for direction in Movement:
dfs(Coordinate(0, 0), direction)
assert len(droid.input_list) == 0 and len(droid.output_list) == 0 # Sanity check
block_map = {p: t for p, t in block_map.items() if t != BlockType.WALL}
oxygen_gen = (
pos for pos, block in block_map.items() if block == BlockType.OXYGEN_TANK
)
oxygen_pos = next(oxygen_gen)
assert next(oxygen_gen, None) is None # Sanity check
seen: Set[Coordinate] = set()
to_visit = [(0, oxygen_pos)]
max_dist = 0
def fill_oxygen() -> None:
nonlocal max_dist
while len(to_visit) != 0:
dist, pos = heapq.heappop(to_visit)
if pos in seen:
continue
if pos not in block_map:
continue
seen.add(pos)
max_dist = max(max_dist, dist)
for d in Movement:
new_pos = coord_plus_dir(pos, d)
heapq.heappush(to_visit, (dist + 1, new_pos))
fill_oxygen()
print(max_dist)
if __name__ == "__main__":
main()

1
2019/d15/ex2/input Normal file
View file

@ -0,0 +1 @@
3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,101,0,1034,1039,1001,1036,0,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1105,1,124,1002,1034,1,1039,1001,1036,0,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1106,0,124,1001,1034,-1,1039,1008,1036,0,1041,101,0,1035,1040,1001,1038,0,1043,1002,1037,1,1042,1105,1,124,1001,1034,1,1039,1008,1036,0,1041,1002,1035,1,1040,101,0,1038,1043,1001,1037,0,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,33,1032,1006,1032,165,1008,1040,33,1032,1006,1032,165,1101,2,0,1044,1106,0,224,2,1041,1043,1032,1006,1032,179,1101,0,1,1044,1106,0,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,68,1044,1106,0,224,1101,0,0,1044,1105,1,224,1006,1044,247,1002,1039,1,1034,102,1,1040,1035,1001,1041,0,1036,1002,1043,1,1038,1001,1042,0,1037,4,1044,1105,1,0,67,55,37,80,63,12,30,78,95,7,20,63,83,54,86,58,97,11,84,24,11,77,42,78,22,54,89,52,44,28,93,30,81,60,58,78,87,60,54,59,78,96,17,82,74,85,66,41,89,96,54,40,82,17,22,89,65,96,71,55,81,34,90,11,85,44,58,83,79,93,30,76,62,80,16,73,20,43,40,73,69,39,39,15,93,39,99,8,74,33,97,84,24,50,91,5,71,34,81,76,22,98,50,93,80,36,76,16,76,43,19,71,63,41,21,99,40,75,55,27,82,80,83,54,66,75,61,86,14,10,74,38,92,31,49,97,20,98,15,71,59,96,53,86,35,60,6,73,71,59,79,10,84,69,23,82,14,7,76,99,45,19,96,92,14,63,55,71,46,71,34,74,73,22,95,89,10,24,59,69,17,42,96,12,92,94,66,1,69,91,36,90,94,13,17,33,46,20,89,90,24,12,94,92,83,42,73,43,70,83,55,17,92,66,23,74,99,1,92,82,54,71,96,1,22,78,74,94,66,78,40,87,13,87,73,74,89,26,26,70,42,79,3,9,84,72,55,98,56,27,73,74,57,85,66,76,88,55,58,30,97,40,71,76,6,10,55,71,43,36,99,46,59,34,37,84,61,85,90,62,98,18,39,46,84,23,70,93,9,71,5,71,94,5,59,40,71,26,90,12,45,57,74,5,92,86,32,99,20,92,82,22,44,88,29,41,89,7,86,81,72,76,9,94,94,3,8,94,71,12,93,6,82,91,91,20,86,86,38,85,95,42,86,85,19,57,90,17,85,6,84,17,81,42,77,63,26,59,9,24,85,22,31,35,93,64,90,4,16,91,67,83,23,43,63,75,3,88,93,52,14,84,85,36,95,12,51,79,54,1,16,72,1,76,79,88,63,95,77,6,91,86,23,92,54,91,51,82,45,14,98,89,74,47,52,82,80,65,74,44,58,90,14,98,42,91,6,50,88,29,81,96,25,1,97,62,62,73,61,48,82,76,93,98,49,14,74,6,97,30,47,73,77,8,89,10,17,65,21,74,95,43,83,89,72,96,27,59,20,58,80,10,70,86,42,92,26,50,98,85,3,62,20,93,86,78,19,78,91,23,90,37,71,66,97,97,95,86,40,46,79,70,37,14,98,51,91,81,4,9,77,93,19,53,70,87,40,11,95,25,93,90,17,98,39,76,92,55,57,93,39,76,13,99,58,92,26,88,80,65,34,71,62,72,17,64,38,97,85,32,4,88,69,82,51,63,61,71,77,33,90,59,74,49,76,8,76,93,55,36,71,84,7,67,47,3,85,98,9,99,32,8,79,18,28,55,77,10,30,79,77,4,1,99,82,66,90,41,64,22,82,33,20,87,24,29,80,53,72,27,17,85,84,70,16,94,11,81,92,48,85,61,47,83,21,45,92,92,38,61,75,98,52,73,80,29,82,94,29,85,61,69,59,35,84,86,60,98,63,83,69,39,10,15,64,18,85,88,63,97,95,56,13,43,75,93,13,34,85,57,37,96,39,65,60,73,73,82,11,81,80,38,88,76,23,88,19,70,2,93,46,28,79,92,91,18,6,92,96,50,77,56,45,77,36,64,83,91,64,75,48,72,71,17,69,40,82,7,6,92,70,25,23,72,9,23,84,16,17,75,76,70,60,61,99,86,21,27,85,63,80,81,55,87,93,97,53,78,53,97,14,97,49,85,65,91,72,72,5,93,34,81,10,85,86,81,19,87,61,84,11,99,96,94,8,78,13,84,9,70,0,0,21,21,1,10,1,0,0,0,0,0,0

29
2019/d16/ex1/ex1.py Executable file
View file

@ -0,0 +1,29 @@
#!/usr/bin/env python
import sys
from functools import reduce
from itertools import chain, cycle
from typing import Iterable, List
def sequencer(pattern: List[int], n: int) -> Iterable[int]:
gen = cycle(list(chain(*([a] * n for a in pattern))))
next(gen) # Skip the first one
yield from gen
def main() -> None:
signal = [int(d) for d in sys.stdin.read().strip()]
base_pattern = [0, 1, 0, -1]
for __ in range(100):
signal = [
abs(sum(a * b for a, b in zip(signal, sequencer(base_pattern, i + 1)))) % 10
for i in range(len(signal))
]
print(reduce(lambda a, b: a * 10 + b, signal[0:8]))
if __name__ == "__main__":
main()

1
2019/d16/ex1/input Normal file
View file

@ -0,0 +1 @@
59793513516782374825915243993822865203688298721919339628274587775705006728427921751430533510981343323758576985437451867752936052153192753660463974146842169169504066730474876587016668826124639010922391218906707376662919204980583671961374243713362170277231101686574078221791965458164785925384486127508173239563372833776841606271237694768938831709136453354321708319835083666223956618272981294631469954624760620412170069396383335680428214399523030064601263676270903213996956414287336234682903859823675958155009987384202594409175930384736760416642456784909043049471828143167853096088824339425988907292558707480725410676823614387254696304038713756368483311

27
2019/d16/ex2/ex2.py Executable file
View file

@ -0,0 +1,27 @@
#!/usr/bin/env python
import sys
from functools import reduce
def main() -> None:
rep = 10000
signal = [int(d) for d in sys.stdin.read().strip()] * rep
offset = reduce(lambda a, b: a * 10 + b, signal[0:7])
assert offset >= len(signal) / 2 # Sanity check
# The trick is that the second half is only affected by itself (triangular matrix):
# For i > len(signal) / 2, new_signal[i] = sum(signal, i, len(signal))
# Therefore, we're only interested in numbers that start at the offset
signal = signal[offset:] # Only take the end we need
for __ in range(100):
for i in range(len(signal) - 1, 0, -1): # Do the sum from the end
signal[i - 1] += signal[i]
signal[i - 1] = signal[i - 1] % 10
print(reduce(lambda a, b: a * 10 + b, signal[:8]))
if __name__ == "__main__":
main()

1
2019/d16/ex2/input Normal file
View file

@ -0,0 +1 @@
59793513516782374825915243993822865203688298721919339628274587775705006728427921751430533510981343323758576985437451867752936052153192753660463974146842169169504066730474876587016668826124639010922391218906707376662919204980583671961374243713362170277231101686574078221791965458164785925384486127508173239563372833776841606271237694768938831709136453354321708319835083666223956618272981294631469954624760620412170069396383335680428214399523030064601263676270903213996956414287336234682903859823675958155009987384202594409175930384736760416642456784909043049471828143167853096088824339425988907292558707480725410676823614387254696304038713756368483311

223
2019/d17/ex1/ex1.py Executable file
View file

@ -0,0 +1,223 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from enum import IntEnum
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
camera = Computer(memory)
camera.run_no_output_interrupt()
view = "".join(chr(c) for c in camera.output_list)
mapped_view = [[c for c in line] for line in view.split("\n") if line != ""]
def is_intersection(x: int, y: int) -> bool:
neighbors_and_point = ((x, y), (x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1))
return all(mapped_view[a][b] not in (".", "X") for a, b in neighbors_and_point)
tot = 0
for x in range(1, len(mapped_view) - 1):
for y in range(1, len(mapped_view[0]) - 1): # No need to look at the borders
if is_intersection(x, y):
tot += x * y
print(tot)
if __name__ == "__main__":
main()

1
2019/d17/ex1/input Normal file
View file

@ -0,0 +1 @@
1,330,331,332,109,2952,1101,1182,0,16,1101,1467,0,24,102,1,0,570,1006,570,36,1002,571,1,0,1001,570,-1,570,1001,24,1,24,1106,0,18,1008,571,0,571,1001,16,1,16,1008,16,1467,570,1006,570,14,21101,0,58,0,1105,1,786,1006,332,62,99,21102,1,333,1,21101,73,0,0,1106,0,579,1101,0,0,572,1101,0,0,573,3,574,101,1,573,573,1007,574,65,570,1005,570,151,107,67,574,570,1005,570,151,1001,574,-64,574,1002,574,-1,574,1001,572,1,572,1007,572,11,570,1006,570,165,101,1182,572,127,101,0,574,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1105,1,81,21101,340,0,1,1105,1,177,21101,477,0,1,1106,0,177,21101,514,0,1,21101,0,176,0,1105,1,579,99,21102,1,184,0,1106,0,579,4,574,104,10,99,1007,573,22,570,1006,570,165,101,0,572,1182,21101,375,0,1,21101,211,0,0,1106,0,579,21101,1182,11,1,21101,222,0,0,1105,1,979,21101,0,388,1,21102,233,1,0,1106,0,579,21101,1182,22,1,21101,0,244,0,1106,0,979,21101,401,0,1,21102,1,255,0,1106,0,579,21101,1182,33,1,21101,266,0,0,1105,1,979,21101,414,0,1,21102,1,277,0,1106,0,579,3,575,1008,575,89,570,1008,575,121,575,1,575,570,575,3,574,1008,574,10,570,1006,570,291,104,10,21101,1182,0,1,21101,313,0,0,1105,1,622,1005,575,327,1101,0,1,575,21102,327,1,0,1106,0,786,4,438,99,0,1,1,6,77,97,105,110,58,10,33,10,69,120,112,101,99,116,101,100,32,102,117,110,99,116,105,111,110,32,110,97,109,101,32,98,117,116,32,103,111,116,58,32,0,12,70,117,110,99,116,105,111,110,32,65,58,10,12,70,117,110,99,116,105,111,110,32,66,58,10,12,70,117,110,99,116,105,111,110,32,67,58,10,23,67,111,110,116,105,110,117,111,117,115,32,118,105,100,101,111,32,102,101,101,100,63,10,0,37,10,69,120,112,101,99,116,101,100,32,82,44,32,76,44,32,111,114,32,100,105,115,116,97,110,99,101,32,98,117,116,32,103,111,116,58,32,36,10,69,120,112,101,99,116,101,100,32,99,111,109,109,97,32,111,114,32,110,101,119,108,105,110,101,32,98,117,116,32,103,111,116,58,32,43,10,68,101,102,105,110,105,116,105,111,110,115,32,109,97,121,32,98,101,32,97,116,32,109,111,115,116,32,50,48,32,99,104,97,114,97,99,116,101,114,115,33,10,94,62,118,60,0,1,0,-1,-1,0,1,0,0,0,0,0,0,1,20,14,0,109,4,2102,1,-3,586,21001,0,0,-1,22101,1,-3,-3,21102,1,0,-2,2208,-2,-1,570,1005,570,617,2201,-3,-2,609,4,0,21201,-2,1,-2,1105,1,597,109,-4,2105,1,0,109,5,2101,0,-4,629,21001,0,0,-2,22101,1,-4,-4,21101,0,0,-3,2208,-3,-2,570,1005,570,781,2201,-4,-3,652,21002,0,1,-1,1208,-1,-4,570,1005,570,709,1208,-1,-5,570,1005,570,734,1207,-1,0,570,1005,570,759,1206,-1,774,1001,578,562,684,1,0,576,576,1001,578,566,692,1,0,577,577,21101,702,0,0,1105,1,786,21201,-1,-1,-1,1106,0,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21101,0,731,0,1105,1,786,1106,0,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21102,1,756,0,1105,1,786,1105,1,774,21202,-1,-11,1,22101,1182,1,1,21101,0,774,0,1105,1,622,21201,-3,1,-3,1106,0,640,109,-5,2106,0,0,109,7,1005,575,802,20102,1,576,-6,20101,0,577,-5,1106,0,814,21101,0,0,-1,21102,1,0,-5,21101,0,0,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,45,-3,22201,-6,-3,-3,22101,1467,-3,-3,1202,-3,1,843,1005,0,863,21202,-2,42,-4,22101,46,-4,-4,1206,-2,924,21102,1,1,-1,1106,0,924,1205,-2,873,21101,0,35,-4,1105,1,924,1201,-3,0,878,1008,0,1,570,1006,570,916,1001,374,1,374,1201,-3,0,895,1102,1,2,0,1201,-3,0,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,921,21001,0,0,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,45,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,33,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1101,0,1,575,21101,973,0,0,1106,0,786,99,109,-7,2105,1,0,109,6,21101,0,0,-4,21102,1,0,-3,203,-2,22101,1,-3,-3,21208,-2,82,-1,1205,-1,1030,21208,-2,76,-1,1205,-1,1037,21207,-2,48,-1,1205,-1,1124,22107,57,-2,-1,1205,-1,1124,21201,-2,-48,-2,1106,0,1041,21102,-4,1,-2,1106,0,1041,21102,1,-5,-2,21201,-4,1,-4,21207,-4,11,-1,1206,-1,1138,2201,-5,-4,1059,1202,-2,1,0,203,-2,22101,1,-3,-3,21207,-2,48,-1,1205,-1,1107,22107,57,-2,-1,1205,-1,1107,21201,-2,-48,-2,2201,-5,-4,1090,20102,10,0,-1,22201,-2,-1,-2,2201,-5,-4,1103,1201,-2,0,0,1106,0,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1105,1,989,21101,0,439,1,1105,1,1150,21102,477,1,1,1106,0,1150,21102,1,514,1,21102,1149,1,0,1106,0,579,99,21102,1157,1,0,1105,1,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,1202,-5,1,1176,2102,1,-4,0,109,-6,2105,1,0,10,11,34,1,9,1,34,1,9,1,7,9,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,9,1,13,3,1,26,1,9,1,3,1,3,1,20,11,5,1,1,9,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,1,9,1,1,1,1,3,9,12,1,5,1,3,1,7,1,1,1,5,1,5,1,10,9,3,1,1,9,5,1,5,1,10,1,1,1,9,1,1,1,5,1,7,1,5,14,9,9,7,1,5,2,9,1,13,1,13,1,5,2,7,9,7,1,13,1,5,2,7,1,1,1,5,1,7,1,19,2,7,1,1,1,5,1,7,1,19,2,7,1,1,1,5,1,7,1,19,2,7,1,1,13,1,1,7,14,7,1,7,1,5,1,1,1,7,1,12,1,7,1,7,1,5,1,1,1,7,1,12,1,7,1,7,1,5,1,1,1,7,1,12,9,7,9,7,1,34,1,9,1,34,1,9,1,34,1,9,1,34,11,12

350
2019/d17/ex2/ex2.py Executable file
View file

@ -0,0 +1,350 @@
#!/usr/bin/env python
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import Enum, IntEnum, auto
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Position(NamedTuple):
x: int
y: int
class Direction(Enum):
NORTH = auto()
WEST = auto()
SOUTH = auto()
EAST = auto()
DIRECTIONS = [d for d in Direction]
ARROW_DIRECTION = {
"^": Direction.NORTH,
"v": Direction.SOUTH,
"<": Direction.WEST,
">": Direction.EAST,
}
DIRECTION_OFFSET = {
Direction.NORTH: (-1, 0),
Direction.SOUTH: (1, 0),
Direction.WEST: (0, -1),
Direction.EAST: (0, 1),
}
def turn(d: Direction, turn: str) -> Direction:
def turn_left() -> Direction:
return DIRECTIONS[(DIRECTIONS.index(d) + 1) % len(DIRECTIONS)]
def turn_right() -> Direction:
return DIRECTIONS[DIRECTIONS.index(d) - 1]
if turn == "L":
return turn_left()
elif turn == "R":
return turn_right()
assert False # Sanity check
def find_arrow(mapped_view: List[List[str]]) -> Position:
for x in range(len(mapped_view)):
for y in range(len(mapped_view[0])):
if mapped_view[x][y] in ARROW_DIRECTION:
return Position(x, y)
assert False # Sanity check
def get_path(mapped_view: List[List[str]]) -> List[str]:
pos = find_arrow(mapped_view)
def pos_is_valid(p: Position) -> bool:
return 0 <= p.x < len(mapped_view) and 0 <= p.y < len(mapped_view[0])
def pos_is_scaffold(p: Position) -> bool:
return pos_is_valid(p) and mapped_view[p.x][p.y] != "."
direction = ARROW_DIRECTION[mapped_view[pos.x][pos.y]]
ans: List[str] = []
def advance_until_stopped(turn_string: str) -> bool:
nonlocal pos
nonlocal direction
d = turn(direction, turn_string)
offset = DIRECTION_OFFSET[d]
neighbor = Position(*(a + b for a, b in zip(pos, offset)))
tot = 0
while pos_is_scaffold(neighbor):
tot += 1
mapped_view[pos.x][pos.y] = "@"
pos = neighbor
neighbor = Position(*(a + b for a, b in zip(pos, offset)))
if tot == 0:
return False
direction = d
ans.append(turn_string)
ans.append(str(tot))
return True
has_no_neighbors = False
while not has_no_neighbors:
for turn_string in ("L", "R"):
if advance_until_stopped(turn_string):
break
else:
has_no_neighbors = True
return ans
def sequitur_algorithm(path: str) -> None:
# FIXME: seems like a good candidate for compression
pass
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
camera = Computer(deepcopy(memory))
camera.run_no_output_interrupt()
view = "".join(chr(c) for c in camera.output_list)
mapped_view = [[c for c in line] for line in view.split("\n") if line != ""]
path = get_path(mapped_view)
print(path)
# I didn't want to write the compression algorithm when I could just use Vim
# The answere is A,B,B,A,C,A,A,C,B,C
# A: R,8,L,12,R,8
# B: R,12,L,8,R,10
# C: R,8,L,8,L,8,R,8,R,10
ans = "A,B,B,A,C,A,A,C,B,C"
A = "R,8,L,12,R,8"
B = "R,12,L,8,R,10"
C = "R,8,L,8,L,8,R,8,R,10"
assert len(ans) <= 20 # Sanity check
assert len(A) <= 20 # Sanity check
assert len(B) <= 20 # Sanity check
assert len(C) <= 20 # Sanity check
memory[0] = 2 # Wake up the robot
robot = Computer(memory)
for c in ans:
robot.input_list.append(ord(c))
robot.input_list.append(ord("\n"))
for c in A:
robot.input_list.append(ord(c))
robot.input_list.append(ord("\n"))
for c in B:
robot.input_list.append(ord(c))
robot.input_list.append(ord("\n"))
for c in C:
robot.input_list.append(ord(c))
robot.input_list.append(ord("\n"))
for c in "n\n": # Do not output the video feed
robot.input_list.append(ord(c))
robot.run_no_output_interrupt()
print(robot.output_list.pop())
if __name__ == "__main__":
main()

1
2019/d17/ex2/input Normal file
View file

@ -0,0 +1 @@
1,330,331,332,109,2952,1101,1182,0,16,1101,1467,0,24,102,1,0,570,1006,570,36,1002,571,1,0,1001,570,-1,570,1001,24,1,24,1106,0,18,1008,571,0,571,1001,16,1,16,1008,16,1467,570,1006,570,14,21101,0,58,0,1105,1,786,1006,332,62,99,21102,1,333,1,21101,73,0,0,1106,0,579,1101,0,0,572,1101,0,0,573,3,574,101,1,573,573,1007,574,65,570,1005,570,151,107,67,574,570,1005,570,151,1001,574,-64,574,1002,574,-1,574,1001,572,1,572,1007,572,11,570,1006,570,165,101,1182,572,127,101,0,574,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1105,1,81,21101,340,0,1,1105,1,177,21101,477,0,1,1106,0,177,21101,514,0,1,21101,0,176,0,1105,1,579,99,21102,1,184,0,1106,0,579,4,574,104,10,99,1007,573,22,570,1006,570,165,101,0,572,1182,21101,375,0,1,21101,211,0,0,1106,0,579,21101,1182,11,1,21101,222,0,0,1105,1,979,21101,0,388,1,21102,233,1,0,1106,0,579,21101,1182,22,1,21101,0,244,0,1106,0,979,21101,401,0,1,21102,1,255,0,1106,0,579,21101,1182,33,1,21101,266,0,0,1105,1,979,21101,414,0,1,21102,1,277,0,1106,0,579,3,575,1008,575,89,570,1008,575,121,575,1,575,570,575,3,574,1008,574,10,570,1006,570,291,104,10,21101,1182,0,1,21101,313,0,0,1105,1,622,1005,575,327,1101,0,1,575,21102,327,1,0,1106,0,786,4,438,99,0,1,1,6,77,97,105,110,58,10,33,10,69,120,112,101,99,116,101,100,32,102,117,110,99,116,105,111,110,32,110,97,109,101,32,98,117,116,32,103,111,116,58,32,0,12,70,117,110,99,116,105,111,110,32,65,58,10,12,70,117,110,99,116,105,111,110,32,66,58,10,12,70,117,110,99,116,105,111,110,32,67,58,10,23,67,111,110,116,105,110,117,111,117,115,32,118,105,100,101,111,32,102,101,101,100,63,10,0,37,10,69,120,112,101,99,116,101,100,32,82,44,32,76,44,32,111,114,32,100,105,115,116,97,110,99,101,32,98,117,116,32,103,111,116,58,32,36,10,69,120,112,101,99,116,101,100,32,99,111,109,109,97,32,111,114,32,110,101,119,108,105,110,101,32,98,117,116,32,103,111,116,58,32,43,10,68,101,102,105,110,105,116,105,111,110,115,32,109,97,121,32,98,101,32,97,116,32,109,111,115,116,32,50,48,32,99,104,97,114,97,99,116,101,114,115,33,10,94,62,118,60,0,1,0,-1,-1,0,1,0,0,0,0,0,0,1,20,14,0,109,4,2102,1,-3,586,21001,0,0,-1,22101,1,-3,-3,21102,1,0,-2,2208,-2,-1,570,1005,570,617,2201,-3,-2,609,4,0,21201,-2,1,-2,1105,1,597,109,-4,2105,1,0,109,5,2101,0,-4,629,21001,0,0,-2,22101,1,-4,-4,21101,0,0,-3,2208,-3,-2,570,1005,570,781,2201,-4,-3,652,21002,0,1,-1,1208,-1,-4,570,1005,570,709,1208,-1,-5,570,1005,570,734,1207,-1,0,570,1005,570,759,1206,-1,774,1001,578,562,684,1,0,576,576,1001,578,566,692,1,0,577,577,21101,702,0,0,1105,1,786,21201,-1,-1,-1,1106,0,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21101,0,731,0,1105,1,786,1106,0,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21102,1,756,0,1105,1,786,1105,1,774,21202,-1,-11,1,22101,1182,1,1,21101,0,774,0,1105,1,622,21201,-3,1,-3,1106,0,640,109,-5,2106,0,0,109,7,1005,575,802,20102,1,576,-6,20101,0,577,-5,1106,0,814,21101,0,0,-1,21102,1,0,-5,21101,0,0,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,45,-3,22201,-6,-3,-3,22101,1467,-3,-3,1202,-3,1,843,1005,0,863,21202,-2,42,-4,22101,46,-4,-4,1206,-2,924,21102,1,1,-1,1106,0,924,1205,-2,873,21101,0,35,-4,1105,1,924,1201,-3,0,878,1008,0,1,570,1006,570,916,1001,374,1,374,1201,-3,0,895,1102,1,2,0,1201,-3,0,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,921,21001,0,0,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,45,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,33,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1101,0,1,575,21101,973,0,0,1106,0,786,99,109,-7,2105,1,0,109,6,21101,0,0,-4,21102,1,0,-3,203,-2,22101,1,-3,-3,21208,-2,82,-1,1205,-1,1030,21208,-2,76,-1,1205,-1,1037,21207,-2,48,-1,1205,-1,1124,22107,57,-2,-1,1205,-1,1124,21201,-2,-48,-2,1106,0,1041,21102,-4,1,-2,1106,0,1041,21102,1,-5,-2,21201,-4,1,-4,21207,-4,11,-1,1206,-1,1138,2201,-5,-4,1059,1202,-2,1,0,203,-2,22101,1,-3,-3,21207,-2,48,-1,1205,-1,1107,22107,57,-2,-1,1205,-1,1107,21201,-2,-48,-2,2201,-5,-4,1090,20102,10,0,-1,22201,-2,-1,-2,2201,-5,-4,1103,1201,-2,0,0,1106,0,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1105,1,989,21101,0,439,1,1105,1,1150,21102,477,1,1,1106,0,1150,21102,1,514,1,21102,1149,1,0,1106,0,579,99,21102,1157,1,0,1105,1,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,1202,-5,1,1176,2102,1,-4,0,109,-6,2105,1,0,10,11,34,1,9,1,34,1,9,1,7,9,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,9,1,13,3,1,26,1,9,1,3,1,3,1,20,11,5,1,1,9,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,1,9,1,1,1,1,3,9,12,1,5,1,3,1,7,1,1,1,5,1,5,1,10,9,3,1,1,9,5,1,5,1,10,1,1,1,9,1,1,1,5,1,7,1,5,14,9,9,7,1,5,2,9,1,13,1,13,1,5,2,7,9,7,1,13,1,5,2,7,1,1,1,5,1,7,1,19,2,7,1,1,1,5,1,7,1,19,2,7,1,1,1,5,1,7,1,19,2,7,1,1,13,1,1,7,14,7,1,7,1,5,1,1,1,7,1,12,1,7,1,7,1,5,1,1,1,7,1,12,1,7,1,7,1,5,1,1,1,7,1,12,9,7,9,7,1,34,1,9,1,34,1,9,1,34,1,9,1,34,11,12

128
2019/d18/ex1/ex1.py Executable file
View file

@ -0,0 +1,128 @@
#!/usr/bin/env python
import heapq
import sys
from collections import defaultdict, deque
from dataclasses import dataclass
from functools import lru_cache
from math import inf
from typing import DefaultDict, Deque, Dict, FrozenSet, Iterator, List, Tuple, Union
RawGrid = List[str]
GraphInfo = List[Tuple[str, int]]
Graph = Dict[str, GraphInfo]
@dataclass(eq=True, frozen=True) # Hash-able
class Position:
x: int
y: int
def neighbours(grid: RawGrid, pos: Position) -> Iterator[Position]:
for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):
new_pos = Position(pos.x + dx, pos.y + dy)
if not (0 <= new_pos.x < len(grid) and 0 <= new_pos.y < len(grid[0])):
continue
if grid[new_pos.x][new_pos.y] == "#":
continue
yield new_pos
def find_adjacent(grid: RawGrid, pos: Position) -> GraphInfo:
queue: Deque[Tuple[Position, int]] = deque()
visited = {pos}
adjacent: GraphInfo = []
for n in neighbours(grid, pos):
queue.append((n, 1)) # Distance is 1
while queue:
n, d = queue.popleft()
if n in visited:
continue
visited |= {n}
cell = grid[n.x][n.y]
if cell not in "#.@": # We don't care about those
adjacent.append((cell, d))
continue # Do not go through doors and keys
for neighbour in neighbours(grid, n):
queue.append((neighbour, d + 1))
return adjacent
def build_graph(grid: RawGrid) -> Graph:
graph = {}
for x, row in enumerate(grid):
for y, cell in enumerate(row):
if cell not in "#.":
graph[cell] = find_adjacent(grid, Position(x, y))
return graph
def solve(G: Graph, start: str) -> int:
@lru_cache(2**20)
def reachable_keys(src: str, found: FrozenSet[str]) -> List[Tuple[str, int]]:
queue = []
distance: DefaultDict[str, Union[float, int]] = defaultdict(lambda: inf)
reachable: List[Tuple[str, int]] = []
for neighbor, weight in G[src]:
queue.append((weight, neighbor)) # Weight first for heap comparisons
heapq.heapify(queue)
while queue:
dist, node = heapq.heappop(queue)
# Do key, add it to reachable if not found previously
if node.islower() and node not in found:
reachable.append((node, dist))
continue
# Do door, if not opened by a key that was found in the search
if node.lower() not in found:
continue
# If not a key and not a closed door
for neighbor, weight in G[node]:
new_dist = dist + weight
if new_dist < distance[neighbor]:
distance[neighbor] = new_dist
heapq.heappush(queue, (new_dist, neighbor))
return reachable
@lru_cache(2**20)
def min_steps(
src: str, keys_to_find: int, found: FrozenSet[str] = frozenset()
) -> int:
if keys_to_find == 0:
return 0
best = inf
for key, dist in reachable_keys(src, found):
new_keys = found | {key}
dist += min_steps(key, keys_to_find - 1, new_keys)
if dist < best:
best = dist
return int(best) # That way we throw if we kept the infinite float
total_keys = sum(node.islower() for node in G)
return min_steps(start, total_keys)
def main() -> None:
G = build_graph(list(line.strip() for line in sys.stdin.readlines()))
print(solve(G, "@"))
if __name__ == "__main__":
main()

81
2019/d18/ex1/input Normal file
View file

@ -0,0 +1,81 @@
#################################################################################
#.......#...#...#...........#.....#...#.#.....#m......#.......#.....#........u..#
#####.#.#.#.#.#.###.#######.###.#.#.#.#.#.###.###.#####.#.###.###.#.###########.#
#.....#...#...#.....#.#.....#...#...#...#.#....e#.......#...#.....#.....#.......#
#.###################.#.#####.#########.#.#####.###########.###########.#.#######
#.#...#...#...........#.#.....#.......#.#.....#.....#.....#...#.......#.#.#.....#
#.#S#.###.#.#####.#####.#.###.#.###.###.#####.#####.#.###.###.#.#.#####.#.#.###.#
#.#.#...#.#...#.#.......#.#.#.#.#...#...#.D.#.#...#...#.#.#...#.#.#.....#j..#...#
#.#.###.#.###.#.#########.#.#.###.###.###.#.#.#.#.#####.#.#.###.###.#########.###
#.#...#.#...#...#.#.........#...#.#...#.#.#...#.#.....#...#...#...#.#.#.....#...#
#.###.#.###.###.#.#.#########.#.#.#.###.#.#####.#####.#.#####.###.#.#.#.#.#.###.#
#...#.#c..#.....#.......#...#.#.#.#.#...#...#.....#.#.#.#.....#...#.#...#.#...#.#
#.###.###.#.#############.#.###.#.#.#.#.###.#####.#.#.#.#.#####.###.#.###.###.#.#
#.#...#.#.#.........#.....#...#.#.....#.#.#...#.#...#.#...#...#.....#.#...#...K.#
#.#.###.#.#########.#.#######.#.#########.###.#.###.#.#####.#.#.#######.#########
#.......#.#.......#h..#.....#.#.........#...#.#.....#.......#...#.....#.#...#...#
#.#######.#O#####.#######.#.#.#.#######.###.#.#.#######.#######.#.###F#.#.#.#.#.#
#.#....y..#...#...#.....#.#.#.#.#.#.....#...#.#.#.....#.#.....#...#.#.#...#.#.#.#
###.#####.###.#.###.###.#.###.#.#.#.###.#.#.#.###.###.#.#.###.#####.#.#.###.#.#.#
#...#.....#.#.#...#.#.Z.#...#.#.#.#.#...#.#.#.....#.#.#.#.#.#...#.....#...#...#.#
#.###.#####.#.###A#.#.###.#.#.#.#.#.#####.#########.#.#.#.#.###.#.#########.###.#
#.#.#.#.....#.#.#...#.#...#...#...#.....#.#.........#.#.#.#.#...#.#.......#.#...#
#.#.#.#####.#.#.#######.#########.#####.#.#.#####.#.#.#.#.#.#####.#.###.#.###.#.#
#.#.#...#...#.#...#.....#.....#.......#.#.#.#.#...#.#.#.#.#.....#.#.#...#.....#.#
#.#.###.#.#.#.###.#.#######.#.#####.###.#.#.#.#.#####.#.#.#.#.###.###.#########X#
#.#...#...#.#...#.#...#.....#.....#.#...#.....#.#...#.#.#.#.#...#...#.....#.....#
#.#W#.#####.###N#.###.#.#.#######.###.#.#######.#.#.#.###.#.###.###.#####.###.###
#i#.#.....#.#.#.#...#.#.#.#.....#.....#.#..r..#...#.#...#.#.#.....#.#...#...#.#.#
#.#######.#.#.#.#.###.###.#.###########.#.###.#.###.###.#.###.#####.#.#.###.#.#.#
#.......#...#.#.#...#...#.#.............#.#.#.#.#.#...#...#...#.....#.#.....#.#.#
#.#####.#.###.#.#.#.###.#.#.#############.#.#.#.#.###.#####.###.#####.#######.#.#
#.#.#...#.....#.#.#...#..t#...#.#.......#.#.#.#...#.....#.....#...#...#.....#.#.#
#.#.#.#######.#.#.###.#######.#.#.#.#####.#.#.#.###.###.#####.###.###.#.###.#.#.#
#...#.#...#...#.#...#.....#.#.#...#.....#.#.#.#.#...#.........#.#...#...T.#.#...#
###.#.#.#.#.###.###.#.###.#.#.#########.#.#.#.###.###########.#.###.#####.#.###.#
#...#...#.#.#...#...#...#...#.......#...#.#.#...#.#.....#...#...#...#...#.#...#.#
#.#######.###.###.#####.###########.#.###.#.###.#.#.###.#.#.###.#.###.#.#####.###
#.#...#v#...#.#.#.....#.........#...#...#.#.......#...#..l#...#.#.....#.....#.P.#
#.#.#.#.###.#.#.#####.#########.#.#####.#.###########.#######.#############.###.#
#...#.....#...#...............#.............................#....b..............#
#######################################.@.#######################################
#...#.#.........#.....#...........#...........#...#.....#.......#...#.....Q.#...#
#.#.#.#.#####.###.#.#.#.#####.###.#.###.#.###.#.#.#.###.#.#####.#.#.#.#.###.###.#
#.#.#.#.#...#.....#.#.#.#.#...#...#...#.#.#.....#.#...#...#.....#.#.#.#...#.#...#
#.#.#.#.#.#.#######.###.#.#.#####.###.#.#.#######.###.#####.#####.#.#.###.#.#.#.#
#.#...#.#.#.....#.#.#.B...#.....#.#...#.#.....#.....#.#...#.......#.#.#...#...#.#
#.#####.#.#####.#.#.#.#######.#.###.###.#.###.###.###.#.#####.#####.#.#.#######.#
#.#...#q#..f#.....#...#.....#.#...#.#...#.#.#...#.#.....#...#.#...#...#.#.....#.#
#.#.#.#.#.#.#######.###.###.###.#.#.#.###.#.###.###.#####.#.#.###.#####.#.###.#.#
#...#.#.#.#...#...#p..#.#.#...#.#...#...#.....#...#.#.....#.#.....#...#...#...#.#
#####.#.#####.#.#.###.#.#.###.#########.#####.###.#.#.#####.#####.###.#####.###.#
#.....#.......#.#.#...#.#...#.#.......#.#...#.#.#...#.#...#.....#.....#.#...#.#.#
#.###########.#.#.#####.###.#L#.#####R#.#.#.#.#.#####.#.#.#####.#####.#.#.###.#.#
#...........#.#.#.......#...#...#...#...#.#.#.....#...#.#.....#...#...#.#...#...#
#######.###.#.#.#########.#.#####.#.#######.#####.#.#######.#.###.#.###.###.###.#
#.......#...#.#.#.........#.......#.....#...#.....#.#.....#.#...#.#...#...#...#.#
#.#######.###.#.#.###.#################.#.###.#####.#.#.#.###.###.###.###.###.#.#
#.#.........#.#.#...#.............#.....#.........#.#.#.#.....#...#.#.......#.#.#
#.###.#######.#.###########.#####.#.###############.###.#####.#.###.#.#####.#.###
#...#.#.......#.#.........#.#...#.#.#...#.......#...#...#.#...#.#.....#...#.#...#
#.#G###.#######.#.#######.#.###.#.###.#.#.#####.#.###.###.#.###.#######.#.#####.#
#.#...#....x#.#.#.#z#.....#.....#.....#.#.....#...#...#...#.#...#.......#.#...#.#
#.###.#####.#.#.#.#.#########.#########.#####.#######.#.###.#####.#######.#.#.#.#
#k#.#.....#...#...#.#.....#...#.......#.#...#.#.......#.#...#.....#.#...#...#.#.#
#.#.#####.###.#####.#.###.#.###.#####.#.#.#.#.#.#.#####.#.###.#####.#.#.#####.#H#
#.#.....#...#.....#.#...#.#.#...#...#...#.#...#.#.#.....#.#...#...#...#...#.#.#.#
#.#.###.###.#####.#.###.#.#.#.###.#.###.#.#######.#.###.#.#.###.#.#.###.#Y#.#.#.#
#...#...#.#...#...#.....#..o#.#.#.#.....#.#.......#.#...#...#...#...#...#...#..g#
#####.###.#.###.#######.#####.#.#.#######.#####.###.###.#############.#####.###.#
#...#.#...#.....#.....#.....#.#.#...#...#.......#.....#...#...........#.#...#...#
#.#.#.###.#######.###.#######.#.###.#.###########.###.###.#.###########.#.###.###
#.#.#.#.....#.#.....#.#.......#...#.#...#...#...#...#.#...#.......#...#.I.#.#...#
#.#.#.#.###.#.#.###.#.#.#######.#.#.###.#.###.#.#.###.#.#########.###.#.###.###.#
#.#.#.#.#...#s....#.#.#.......#a#.#.....#.#...#.#.#...#.....#.....#...#.....#.#.#
#.###M#U###.#####.#.#.###.###.###.#####.#.#.###.#.#.#.#####.#.#####.#V#####.#.#.#
#.....#...#...#...#.#...#...#.#...#....n#.#...#d..#.#.#.J.#...#.....#...#..w#.#.#
#.#######.###.#####.###.#####.#.###.#####.###.#####.#.#.#.###.#####.#####.###.#.#
#.......#.#.#...#...#.#.....#.#...#.#...#...#.#.#...#.#.#.#...#...#...........#.#
#######.#.#.###E#.###.#####.#.#.#.#.###.#.###.#.#.#####.#.#####.#.#############.#
#.........#.......#.........C.#.#.......#.......#.......#.......#...............#
#################################################################################

130
2019/d18/ex2/ex2.py Executable file
View file

@ -0,0 +1,130 @@
#!/usr/bin/env python
import heapq
import sys
from collections import defaultdict, deque
from dataclasses import dataclass
from functools import lru_cache
from math import inf
from typing import DefaultDict, Deque, Dict, FrozenSet, Iterator, List, Tuple, Union
RawGrid = List[str]
GraphInfo = List[Tuple[str, int]]
Graph = Dict[str, GraphInfo]
@dataclass(eq=True, frozen=True) # Hash-able
class Position:
x: int
y: int
def neighbours(grid: RawGrid, pos: Position) -> Iterator[Position]:
for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):
new_pos = Position(pos.x + dx, pos.y + dy)
if not (0 <= new_pos.x < len(grid) and 0 <= new_pos.y < len(grid[0])):
continue
if grid[new_pos.x][new_pos.y] == "#":
continue
yield new_pos
def find_adjacent(grid: RawGrid, pos: Position) -> GraphInfo:
queue: Deque[Tuple[Position, int]] = deque()
visited = {pos}
adjacent: GraphInfo = []
for n in neighbours(grid, pos):
queue.append((n, 1)) # Distance is 1
while queue:
n, d = queue.popleft()
if n in visited:
continue
visited |= {n}
cell = grid[n.x][n.y]
if cell not in "#.1234": # We don't care about those
adjacent.append((cell, d))
continue # Do not go through doors and keys
for neighbour in neighbours(grid, n):
queue.append((neighbour, d + 1))
return adjacent
def build_graph(grid: RawGrid) -> Graph:
graph = {}
for x, row in enumerate(grid):
for y, cell in enumerate(row):
if cell not in "#.":
graph[cell] = find_adjacent(grid, Position(x, y))
return graph
def solve(G: Graph, start: str) -> int:
@lru_cache(2**20)
def reachable_keys(src: str, found: FrozenSet[str]) -> GraphInfo:
queue = []
distance: DefaultDict[str, Union[float, int]] = defaultdict(lambda: inf)
reachable: GraphInfo = []
for neighbor, weight in G[src]:
queue.append((weight, neighbor)) # Weight first for heap comparisons
heapq.heapify(queue)
while queue:
dist, node = heapq.heappop(queue)
# Do key, add it to reachable if not found previously
if node.islower() and node not in found:
reachable.append((node, dist))
continue
# Do door, if not opened by a key that was found in the search
if node.lower() not in found:
continue
# If not a key and not a closed door
for neighbor, weight in G[node]:
new_dist = dist + weight
if new_dist < distance[neighbor]:
distance[neighbor] = new_dist
heapq.heappush(queue, (new_dist, neighbor))
return reachable
@lru_cache(2**20)
def min_steps(
sources: str, keys_to_find: int, found: FrozenSet[str] = frozenset()
) -> Union[float, int]:
if keys_to_find == 0:
return 0
best = inf
for src in sources:
for key, dist in reachable_keys(src, found):
new_keys = found | {key}
new_sources = sources.replace(src, key)
new_dist = dist + min_steps(new_sources, keys_to_find - 1, new_keys)
if new_dist < best:
best = new_dist
return best
total_keys = sum(node.islower() for node in G)
return int(min_steps(start, total_keys)) # Throw if we kept the infinite float
def main() -> None:
G = build_graph(list(line.strip() for line in sys.stdin.readlines()))
print(solve(G, "1234"))
if __name__ == "__main__":
main()

81
2019/d18/ex2/input Normal file
View file

@ -0,0 +1,81 @@
#################################################################################
#.......#...#...#...........#.....#...#.#.....#m......#.......#.....#........u..#
#####.#.#.#.#.#.###.#######.###.#.#.#.#.#.###.###.#####.#.###.###.#.###########.#
#.....#...#...#.....#.#.....#...#...#...#.#....e#.......#...#.....#.....#.......#
#.###################.#.#####.#########.#.#####.###########.###########.#.#######
#.#...#...#...........#.#.....#.......#.#.....#.....#.....#...#.......#.#.#.....#
#.#S#.###.#.#####.#####.#.###.#.###.###.#####.#####.#.###.###.#.#.#####.#.#.###.#
#.#.#...#.#...#.#.......#.#.#.#.#...#...#.D.#.#...#...#.#.#...#.#.#.....#j..#...#
#.#.###.#.###.#.#########.#.#.###.###.###.#.#.#.#.#####.#.#.###.###.#########.###
#.#...#.#...#...#.#.........#...#.#...#.#.#...#.#.....#...#...#...#.#.#.....#...#
#.###.#.###.###.#.#.#########.#.#.#.###.#.#####.#####.#.#####.###.#.#.#.#.#.###.#
#...#.#c..#.....#.......#...#.#.#.#.#...#...#.....#.#.#.#.....#...#.#...#.#...#.#
#.###.###.#.#############.#.###.#.#.#.#.###.#####.#.#.#.#.#####.###.#.###.###.#.#
#.#...#.#.#.........#.....#...#.#.....#.#.#...#.#...#.#...#...#.....#.#...#...K.#
#.#.###.#.#########.#.#######.#.#########.###.#.###.#.#####.#.#.#######.#########
#.......#.#.......#h..#.....#.#.........#...#.#.....#.......#...#.....#.#...#...#
#.#######.#O#####.#######.#.#.#.#######.###.#.#.#######.#######.#.###F#.#.#.#.#.#
#.#....y..#...#...#.....#.#.#.#.#.#.....#...#.#.#.....#.#.....#...#.#.#...#.#.#.#
###.#####.###.#.###.###.#.###.#.#.#.###.#.#.#.###.###.#.#.###.#####.#.#.###.#.#.#
#...#.....#.#.#...#.#.Z.#...#.#.#.#.#...#.#.#.....#.#.#.#.#.#...#.....#...#...#.#
#.###.#####.#.###A#.#.###.#.#.#.#.#.#####.#########.#.#.#.#.###.#.#########.###.#
#.#.#.#.....#.#.#...#.#...#...#...#.....#.#.........#.#.#.#.#...#.#.......#.#...#
#.#.#.#####.#.#.#######.#########.#####.#.#.#####.#.#.#.#.#.#####.#.###.#.###.#.#
#.#.#...#...#.#...#.....#.....#.......#.#.#.#.#...#.#.#.#.#.....#.#.#...#.....#.#
#.#.###.#.#.#.###.#.#######.#.#####.###.#.#.#.#.#####.#.#.#.#.###.###.#########X#
#.#...#...#.#...#.#...#.....#.....#.#...#.....#.#...#.#.#.#.#...#...#.....#.....#
#.#W#.#####.###N#.###.#.#.#######.###.#.#######.#.#.#.###.#.###.###.#####.###.###
#i#.#.....#.#.#.#...#.#.#.#.....#.....#.#..r..#...#.#...#.#.#.....#.#...#...#.#.#
#.#######.#.#.#.#.###.###.#.###########.#.###.#.###.###.#.###.#####.#.#.###.#.#.#
#.......#...#.#.#...#...#.#.............#.#.#.#.#.#...#...#...#.....#.#.....#.#.#
#.#####.#.###.#.#.#.###.#.#.#############.#.#.#.#.###.#####.###.#####.#######.#.#
#.#.#...#.....#.#.#...#..t#...#.#.......#.#.#.#...#.....#.....#...#...#.....#.#.#
#.#.#.#######.#.#.###.#######.#.#.#.#####.#.#.#.###.###.#####.###.###.#.###.#.#.#
#...#.#...#...#.#...#.....#.#.#...#.....#.#.#.#.#...#.........#.#...#...T.#.#...#
###.#.#.#.#.###.###.#.###.#.#.#########.#.#.#.###.###########.#.###.#####.#.###.#
#...#...#.#.#...#...#...#...#.......#...#.#.#...#.#.....#...#...#...#...#.#...#.#
#.#######.###.###.#####.###########.#.###.#.###.#.#.###.#.#.###.#.###.#.#####.###
#.#...#v#...#.#.#.....#.........#...#...#.#.......#...#..l#...#.#.....#.....#.P.#
#.#.#.#.###.#.#.#####.#########.#.#####.#.###########.#######.#############.###.#
#...#.....#...#...............#........1#2..................#....b..............#
########################################@.#######################################
#...#.#.........#.....#...........#....3#4....#...#.....#.......#...#.....Q.#...#
#.#.#.#.#####.###.#.#.#.#####.###.#.###.#.###.#.#.#.###.#.#####.#.#.#.#.###.###.#
#.#.#.#.#...#.....#.#.#.#.#...#...#...#.#.#.....#.#...#...#.....#.#.#.#...#.#...#
#.#.#.#.#.#.#######.###.#.#.#####.###.#.#.#######.###.#####.#####.#.#.###.#.#.#.#
#.#...#.#.#.....#.#.#.B...#.....#.#...#.#.....#.....#.#...#.......#.#.#...#...#.#
#.#####.#.#####.#.#.#.#######.#.###.###.#.###.###.###.#.#####.#####.#.#.#######.#
#.#...#q#..f#.....#...#.....#.#...#.#...#.#.#...#.#.....#...#.#...#...#.#.....#.#
#.#.#.#.#.#.#######.###.###.###.#.#.#.###.#.###.###.#####.#.#.###.#####.#.###.#.#
#...#.#.#.#...#...#p..#.#.#...#.#...#...#.....#...#.#.....#.#.....#...#...#...#.#
#####.#.#####.#.#.###.#.#.###.#########.#####.###.#.#.#####.#####.###.#####.###.#
#.....#.......#.#.#...#.#...#.#.......#.#...#.#.#...#.#...#.....#.....#.#...#.#.#
#.###########.#.#.#####.###.#L#.#####R#.#.#.#.#.#####.#.#.#####.#####.#.#.###.#.#
#...........#.#.#.......#...#...#...#...#.#.#.....#...#.#.....#...#...#.#...#...#
#######.###.#.#.#########.#.#####.#.#######.#####.#.#######.#.###.#.###.###.###.#
#.......#...#.#.#.........#.......#.....#...#.....#.#.....#.#...#.#...#...#...#.#
#.#######.###.#.#.###.#################.#.###.#####.#.#.#.###.###.###.###.###.#.#
#.#.........#.#.#...#.............#.....#.........#.#.#.#.....#...#.#.......#.#.#
#.###.#######.#.###########.#####.#.###############.###.#####.#.###.#.#####.#.###
#...#.#.......#.#.........#.#...#.#.#...#.......#...#...#.#...#.#.....#...#.#...#
#.#G###.#######.#.#######.#.###.#.###.#.#.#####.#.###.###.#.###.#######.#.#####.#
#.#...#....x#.#.#.#z#.....#.....#.....#.#.....#...#...#...#.#...#.......#.#...#.#
#.###.#####.#.#.#.#.#########.#########.#####.#######.#.###.#####.#######.#.#.#.#
#k#.#.....#...#...#.#.....#...#.......#.#...#.#.......#.#...#.....#.#...#...#.#.#
#.#.#####.###.#####.#.###.#.###.#####.#.#.#.#.#.#.#####.#.###.#####.#.#.#####.#H#
#.#.....#...#.....#.#...#.#.#...#...#...#.#...#.#.#.....#.#...#...#...#...#.#.#.#
#.#.###.###.#####.#.###.#.#.#.###.#.###.#.#######.#.###.#.#.###.#.#.###.#Y#.#.#.#
#...#...#.#...#...#.....#..o#.#.#.#.....#.#.......#.#...#...#...#...#...#...#..g#
#####.###.#.###.#######.#####.#.#.#######.#####.###.###.#############.#####.###.#
#...#.#...#.....#.....#.....#.#.#...#...#.......#.....#...#...........#.#...#...#
#.#.#.###.#######.###.#######.#.###.#.###########.###.###.#.###########.#.###.###
#.#.#.#.....#.#.....#.#.......#...#.#...#...#...#...#.#...#.......#...#.I.#.#...#
#.#.#.#.###.#.#.###.#.#.#######.#.#.###.#.###.#.#.###.#.#########.###.#.###.###.#
#.#.#.#.#...#s....#.#.#.......#a#.#.....#.#...#.#.#...#.....#.....#...#.....#.#.#
#.###M#U###.#####.#.#.###.###.###.#####.#.#.###.#.#.#.#####.#.#####.#V#####.#.#.#
#.....#...#...#...#.#...#...#.#...#....n#.#...#d..#.#.#.J.#...#.....#...#..w#.#.#
#.#######.###.#####.###.#####.#.###.#####.###.#####.#.#.#.###.#####.#####.###.#.#
#.......#.#.#...#...#.#.....#.#...#.#...#...#.#.#...#.#.#.#...#...#...........#.#
#######.#.#.###E#.###.#####.#.#.#.#.###.#.###.#.#.#####.#.#####.#.#############.#
#.........#.......#.........C.#.#.......#.......#.......#.......#...............#
#################################################################################

214
2019/d19/ex1/ex1.py Executable file
View file

@ -0,0 +1,214 @@
#!/usr/bin/env python
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import IntEnum
from itertools import product
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self) -> None: # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
lines: List[List[int]] = [[0 for i in range(50)] for __ in range(50)]
for x, y in product(range(50), range(50)):
drone = Computer(deepcopy(memory), input_list=[x, y])
drone.run_no_output_interrupt()
assert len(drone.output_list) == 1
lines[x][y] = drone.output_list.pop()
print(sum(map(sum, lines)))
if __name__ == "__main__":
main()

1
2019/d19/ex1/input Normal file
View file

@ -0,0 +1 @@
109,424,203,1,21102,11,1,0,1106,0,282,21102,18,1,0,1106,0,259,1201,1,0,221,203,1,21102,31,1,0,1106,0,282,21101,38,0,0,1106,0,259,21002,23,1,2,22102,1,1,3,21101,1,0,1,21102,57,1,0,1105,1,303,2102,1,1,222,20101,0,221,3,20101,0,221,2,21102,259,1,1,21101,80,0,0,1106,0,225,21101,0,44,2,21102,91,1,0,1105,1,303,1201,1,0,223,20101,0,222,4,21101,0,259,3,21102,225,1,2,21101,225,0,1,21102,118,1,0,1105,1,225,21002,222,1,3,21101,100,0,2,21101,133,0,0,1105,1,303,21202,1,-1,1,22001,223,1,1,21101,148,0,0,1106,0,259,2102,1,1,223,20102,1,221,4,21002,222,1,3,21102,1,12,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21102,1,195,0,106,0,108,20207,1,223,2,21002,23,1,1,21102,-1,1,3,21101,0,214,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,2102,1,-4,249,21201,-3,0,1,22101,0,-2,2,22101,0,-1,3,21101,0,250,0,1105,1,225,22102,1,1,-4,109,-5,2106,0,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,21202,-2,1,-2,109,-3,2105,1,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,22102,1,-2,3,21101,0,343,0,1105,1,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,21201,-4,0,1,21101,0,384,0,1106,0,303,1106,0,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,22102,1,1,-4,109,-5,2106,0,0

221
2019/d19/ex2/ex2.py Executable file
View file

@ -0,0 +1,221 @@
#!/usr/bin/env python
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import IntEnum
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self) -> None: # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def true_at(memory: List[int], x: int, y: int) -> bool:
drone = Computer(deepcopy(memory), input_list=[x, y])
drone.run_no_output_interrupt()
assert len(drone.output_list) == 1
return drone.output_list.pop() == 1
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
x = 0
y = 0
size = 100
while not true_at(memory, x + size - 1, y):
y += 1
while not true_at(memory, x, y + size - 1):
x += 1
print((x * 10000 + y))
if __name__ == "__main__":
main()

1
2019/d19/ex2/input Normal file
View file

@ -0,0 +1 @@
109,424,203,1,21102,11,1,0,1106,0,282,21102,18,1,0,1106,0,259,1201,1,0,221,203,1,21102,31,1,0,1106,0,282,21101,38,0,0,1106,0,259,21002,23,1,2,22102,1,1,3,21101,1,0,1,21102,57,1,0,1105,1,303,2102,1,1,222,20101,0,221,3,20101,0,221,2,21102,259,1,1,21101,80,0,0,1106,0,225,21101,0,44,2,21102,91,1,0,1105,1,303,1201,1,0,223,20101,0,222,4,21101,0,259,3,21102,225,1,2,21101,225,0,1,21102,118,1,0,1105,1,225,21002,222,1,3,21101,100,0,2,21101,133,0,0,1105,1,303,21202,1,-1,1,22001,223,1,1,21101,148,0,0,1106,0,259,2102,1,1,223,20102,1,221,4,21002,222,1,3,21102,1,12,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21102,1,195,0,106,0,108,20207,1,223,2,21002,23,1,1,21102,-1,1,3,21101,0,214,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,2102,1,-4,249,21201,-3,0,1,22101,0,-2,2,22101,0,-1,3,21101,0,250,0,1105,1,225,22102,1,1,-4,109,-5,2106,0,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,21202,-2,1,-2,109,-3,2105,1,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,22102,1,-2,3,21101,0,343,0,1105,1,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,21201,-4,0,1,21101,0,384,0,1106,0,303,1106,0,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,22102,1,1,-4,109,-5,2106,0,0

17
2020/d01/ex1/ex1.py Executable file
View file

@ -0,0 +1,17 @@
#!/usr/bin/env python
import functools
import itertools
import operator
import sys
def main() -> None:
values = [int(n) for n in sys.stdin.readlines()]
for tup in itertools.combinations(values, 2):
if sum(tup) == 2020:
print(functools.reduce(operator.mul, tup))
break
if __name__ == "__main__":
main()

200
2020/d01/ex1/input Normal file
View file

@ -0,0 +1,200 @@
1742
1763
1238
1424
1736
1903
1580
1847
1860
1933
1779
1901
1984
1861
1769
1896
1428
2010
1673
1491
1996
1746
1973
1696
1616
2006
1890
1600
1991
1724
1804
1794
462
1706
2002
1939
1834
1312
1943
1465
1405
1459
1659
1288
1241
1935
1294
1388
1772
1945
1649
813
1956
1274
1686
1404
1770
1631
1366
1321
1353
1685
1365
1738
1911
1235
1495
1837
1456
1283
1929
1326
1735
1604
1223
1261
1844
1850
1429
277
1848
1818
1395
1522
1863
1475
1562
1351
1538
1313
1416
1690
1539
1338
1982
1297
1821
780
1859
1420
1934
1303
1731
1714
1702
1417
1872
1998
1908
1957
1270
1359
1760
1997
1773
2000
1203
1880
1955
1273
1775
1893
1237
1707
1885
1900
1801
1367
1561
1524
1678
1511
1623
1464
1477
1733
1423
1575
1851
2007
1651
804
1836
1849
1713
1401
1502
1806
1506
1646
1968
1253
1889
1759
1734
1611
1558
1256
1657
1778
1953
1578
1717
1498
1381
1919
1512
1391
384
1802
1573
1940
1323
2003
1689
1936
1368
1962
1964
1586
1619
1482
1445
372
1792
96
1468
1999
1301
1757
1613
1807
1941
1642
1557
1884
1626
489
1989
1327

17
2020/d01/ex2/ex2.py Executable file
View file

@ -0,0 +1,17 @@
#!/usr/bin/env python
import functools
import itertools
import operator
import sys
def main() -> None:
values = [int(n) for n in sys.stdin.readlines()]
for tup in itertools.combinations(values, 3):
if sum(tup) == 2020:
print(functools.reduce(operator.mul, tup))
break
if __name__ == "__main__":
main()

200
2020/d01/ex2/input Normal file
View file

@ -0,0 +1,200 @@
1742
1763
1238
1424
1736
1903
1580
1847
1860
1933
1779
1901
1984
1861
1769
1896
1428
2010
1673
1491
1996
1746
1973
1696
1616
2006
1890
1600
1991
1724
1804
1794
462
1706
2002
1939
1834
1312
1943
1465
1405
1459
1659
1288
1241
1935
1294
1388
1772
1945
1649
813
1956
1274
1686
1404
1770
1631
1366
1321
1353
1685
1365
1738
1911
1235
1495
1837
1456
1283
1929
1326
1735
1604
1223
1261
1844
1850
1429
277
1848
1818
1395
1522
1863
1475
1562
1351
1538
1313
1416
1690
1539
1338
1982
1297
1821
780
1859
1420
1934
1303
1731
1714
1702
1417
1872
1998
1908
1957
1270
1359
1760
1997
1773
2000
1203
1880
1955
1273
1775
1893
1237
1707
1885
1900
1801
1367
1561
1524
1678
1511
1623
1464
1477
1733
1423
1575
1851
2007
1651
804
1836
1849
1713
1401
1502
1806
1506
1646
1968
1253
1889
1759
1734
1611
1558
1256
1657
1778
1953
1578
1717
1498
1381
1919
1512
1391
384
1802
1573
1940
1323
2003
1689
1936
1368
1962
1964
1586
1619
1482
1445
372
1792
96
1468
1999
1301
1757
1613
1807
1941
1642
1557
1884
1626
489
1989
1327

42
2020/d02/ex1/ex1.py Executable file
View file

@ -0,0 +1,42 @@
#!/usr/bin/env python
import re
import sys
from dataclasses import dataclass
from typing import List
@dataclass
class Policy:
min: int
max: int
letter: str
@dataclass
class Password:
policy: Policy
password: str
def is_valid(pwd: Password) -> bool:
occurences = pwd.password.count(pwd.policy.letter)
return pwd.policy.min <= occurences <= pwd.policy.max
def solve(passwords: List[Password]) -> int:
return sum(map(is_valid, passwords))
def main() -> None:
pattern = re.compile("([0-9]+)-([0-9]+) (.): (.+)")
input = [
Password(Policy(int(m.group(1)), int(m.group(2)), m.group(3)), m.group(4))
for m in (pattern.match(line) for line in sys.stdin.readlines())
if m
]
print(solve(input))
if __name__ == "__main__":
main()

1000
2020/d02/ex1/input Normal file

File diff suppressed because it is too large Load diff

43
2020/d02/ex2/ex2.py Executable file
View file

@ -0,0 +1,43 @@
#!/usr/bin/env python
import re
import sys
from dataclasses import dataclass
from typing import List
@dataclass
class Policy:
min: int
max: int
letter: str
@dataclass
class Password:
policy: Policy
password: str
def is_valid(pwd: Password) -> bool:
min = pwd.password[pwd.policy.min - 1] == pwd.policy.letter
max = pwd.password[pwd.policy.max - 1] == pwd.policy.letter
return min ^ max
def solve(passwords: List[Password]) -> int:
return sum(map(is_valid, passwords))
def main() -> None:
pattern = re.compile("([0-9]+)-([0-9]+) (.): (.+)")
input = [
Password(Policy(int(m.group(1)), int(m.group(2)), m.group(3)), m.group(4))
for m in (pattern.match(line) for line in sys.stdin.readlines())
if m
]
print(solve(input))
if __name__ == "__main__":
main()

1000
2020/d02/ex2/input Normal file

File diff suppressed because it is too large Load diff

25
2020/d03/ex1/ex1.py Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env python
import sys
from typing import List, Tuple
def solve(trees: List[str], delta: Tuple[int, int]) -> int:
x, y = 0, 0
sum = 0
while True:
x += delta[0]
y += delta[1]
if y >= len(trees):
break
sum += trees[y][x % len(trees[0])] == "#"
return sum
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input, (3, 1)))
if __name__ == "__main__":
main()

323
2020/d03/ex1/input Normal file
View file

@ -0,0 +1,323 @@
...............#.#.............
##..#....................#...##
......#..#.#.....#..#.#.##.....
.........#...#..............#.#
............#.......##.........
...#.....#.....#...#.....#..#..
..............#..##.#..#......#
.##.....#.....#......##.#......
.#..........###....#...##....#.
.....#....#.#.......#......##..
.#....#......#.......#........#
..#.#.......#..##.....##.......
...#.#....#.......#.......#...#
##.##...##..#......#.#.....#..#
.#.#.......#..#.#......#...#.#.
#.......##.......#...#.........
.....#......#.#.#.....#....##..
.#.#........#....#..#..#.......
...#....#..###.........#.....#.
........#........#........#....
..##..............#.....#.#..#.
.#...##.............#.#........
....#..#...........#.......#...
..#....#.....................#.
#.#..................##......##
.#.##....#......#........#.....
.........##.....#....#...##..#.
#..........#..#.#.............#
.........#...#.#.#.#..##..##...
#...#.....#..#..#....#...#.....
..##.....#..................#..
#..###.....#....#.......#..#...
...##.##..#............#......#
........###.........###......#.
#..##....#.........#.........#.
....#.....................#....
#..#..##..#..####.##..#.....##.
..#...#.#....#....##.....#.....
...#.#.........#.....#.#.......
....#................#..#...##.
....#..#..........#...#.#.##...
........#..##............#....#
...#......##..........#.##...#.
.......##......................
.......##..........#....#.#...#
......###.##..##..#....#...#..#
#.#...........##.....#........#
..#...........#..###....#.#.#..
........#...........#......##..
.........#...##.###...###..#...
.....#.....#..##.........##....
...##..............#.....#...##
.##....#.......###.....#.......
.#...........##.............##.
......#..#..##.##......#......#
........###........#......#.#..
#.#....#.....#........#......#.
.##..#.........##...##....#....
.....#.........#...##.....#....
.............#........###....#.
......#.......#.#........#.#...
..#....#.#...#....#...#.#...##.
#...#......##..##......#.##.###
...##.#....#...#....#.........#
...#..####.....##.#..#.#...##..
##.#..#....##......#......##...
###.........#.#..#.#.....#.....
...#........#..##...#.#.#..#.#.
...###..#.###.#...#............
....................###........
...........#...........#.......
#..............#.#.........###.
....................##.....#..#
#.#.....#.......#...#..........
.#...#......#....##...#...#....
.....#.##..................###.
.........#.#..#.#......#.......
.......#.....##..#.##.#........
..#..........#.###.....#....#..
......#.............#.#........
........##....#........#.......
...#.............#....#.#......
#........#..####.....#.....#.#.
.##......##...#........#..#.#..
....##....#...#...#..##...#.#..
#.##...###..#....##.#..........
....#.#...#.#...#..##.###...#..
#.....##..#..#....#.#.....##...
.#..#..........##.#.....##.....
.#..#........#.#.#.#...........
.#..#.....#...........#...#....
...#......##..........##..#....
...#..#....#.##...#..#.....###.
#.#....#.....##................
#..#......#.#.#.......#........
......#....#.#....#..##....#..#
.#.....#.#....###.##.........#.
.###..#.....#........#.#.......
.#...#......#..#.#......#.....#
#...............####...#.....#.
.......#..........##.#........#
#........##....##.....###..##..
#..#.....#..##.....#....#..#...
#.....#.......##......#.#.....#
#.##..#......##..#.............
##...#.....#........##.........
....#..##....#...#.......#.#...
....#...#...##..#....#..#...#..
..............#.#...#....###...
...#....#..##...##..#....##....
#.##.#..#..#......#.#.#.#...#..
.......#..#..##........#......#
##.#....#....##.#......##.#....
.#...#..............#........#.
.#.#....#.........#............
.#..#..###.............#....#..
#......#...#.#..##..#...#....#.
.......................#...#.#.
.............#..#...##.........
..#.#..#....#....#........#....
#......#.##..#...#.#...........
.....#....#...........##.#..#..
..#.#.....#..............#.#...
#.......#.....#................
#..............#...#....#...#..
...#...##..#..#............#...
......###.....................#
.........#.......##..#....#....
........#...#.##..#.##......#..
....###..#.#...#...#..#.#...###
##...#...##.#...#.#...#.#....#.
.........#...#.....###.........
...#........##..#.......##.....
.#.......##.........#.....##..#
.#..................#...#......
.##..#..#.#.....#.###..........
...#.....##..#.........#...#...
.#......#.#.......#.#..........
.........#.#...#..........#.#..
#..........#.##..#.##....#.....
.#.#....#.....#..##.....#...#..
..#........##...##..#..#....#..
#...........##....#..###....#..
...........##.........####...#.
..#........###...#.#.........#.
.#...............#.##.#.#...#..
.#.##..#.....#.#.....##..#.....
...#...#..#.##.##...#.......##.
..#...#...#......##.##.##...#..
##....#...#...#...............#
...##...........#......#..#.#..
#.........#......#.#.##.....#..
........#..#.........##........
..#.#....###.....##..#...#.....
.........#...#.......#.....##..
##.....................#...##..
.#.#..#......#.................
.....###..#......#..###..#.....
...#.....##.........#......#..#
......##.....#...#........#.#..
..#.#...#......#...#.##.##.....
...#..........#...#.......#..##
.###........#........##........
..#.#.#..........#.#...##......
.........#........#......###..#
....##..#.........#...........#
..####..#............##.......#
.....##.#..##.........#...#.#..
...#.........#.....#.....#.....
.......#...#..#...##.........#.
...#...#..#...#....#..#........
#............##.##...#.........
.#.#.....#.......####.....#....
..............#......#.#.......
..............#...........#...#
#...#........###....#.#....#.#.
##.#..#..#......#......#.#.#...
.#..#.....#..#.#..#.#.......##.
......##.#...#...#......#...#..
#...........##....#.#..........
....#.......###.#...#..........
.......................#.....#.
........#...#..#...#.#.#.#.#...
.#.#...........#......##...#...
.........................#.....
.................#.##.#...##...
...#...##.....#.....##....#.#..
...#...#...................#...
...#..#..#...#...#....#........
#....#...#.....#...............
.......#...........#...#.......
....#....#.....##.......#......
.......#..........##...........
.#.#........#..##....#......#..
.....#.......#.#.........#...#.
.#..####.#.#...............#..#
.....###..#..#..........#.#..##
..#.......#...#.....##..#..#.#.
#....#......#..................
........#.##.#....#...........#
....#.#....##..#.#.....##......
...#..#.......#....#.....#.#.#.
#...#......#.....#.#..........#
....#....#...............#.....
..###......................###.
.##....#..#.......###.....#..#.
..###............#........#.##.
.#........#......#.....#..#....
....#..##...#...#.###.......#.#
.......#.##...........#.#..#...
.....#...##....................
....#....#...##......#.........
..#............##....###.#...#.
.#........#...............#....
#..#.#.##.........#..##....##..
#.#....#..#.##....##...#.#.....
.....#.....##....#.#........#..
#..#...#...#....#....#.........
...#........#..#.#.....##......
..#...#...#................##..
#........#.#.##.......#.#...#..
#......#..####.##.....#.#..#.#.
............#..#.#....#......##
..#.....##....#...#.#..........
...#...#.........#...#.#.......
.###..#.......##.##.....#.#.#..
...#....#...............##.#...
....##..#..#..#.#......##.....#
#.#..............##...##...####
.....#.##...#.#...............#
.##.....#.........#.......#.#.#
#.#..#.....#.......#.......#..#
...#.#.....#.....#......#......
.......#....#..#.#..........#..
......#......#.##...#..........
.....#.......###...#...#.#.....
#..#.#.........#.....#.##....#.
..#.#.........#..#..#..#.....#.
.#..##..#..#....#......#.##..#.
...##......###.....#.##.##.....
.#.....#...#..#...#............
##..##..#.##....#..#...........
...#..##..#..#.............#.##
...............##............#.
..#.....##........##.#...#....#
.#.#...#.#.#..#.#.....#....#...
.#....#...............#..#.....
....#.##..#....#......#...###..
#................###...#.#.....
...#...#......##..#.#....#.....
.#....#....#.#...##............
....#...##..#..#........#.##...
..##.....#..#..##..............
..#..##..#.#..##....#....#....#
...##.............#............
#....#....#.#........#.....##.#
.....#..#.#.....####...###.....
................#......#.......
.....#.#.#.#.#....#..#........#
.##.#...#.#.......##....#....#.
.....#........#................
..#.....#..#...#..#...........#
.#.....#...##.....##..#.#....##
......#.......#..#......##.#...
#.#..........#.##.#........#...
...#..#.............#..........
#..#..#..........#..##.#.......
.#..#...............####..#....
.......#.....#......#.....#.#..
.#...............#...#.........
.#..#..........#..#.#..##..#..#
......##..#.....#..#......###..
..........#...#..#.......#.....
.#.#.#..#.....#.##.#...#..#....
........#.......#.....#.#......
......#.....##.....#....##.#...
...............#......#.......#
..#.#...#.....#.#...##......#..
#.#.........#.#...#........####
#..........##..#..#........##..
.............#..#.......##.#..#
..#........#.#....#........#.#.
.#......####..#..#.............
............###.......#.#..#...
#.##......##...#...#.........#.
....##.#.#.#......#....#..#...#
.#..#.#....#...#.........#.....
#...#.....##............#...#..
#.#...#..#.................#...
............#.#..#.....#.#.#..#
...................#....#.##...
.....#...#.#....#....#.#......#
.......##.#.#......##..........
.#..#...##.#...#..#......#.....
......#.#..#..###..##..##......
.#.#.#.#.....#...###.....#..#..
.#....#.....#.......#.......#..
..........##.........####......
.#.#.............#..#.#...#....
........#........##...#.#....#.
........#......................
..#.#....#...............#...##
.......#.#...#..#.....##......#
.#...#....#..........##........
.#.........#.#............##...
.....#......##...#.......#..#..
#.#..#.............#...#...#...
......#.......#............#...
...........##....#......##.....
.#.#..#.....................#..
##..##.....###..##.#...........
...##......##....#...##.....#..
#...#.##.............#.........
......#..#.........###.#......#
#.#.....#.....................#
....#####.....##........#.#..#.
...........##..##.###..........
..........##.....#........#...#
.......#..#......#.....##..##.#
.....##.#........#.........#...
......##......................#
.#.......#.#.#............#..#.
.....##.#.......#.#........#...

33
2020/d03/ex2/ex2.py Executable file
View file

@ -0,0 +1,33 @@
#!/usr/bin/env python
import sys
from math import prod
from typing import List, Tuple
def solve(trees: List[str], delta: Tuple[int, int]) -> int:
x, y = 0, 0
sum = 0
while True:
x += delta[0]
y += delta[1]
if y >= len(trees):
break
sum += trees[y][x % len(trees[0])] == "#"
return sum
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
deltas = [
(1, 1),
(3, 1),
(5, 1),
(7, 1),
(1, 2),
]
print(prod(solve(input, delt) for delt in deltas))
if __name__ == "__main__":
main()

323
2020/d03/ex2/input Normal file
View file

@ -0,0 +1,323 @@
...............#.#.............
##..#....................#...##
......#..#.#.....#..#.#.##.....
.........#...#..............#.#
............#.......##.........
...#.....#.....#...#.....#..#..
..............#..##.#..#......#
.##.....#.....#......##.#......
.#..........###....#...##....#.
.....#....#.#.......#......##..
.#....#......#.......#........#
..#.#.......#..##.....##.......
...#.#....#.......#.......#...#
##.##...##..#......#.#.....#..#
.#.#.......#..#.#......#...#.#.
#.......##.......#...#.........
.....#......#.#.#.....#....##..
.#.#........#....#..#..#.......
...#....#..###.........#.....#.
........#........#........#....
..##..............#.....#.#..#.
.#...##.............#.#........
....#..#...........#.......#...
..#....#.....................#.
#.#..................##......##
.#.##....#......#........#.....
.........##.....#....#...##..#.
#..........#..#.#.............#
.........#...#.#.#.#..##..##...
#...#.....#..#..#....#...#.....
..##.....#..................#..
#..###.....#....#.......#..#...
...##.##..#............#......#
........###.........###......#.
#..##....#.........#.........#.
....#.....................#....
#..#..##..#..####.##..#.....##.
..#...#.#....#....##.....#.....
...#.#.........#.....#.#.......
....#................#..#...##.
....#..#..........#...#.#.##...
........#..##............#....#
...#......##..........#.##...#.
.......##......................
.......##..........#....#.#...#
......###.##..##..#....#...#..#
#.#...........##.....#........#
..#...........#..###....#.#.#..
........#...........#......##..
.........#...##.###...###..#...
.....#.....#..##.........##....
...##..............#.....#...##
.##....#.......###.....#.......
.#...........##.............##.
......#..#..##.##......#......#
........###........#......#.#..
#.#....#.....#........#......#.
.##..#.........##...##....#....
.....#.........#...##.....#....
.............#........###....#.
......#.......#.#........#.#...
..#....#.#...#....#...#.#...##.
#...#......##..##......#.##.###
...##.#....#...#....#.........#
...#..####.....##.#..#.#...##..
##.#..#....##......#......##...
###.........#.#..#.#.....#.....
...#........#..##...#.#.#..#.#.
...###..#.###.#...#............
....................###........
...........#...........#.......
#..............#.#.........###.
....................##.....#..#
#.#.....#.......#...#..........
.#...#......#....##...#...#....
.....#.##..................###.
.........#.#..#.#......#.......
.......#.....##..#.##.#........
..#..........#.###.....#....#..
......#.............#.#........
........##....#........#.......
...#.............#....#.#......
#........#..####.....#.....#.#.
.##......##...#........#..#.#..
....##....#...#...#..##...#.#..
#.##...###..#....##.#..........
....#.#...#.#...#..##.###...#..
#.....##..#..#....#.#.....##...
.#..#..........##.#.....##.....
.#..#........#.#.#.#...........
.#..#.....#...........#...#....
...#......##..........##..#....
...#..#....#.##...#..#.....###.
#.#....#.....##................
#..#......#.#.#.......#........
......#....#.#....#..##....#..#
.#.....#.#....###.##.........#.
.###..#.....#........#.#.......
.#...#......#..#.#......#.....#
#...............####...#.....#.
.......#..........##.#........#
#........##....##.....###..##..
#..#.....#..##.....#....#..#...
#.....#.......##......#.#.....#
#.##..#......##..#.............
##...#.....#........##.........
....#..##....#...#.......#.#...
....#...#...##..#....#..#...#..
..............#.#...#....###...
...#....#..##...##..#....##....
#.##.#..#..#......#.#.#.#...#..
.......#..#..##........#......#
##.#....#....##.#......##.#....
.#...#..............#........#.
.#.#....#.........#............
.#..#..###.............#....#..
#......#...#.#..##..#...#....#.
.......................#...#.#.
.............#..#...##.........
..#.#..#....#....#........#....
#......#.##..#...#.#...........
.....#....#...........##.#..#..
..#.#.....#..............#.#...
#.......#.....#................
#..............#...#....#...#..
...#...##..#..#............#...
......###.....................#
.........#.......##..#....#....
........#...#.##..#.##......#..
....###..#.#...#...#..#.#...###
##...#...##.#...#.#...#.#....#.
.........#...#.....###.........
...#........##..#.......##.....
.#.......##.........#.....##..#
.#..................#...#......
.##..#..#.#.....#.###..........
...#.....##..#.........#...#...
.#......#.#.......#.#..........
.........#.#...#..........#.#..
#..........#.##..#.##....#.....
.#.#....#.....#..##.....#...#..
..#........##...##..#..#....#..
#...........##....#..###....#..
...........##.........####...#.
..#........###...#.#.........#.
.#...............#.##.#.#...#..
.#.##..#.....#.#.....##..#.....
...#...#..#.##.##...#.......##.
..#...#...#......##.##.##...#..
##....#...#...#...............#
...##...........#......#..#.#..
#.........#......#.#.##.....#..
........#..#.........##........
..#.#....###.....##..#...#.....
.........#...#.......#.....##..
##.....................#...##..
.#.#..#......#.................
.....###..#......#..###..#.....
...#.....##.........#......#..#
......##.....#...#........#.#..
..#.#...#......#...#.##.##.....
...#..........#...#.......#..##
.###........#........##........
..#.#.#..........#.#...##......
.........#........#......###..#
....##..#.........#...........#
..####..#............##.......#
.....##.#..##.........#...#.#..
...#.........#.....#.....#.....
.......#...#..#...##.........#.
...#...#..#...#....#..#........
#............##.##...#.........
.#.#.....#.......####.....#....
..............#......#.#.......
..............#...........#...#
#...#........###....#.#....#.#.
##.#..#..#......#......#.#.#...
.#..#.....#..#.#..#.#.......##.
......##.#...#...#......#...#..
#...........##....#.#..........
....#.......###.#...#..........
.......................#.....#.
........#...#..#...#.#.#.#.#...
.#.#...........#......##...#...
.........................#.....
.................#.##.#...##...
...#...##.....#.....##....#.#..
...#...#...................#...
...#..#..#...#...#....#........
#....#...#.....#...............
.......#...........#...#.......
....#....#.....##.......#......
.......#..........##...........
.#.#........#..##....#......#..
.....#.......#.#.........#...#.
.#..####.#.#...............#..#
.....###..#..#..........#.#..##
..#.......#...#.....##..#..#.#.
#....#......#..................
........#.##.#....#...........#
....#.#....##..#.#.....##......
...#..#.......#....#.....#.#.#.
#...#......#.....#.#..........#
....#....#...............#.....
..###......................###.
.##....#..#.......###.....#..#.
..###............#........#.##.
.#........#......#.....#..#....
....#..##...#...#.###.......#.#
.......#.##...........#.#..#...
.....#...##....................
....#....#...##......#.........
..#............##....###.#...#.
.#........#...............#....
#..#.#.##.........#..##....##..
#.#....#..#.##....##...#.#.....
.....#.....##....#.#........#..
#..#...#...#....#....#.........
...#........#..#.#.....##......
..#...#...#................##..
#........#.#.##.......#.#...#..
#......#..####.##.....#.#..#.#.
............#..#.#....#......##
..#.....##....#...#.#..........
...#...#.........#...#.#.......
.###..#.......##.##.....#.#.#..
...#....#...............##.#...
....##..#..#..#.#......##.....#
#.#..............##...##...####
.....#.##...#.#...............#
.##.....#.........#.......#.#.#
#.#..#.....#.......#.......#..#
...#.#.....#.....#......#......
.......#....#..#.#..........#..
......#......#.##...#..........
.....#.......###...#...#.#.....
#..#.#.........#.....#.##....#.
..#.#.........#..#..#..#.....#.
.#..##..#..#....#......#.##..#.
...##......###.....#.##.##.....
.#.....#...#..#...#............
##..##..#.##....#..#...........
...#..##..#..#.............#.##
...............##............#.
..#.....##........##.#...#....#
.#.#...#.#.#..#.#.....#....#...
.#....#...............#..#.....
....#.##..#....#......#...###..
#................###...#.#.....
...#...#......##..#.#....#.....
.#....#....#.#...##............
....#...##..#..#........#.##...
..##.....#..#..##..............
..#..##..#.#..##....#....#....#
...##.............#............
#....#....#.#........#.....##.#
.....#..#.#.....####...###.....
................#......#.......
.....#.#.#.#.#....#..#........#
.##.#...#.#.......##....#....#.
.....#........#................
..#.....#..#...#..#...........#
.#.....#...##.....##..#.#....##
......#.......#..#......##.#...
#.#..........#.##.#........#...
...#..#.............#..........
#..#..#..........#..##.#.......
.#..#...............####..#....
.......#.....#......#.....#.#..
.#...............#...#.........
.#..#..........#..#.#..##..#..#
......##..#.....#..#......###..
..........#...#..#.......#.....
.#.#.#..#.....#.##.#...#..#....
........#.......#.....#.#......
......#.....##.....#....##.#...
...............#......#.......#
..#.#...#.....#.#...##......#..
#.#.........#.#...#........####
#..........##..#..#........##..
.............#..#.......##.#..#
..#........#.#....#........#.#.
.#......####..#..#.............
............###.......#.#..#...
#.##......##...#...#.........#.
....##.#.#.#......#....#..#...#
.#..#.#....#...#.........#.....
#...#.....##............#...#..
#.#...#..#.................#...
............#.#..#.....#.#.#..#
...................#....#.##...
.....#...#.#....#....#.#......#
.......##.#.#......##..........
.#..#...##.#...#..#......#.....
......#.#..#..###..##..##......
.#.#.#.#.....#...###.....#..#..
.#....#.....#.......#.......#..
..........##.........####......
.#.#.............#..#.#...#....
........#........##...#.#....#.
........#......................
..#.#....#...............#...##
.......#.#...#..#.....##......#
.#...#....#..........##........
.#.........#.#............##...
.....#......##...#.......#..#..
#.#..#.............#...#...#...
......#.......#............#...
...........##....#......##.....
.#.#..#.....................#..
##..##.....###..##.#...........
...##......##....#...##.....#..
#...#.##.............#.........
......#..#.........###.#......#
#.#.....#.....................#
....#####.....##........#.#..#.
...........##..##.###..........
..........##.....#........#...#
.......#..#......#.....##..##.#
.....##.#........#.........#...
......##......................#
.#.......#.#.#............#..#.
.....##.#.......#.#........#...

38
2020/d04/ex1/ex1.py Executable file
View file

@ -0,0 +1,38 @@
#!/usr/bin/env python
import sys
from typing import List
def validate(passport: List[str]) -> int:
fields = [
"byr",
"iyr",
"eyr",
"hgt",
"hcl",
"ecl",
"pid",
]
for field in fields:
if field not in passport:
return False
return True
def solve(passport_fields: List[List[str]]) -> int:
return sum(validate(passport) for passport in passport_fields)
def main() -> None:
passports: List[List[str]] = [[]]
for line in sys.stdin:
if line == "\n" or line == "":
passports.append([])
continue
passports[-1] += [s.split(":")[0] for s in line.split(" ")]
print(solve(passports))
if __name__ == "__main__":
main()

1069
2020/d04/ex1/input Normal file

File diff suppressed because it is too large Load diff

109
2020/d04/ex2/ex2.py Executable file
View file

@ -0,0 +1,109 @@
#!/usr/bin/env python
import re
import sys
from typing import List, Tuple
Field = Tuple[str, ...]
def validate_byr(field: str) -> bool:
pattern = "^[0-9]{4}$"
if not re.fullmatch(pattern, field):
return False
val = int(field)
return 1920 <= val <= 2002
def validate_iyr(field: str) -> bool:
pattern = "^[0-9]{4}$"
if not re.fullmatch(pattern, field):
return False
val = int(field)
return 2010 <= val <= 2020
def validate_eyr(field: str) -> bool:
pattern = "^[0-9]{4}$"
if not re.fullmatch(pattern, field):
return False
val = int(field)
return 2020 <= val <= 2030
def validate_hgt(field: str) -> bool:
pattern = "^[0-9]+(cm|in)$"
if not re.fullmatch(pattern, field):
return False
val = int(field[:-2])
if "cm" in field:
return 150 <= val <= 193
return 59 <= val <= 76
def validate_hcl(field: str) -> bool:
pattern = "^#[a-f0-9]{6}$"
if not re.fullmatch(pattern, field):
return False
return True
def validate_ecl(field: str) -> bool:
return field in {
"amb",
"blu",
"brn",
"gry",
"grn",
"hzl",
"oth",
}
def validate_pid(field: str) -> bool:
pattern = "^[0-9]{9}$"
if not re.fullmatch(pattern, field):
return False
return True
def validate(passport: List[Field]) -> int:
fields = {
"byr": validate_byr,
"iyr": validate_iyr,
"eyr": validate_eyr,
"hgt": validate_hgt,
"hcl": validate_hcl,
"ecl": validate_ecl,
"pid": validate_pid,
}
tot = 0
for field in passport:
if len(field) != 2:
continue
if field[0] not in fields:
if field[0] == "cid":
continue
return False
if not fields[field[0]](field[1].strip()):
return False
tot += 1
return tot == len(fields)
def solve(passport_fields: List[List[Field]]) -> int:
return sum(validate(passport) for passport in passport_fields)
def main() -> None:
passports: List[List[Field]] = [[]]
for line in sys.stdin:
if line == "\n" or line == "":
passports.append([])
continue
passports[-1] += [tuple(s.split(":")) for s in line.split(" ") if s]
print(solve(passports))
if __name__ == "__main__":
main()

1069
2020/d04/ex2/input Normal file

File diff suppressed because it is too large Load diff

35
2020/d05/ex1/ex1.py Executable file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env python
import sys
from typing import List
def seat_id(boarding_pass: str) -> int:
min_x = 0
max_x = 128
min_y = 0
max_y = 8
for char in boarding_pass:
if char == "F":
max_x = (min_x + max_x) // 2
elif char == "B":
min_x = (min_x + max_x) // 2
elif char == "L":
max_y = (min_y + max_y) // 2
elif char == "R":
min_y = (min_y + max_y) // 2
return min_x * 8 + min_y
def solve(passes: List[str]) -> int:
return max(seat_id(p) for p in passes)
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

781
2020/d05/ex1/input Normal file
View file

@ -0,0 +1,781 @@
FBFFBFFRLL
BFFFFBBRLR
FFFBBBBRLR
FBFFFBFLRL
FFBFBFFRRL
FFBBBBFRRR
FBFFBFBLRR
FFBBFBFRRL
FFFFBBFRRL
BFBBBBBLLL
FFBFBFBLLL
FFBFFFBLLL
FBBBFBFRLL
BBFFFBFRRR
FFFBFBBLLR
FBFBFBFRRR
BBFFBFBRLL
FBFBBBBLRL
FBFFFFFLLL
BFFFFFFRLL
BFFFBFBLRL
BFBBBFBRRL
BFFFBFFRRL
FBFFFFFRRR
FFBBBBBLLR
BFBBFFBLRL
FBBFBBBRLR
BFBFBFFRLL
BFBFBFBRLL
BFFBFBFLLL
FFBBFFBLRL
FBBFFBFLRR
FBBBFBBRRR
BFBFFBFRLR
BFBBBFBLLL
FFBFBBBLRR
BFBFFBFLLL
FBFBFBBLLL
BFBBBFBLRL
FBFBFBFLRL
FFBFFBFRRL
FBBFFBFLLL
BFBBBBBLRL
FBBBBBFRLR
BFFFBBFRLL
FBBBBFFLLR
FBBBBBFRLL
BFBBBFFRLR
BFBBBFBRLL
BFFFBFFLLL
FFFBFBFLRL
BFFBBFFLRL
BBFFFBFRLL
BFBBFFBRLR
BFBFBFBRRL
BBFFFBFRRL
FBBFBBBLRR
FFBFBBBLLL
BFFFBFBRLR
FFBBFBBLLL
FBFBBFBLLL
BFBBFBFLLR
FFBFBBBRRL
FFBFFFFLRL
FFFBBFFLRR
FBBBBBFRRR
FFFFBBBRLL
BFBFBBBRRR
BBFFBFBRRL
FBFBBFFRLR
FBBFFBFRRR
BBFFBFBRRR
FBFBBFBLRR
FBBFFBBLRR
FBBBBFFRLL
BFBFFFBRLR
FBFBBFBRRL
FFBFBBFRRR
FBFBFFFRLL
BFBBFFBLLR
FBFFFFBRLR
BFBBBFFRLL
FFBBFFBRLR
FFFBBFBRLL
FBBBBBBLRR
FBFFBBBLRR
BFFFFBFLRL
BBFFFFFLRR
BFFBFFBLLR
FFBBBFFRLL
BFBFBFBRLR
FBBFBFBLRR
FBFBBBFRLR
FBFFBBBRRR
FBBFFBFRLL
FBBBFFFRLR
BFBBBBFLLR
BFFFBFFLLR
FFBFFFBRRR
FBFFFBFLLR
FFFFBBBLLR
BFBFFFBRLL
BFFBBFBLRL
BFFBFBFLLR
FFBFFBFRLR
BFBFFFBRRL
FFBBFBFLLL
BFBBBBBRLR
BFBFBFBLRR
FBFFBFBLLR
FBFBFBBRRL
BFBFBBBLLL
FFBBFBBLRL
FBFFFBFRRL
BFBBFFFLRR
BFBFBBFRRR
FBFFFFBLRL
BBFFBBFRRR
FFBFFBBRLR
FBBFBFBLRL
BFBFFFBRRR
FFFBBBFLRL
BFFBFFBRLL
FBFBFFBLRR
FFBFBBFLLL
FFBBBFFLRL
FFBBFFFRLR
BBFFBFBLRL
FFFFBBFRLR
FFFBFFBLRR
BFFBBBFLLR
BFFFBBBRRL
FBBFBFBRLL
BFFBFFFRRR
BBFFFFFLRL
BBFFFBBRLL
BFFFBBBRRR
BFFFBBBLRL
BBFFBFFRRR
BFFBFFBLRL
FBBBBFBRLR
FFFBFBFRRL
BFFBBBBRRL
FBBBBBFLRR
FBFBBBBLLR
FBBBBFBLRR
FFFBFFBRLL
FFBBBBFLLR
FFBBBBBRRL
FBBFFFFLLL
FBFFBBBRLL
FBFBFFBLLR
FBBBBBFRRL
BFFFBFBLLL
FFFBFFFLRL
FFFFBBFRLL
BFBBFFFRLR
BFFFBBBRLR
FFBBBFBLLR
BFFFBFBRRR
BFFBFBBLRL
FFBFBFBLRR
FBBBBFBRRR
FFBFBFFLLR
BBFFFFFLLR
FBBBFBFRRR
BBFFFFBRRL
FBFBFBBLRL
BFBBBFFLLR
BBFFBBFLRL
BFBFFBBRLR
FBFBBBFRRL
FBBBFFBRLL
BBFFFFBLLR
FFBBFBBLRR
FBBBBBBRLR
FFFFBBBRRL
FBFBBBBRLR
BBFFBFFRRL
FBBBFFBLRL
FFBBBFBLRR
BFBFBBBRLL
FBFFFBBLRL
FBFBBBBRLL
BBFFFBBLLL
BFBBFFBLLL
BFFBBBBRRR
FBFBFFBLLL
FBFBFBFRRL
FBBFFFBLLL
BBFFFBFRLR
FBBBBFFLRR
FBFFFBBRLL
FFBBFBFRRR
FBFFFFFLRR
BFBFFBBLRR
FFBFBFFRRR
BFBFFBBRLL
FBBFFFFRRL
BFFBBFBRLL
BFFFFFBLLR
FBFBBFBLLR
BFFBBFBRLR
BFFBFBFRRR
FFBFBBFRLL
FFFBBBBLRR
BFFFBFBLLR
FBBBBFBLRL
FBFBBFFLRL
FFFBFFFRLL
BFFFFBBRRL
FBBFFFBRRR
FBBFBFFLLR
BFBBBBBRRR
BFFBFBFRLL
FFBFBBFRRL
BFBFBFBLLR
FFBFBBFLLR
FFBFFFFLRR
FBBBFBBRRL
BFFBFBFRLR
BFFBFFBRRL
BFBBBFBRLR
BBFFFFBLRL
FBBBFFBRRL
FBFFFBBRRL
FBBBBBBLLL
FFFBFFBLLL
BFBBFBFRLL
FBFBFFBRLR
FFFFBBBRRR
BBFFFBBRLR
BFBBBBFRLR
FBFFBBFLRR
BFFFBFFRLR
FFFBBBBLLR
FBFFFFBLRR
FBFBFBBRLL
FBFFBBBRLR
BFFFFFFLRR
FBFFFFFRLL
FFBFBFFRLL
FFFBBFFRLR
FBBFBFFRRL
FBBBBBBRRR
BFBFBBBLRL
BBFFFFBRRR
FFBFFBBLRL
FBBBBBBLLR
FFBBFFFLRL
FBBBFBBLRR
FFBBBBBRLR
BFBFFFFLLR
BFFBBBBRLL
BFBFBFFLRL
FBBFFFBLRL
BFBFBBBRRL
BFBFBFBLRL
BFBBFBFLRR
BFFFFBFRLR
BFFFBFBRLL
FBFBFBFLLL
FBFFBFFLRL
BFFFFFFRRL
FBBFBFFRLR
FFBBBFFLLR
FBBBBFFLRL
FBBBFBBRLR
BFBBBFFLRL
FBFFBBBLRL
BFFFFBFRRL
BFFFBFFLRR
FFBFBBFLRL
BFBFFFBLRL
BFFFFFBLLL
FBFFBFBLLL
FBFBBBBRRL
FBBFFBBRLR
BFFFBBFRRL
BFBBFBBRLR
FFFBFBBLRR
FFFBFBFRLR
FBFBFBFRLR
BFBFBBBRLR
BFFFFBBLLL
BFFBBFBRRR
BFFBBBFLLL
FFBBBFFRRL
BFBBBFBLLR
FBBFFBBLLR
FBBFBBFLRL
BFFFFFBRRR
FBBBFBBRLL
FBFBFFBRRR
BFFBBBFRRR
FBBBBBBLRL
FFBBBFFLRR
BFFBBBFRLL
BBFFBBFRLL
FBBFBBFRLR
BFBFBFFRRR
BFBFBBFLRL
BFFFFBFRLL
FFBBFBFLLR
BFFBFBBLRR
FBFFBBBRRL
FBBFBBFRLL
FBFFFBBLLR
FFFBBBBRRR
FFFFBBBLRL
FFBBFFFRRL
BFFBBFFRRL
BFFFBBFLRL
BFFFFBBLRR
BBFFBBBLRR
BFBFFFFLRR
FBFBBBBLLL
BBFFFBBLRR
FFFBFBFLRR
FBBFFFFLRL
FFBBBBFRLL
FBFFBFBLRL
BFBBFBBLLL
FBBFBBFLLL
FFBFFBBRLL
BFBFFFFRLR
FBFFBBFRRR
FFFBBFFRRR
FFFBFFBRLR
FBBBBBFLLL
FBBBFFFLRL
FFBBFFFLRR
FFFBBBBRRL
BFBFBBFRLL
BFBFFBBRRL
FBBFBBFRRL
BFBFBBFLLR
BBFFBBBRRR
BFFFBBFRLR
FFFBBBFRLR
BFFBFFFRLL
BFBFFFFRRL
FFBBFFFLLL
FBFBBBBLRR
FBFBFFFLRR
BBFFBFFLRR
FBBBFBBLRL
BFBFBFBLLL
FBFBFFFLLR
BFFBBFBLRR
FBBFFFBRRL
BFFBBFFRRR
FBBFBBBRRL
BFFFFBBLLR
FFBBBBFLLL
BFFBFFBRRR
BFFFFBFRRR
FFFBBBFRRR
FBFBFFFRLR
FBBBFBFLLR
FFBBFFBRLL
FBFBFFFLLL
BFFBFBFRRL
BFBFFBFRRL
BFBBBBFLLL
FBBBFBFRRL
FFBFBFFLLL
BFBBFFFRRL
FFBBFFBLLR
BFFBBBBRLR
FFBBBBBLRR
BFFBFFFRRL
BFFBFBBRLL
FBBBFBFRLR
FBBFFFFLRR
BFFFBBFLLR
FFFBBFBRRL
FFBBFFBLRR
FBBFFFBRLR
BFBBBBBRLL
BBFFFFFRRL
FFBFFBBRRL
BFBFFBFLLR
FBFBBBFLLL
FBFFFFFRRL
BFFFBFBLRR
FBFFFFBLLR
FBBFBFBRRR
FBBBFFFLLR
BBFFBFBLRR
BBFFFBFLLL
FBFFFBFRLR
BFFFBFFLRL
BBFFBFFLRL
BFFFFFFLLR
BBFFBBBLLL
FFBFBBBLLR
FBBFBBBLRL
BFBBFBBLRR
FFBFBFBLLR
FFBFBFBRRL
BFBBFBBRRL
BFFBFFFLLR
FFBBFFBRRL
BBFFBBBRRL
FFFBBFBRLR
BFBBFBFRRR
BFFFFFFRRR
FBBBFFBLLL
BFBFFFFLLL
BBFFBFBLLR
BFBFBBFRLR
FFBFBBBRRR
BFFFBBFLLL
FBFFBBFRLL
FFBBFBFRLL
BFBFBBBLLR
FBBFBFBLLL
BBFFFFBRLL
BBFFBFBLLL
BFFBFFBLRR
BFFBBFBLLL
FFBFFFBLRR
FBBFFBFRRL
FBBBBFBLLL
FFBFFBBLLR
BFFBBBFLRR
FBFBFFBRLL
FFBFFFBRLL
FFBFFBFLLL
FBFBBFBLRL
FBBFBFFRRR
BFBFBFFLLR
FBBFFFBLLR
BFBBBBFRRR
FBBFBBFRRR
BBFFBFFRLR
FBFBBBFRLL
FBBFBBBLLR
BFFFFFFLRL
BFBFFBBRRR
BFFFBFFRLL
BFBBFBFLRL
FFBFFFFRRR
BFFBBFFRLR
FBBBBBFLLR
FBFBFFBLRL
FFFBBFBLLR
FBBFBFBLLR
FFFBFFBRRR
FBFFFFFRLR
FBFBBFBRLR
FBBBFBFLRR
FBFBBBFLRL
BFFBFFFLRL
FFBBBFFRRR
FFBBBBBLLL
FBFFBBFLLR
FFBFBFFLRR
FFFBBBFLRR
BFBFBBFLLL
BBFFBFFLLR
FFBBFBBRLL
FBBFFBBLLL
FBFFBFBRLL
BFBFBFFLRR
FBBBFFBRLR
FFBFFBFRLL
FFFFBBBLLL
FFBFFBBRRR
FBBBBFBRLL
BFFFFBBRRR
FFBBFFFRLL
FFBFBFBRLL
BBFFFFBLLL
FFBBBFBRRL
BFFFFBBLRL
FBBBFBBLLR
FBBBFBBLLL
FFBFBFBLRL
FBBBBFFRRR
FBBFFFFRLR
FFBFFFBRLR
BFBFBFBRRR
FFFBFBBRLL
FBBBFFBRRR
FBBFBFFRLL
BFFBFBFLRR
BFBBBFFRRL
BFFBBFBLLR
FFBBBFBRLL
FBFBFBBLRR
BFBBFFFLRL
BFBFBBFLRR
BFBBBFFRRR
FBBBFFFRRL
FBFBFBFLLR
FBBFFFFLLR
FFBFBBFRLR
FFFBFBBLRL
BBFFFBBLLR
BFFBBBFRLR
FFFFBBBRLR
BBFFBBFRLR
FBFFFFBRLL
FBFBFFFRRR
FBFFFBBLLL
BFBBBBFRLL
FBFBFFBRRL
FFFBFFFRLR
BFBBFBFRRL
FBFFBFFLRR
FBFFFBBLRR
FFBFBBBRLR
FBBFBFFLRR
FBFFFBBRRR
FFBFBBBRLL
FFBBBBBRRR
BFFBBFFLLL
BFBBBBBRRL
BBFFBBBRLL
FBFFFFFLRL
BFFBBFFLRR
FBFFBBFLRL
BFBFFBFRRR
FBFBBFBRLL
BFFFBFBRRL
FBBFFBFLLR
BFFFFFFLLL
FBFBFBFRLL
FBBBBFFRRL
BFBFFBBLLR
FBBFBFBRRL
FFFBFFFLLR
FFBBBBBLRL
FFBFFBBLRR
FFFBFBFRRR
BFBBFBBRLL
BFBBBFBLRR
FFBBBBFLRR
FBBBFFBLLR
BBFFBBBLLR
FBFBBFFRRL
FBBBBBFLRL
FFFBBFFRRL
BFFBBBBLRR
FFFFBBBLRR
FFFFBBFLRR
FBFFFBFLLL
FBFBFBBLLR
BFFBBBBLLL
FFBFFFFRLR
BFBBFFBLRR
FFBBFBFLRL
BFBFBFFLLL
BFFBFBBLLR
BFBBFBBLRL
FFBBBBFLRL
FBBBFFFLLL
FFFBFFBRRL
BFFFFBBRLL
BFFFBBBRLL
BFFBFFFLRR
FFBFBFBRRR
BBFFBBFLLR
FFBBFBBLLR
FFBFFBFRRR
FFBBBFFRLR
BFFBBBBLLR
FFFBFFFLRR
FBFFFFFLLR
FBFFBBBLLL
BBFFBBFLLL
FFBBFBFLRR
BFFBFBFLRL
FBFBBBFRRR
BFBBFBBLLR
FBFFFFBRRL
FFFBBFBLRR
BBFFFFBLRR
BFBBBBFRRL
FFBBBFBLLL
BFBBFBFRLR
BFBBFFBRRL
BFBFBFFRRL
FBBFFBBLRL
FFFBFFBLRL
BFFBBFFRLL
FBBBFFFRLL
FBBFBBFLLR
FFBFFFFLLR
FBBBFBFLRL
BFFFBBBLLR
FBFBBBBRRR
FBBFBFBRLR
FFFBFBFLLR
FFFFBBFRRR
FFFBBFFLRL
BFBFFBFRLL
FFFBFFBLLR
FBBFFFBRLL
FFBBBFBRRR
FFBBFBBRLR
BBFFFFFRRR
FFBFFFFRLL
FBBFFBBRRL
BBFFFBFLRR
FBBFFFFRRR
FFBFFFBRRL
BFBBFBFLLL
BFFFFBFLRR
BBFFFFFLLL
FFBBFBBRRL
FFBFBFFLRL
FBFFBBFRRL
BBFFBFBRLR
BBFFBBFLRR
FBFFBFBRRR
FBBFBBFLRR
FBFFFBFRLL
BFBFFFFLRL
FFFBBFBRRR
BFBBBBBLLR
FBBFFBBRRR
FFBBBFFLLL
FBBBBFBLLR
BBFFFFFRLL
FFBBBBFRLR
FBFBFBBRRR
FBFFBFFLLL
FBFFBBBLLR
FBBBBFBRRL
BFBFBFFRLR
FBBFBBBRLL
BFBBFFFRLL
FBBBFBFLLL
FFBFFFFRRL
FBFBBFFRRR
FBFFFFBLLL
FBBBBBBRLL
BFFBFBBRRR
BBFFBBFRRL
FBBFBFFLRL
FBFFFFBRRR
FBBFFFFRLL
FFFBFFFRRR
FBFFBBFLLL
BFFFFBFLLL
BFFFFBFLLR
FFBFFBFLLR
FFBFFBFLRR
BFFBBBBLRL
FFBBFFBLLL
FBBFBBBLLL
FBFBBBFLLR
BFFBBBFLRL
BFBBFFBRLL
FBFFBFFRRR
FFBFFFBLRL
FFFBBBFRRL
FFBFBBFLRR
FFFBBBBLRL
FFFBBFFLLL
FFFBFBBRRR
FBBFBFFLLL
BFFFBBBLLL
BFFBFFFRLR
FFFBBBBLLL
BFFFFFBRRL
FFBBFFFLLR
BFBBFFFRRR
BFBFFBFLRR
FFFBBBFLLR
FBFBBBFLRR
BBFFBBBRLR
FBFBBFFLRR
FFBBBFBLRL
FFFBBBFRLL
BFFBFFBRLR
BBFFFBBRRR
BFBBBBFLRL
BFBBBFBRRR
FBBBBFFLLL
FFFBFBBLLL
BBFFFFFRLR
BBFFBFFLLL
FFBFBBBLRL
FFBBFBFRLR
BFBBBBBLRR
FFBFFFBLLR
FFBFFBFLRL
BFFBFBBRLR
FBFBFFFRRL
FBBBFFFLRR
FFFBBFFLLR
FBBBBFFRLR
FFBBFBBRRR
BFBBFBBRRR
BFBFBBFRRL
BFFBBBFRRL
FFFBFFFLLL
FBBFFBFLRL
FFFBFBBRLR
BFBBFFFLLR
BFBBFFBRRR
FBFFBFBRRL
FFBBBBBRLL
BFFBFFBLLL
BFFFBBFRRR
FBFFFBFRRR
FFBFBFBRLR
FBFBBFFLLR
FBBFBBBRRR
BFBFFFFRRR
FFBFFFFLLL
FBFBBFFRLL
BFBFFBFLRL
BFBBFFFLLL
FBFBBFBRRR
BFBFFFBLLR
BFBFFFBLLL
BBFFFBFLLR
BBFFBFFRLL
FFBBBBFRRL
BBFFFBFLRL
BBFFBBBLRL
BFBFFFBLRR
FFFBFBFRLL
BFBFFBBLLL
BBFFFBBRRL
BFBBBFFLLL
BFFBBFFLLR
FFBFFBBLLL
BFFBBFBRRL
BFFFFFBLRL
BBFFFFBRLR
FBFBBFFLLL
FFBBBFBRLR
FFFBBFBLLL
FBFFFBBRLR
FFBFBFFRLR
BFFFFFBLRR
FFFBBBBRLL
FFBBFFFRRR
BFFFFFBRLR
FBBBFFBLRR
FBFBFBBRLR
FBBFFFBLRR
BFBFFBBLRL
FBFFBFBRLR
FBFBFFFLRL
BFFFFFBRLL
BFBBBBFLRR
BFFBFFFLLL
FBFFBFFRRL
FFFBBFFRLL
BFFFBFFRRR
FBFFBFFLLR
FFFBBBFLLL
FBFFFBFLRR
BFFBFBBLLL
BFFFBBBLRR
FBBBBBBRRL
FBFFBFFRLR
FBBFFBBRLL
FBBBFFFRRR
BFFBFBBRRL
FFBBFFBRRR
BFBBBFFLRR
FFFBFBBRRL
BFBFBBBLRR
FFFBBFBLRL
FBFFBBFRLR
BFFFBBFLRR
BBFFFBBLRL
FBBFFBFRLR
FFFBFBFLLL
FFFBFFFRRL
BBFBFFFLLL
FBFBFBFLRR
BFBFFFFRLL

41
2020/d05/ex2/ex2.py Executable file
View file

@ -0,0 +1,41 @@
#!/usr/bin/env python
import sys
from typing import List
def seat_id(boarding_pass: str) -> int:
min_x = 0
max_x = 128
min_y = 0
max_y = 8
for char in boarding_pass:
if char == "F":
max_x = (min_x + max_x) // 2
elif char == "B":
min_x = (min_x + max_x) // 2
elif char == "L":
max_y = (min_y + max_y) // 2
elif char == "R":
min_y = (min_y + max_y) // 2
return min_x * 8 + min_y
def solve(passes: List[str]) -> int:
ids = sorted(seat_id(p) for p in passes)
for prev, cur in zip(ids, ids[1:]):
if prev + 1 != cur:
return prev + 1
assert False # Sanity check
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

781
2020/d05/ex2/input Normal file
View file

@ -0,0 +1,781 @@
FBFFBFFRLL
BFFFFBBRLR
FFFBBBBRLR
FBFFFBFLRL
FFBFBFFRRL
FFBBBBFRRR
FBFFBFBLRR
FFBBFBFRRL
FFFFBBFRRL
BFBBBBBLLL
FFBFBFBLLL
FFBFFFBLLL
FBBBFBFRLL
BBFFFBFRRR
FFFBFBBLLR
FBFBFBFRRR
BBFFBFBRLL
FBFBBBBLRL
FBFFFFFLLL
BFFFFFFRLL
BFFFBFBLRL
BFBBBFBRRL
BFFFBFFRRL
FBFFFFFRRR
FFBBBBBLLR
BFBBFFBLRL
FBBFBBBRLR
BFBFBFFRLL
BFBFBFBRLL
BFFBFBFLLL
FFBBFFBLRL
FBBFFBFLRR
FBBBFBBRRR
BFBFFBFRLR
BFBBBFBLLL
FFBFBBBLRR
BFBFFBFLLL
FBFBFBBLLL
BFBBBFBLRL
FBFBFBFLRL
FFBFFBFRRL
FBBFFBFLLL
BFBBBBBLRL
FBBBBBFRLR
BFFFBBFRLL
FBBBBFFLLR
FBBBBBFRLL
BFBBBFFRLR
BFBBBFBRLL
BFFFBFFLLL
FFFBFBFLRL
BFFBBFFLRL
BBFFFBFRLL
BFBBFFBRLR
BFBFBFBRRL
BBFFFBFRRL
FBBFBBBLRR
FFBFBBBLLL
BFFFBFBRLR
FFBBFBBLLL
FBFBBFBLLL
BFBBFBFLLR
FFBFBBBRRL
FFBFFFFLRL
FFFBBFFLRR
FBBBBBFRRR
FFFFBBBRLL
BFBFBBBRRR
BBFFBFBRRL
FBFBBFFRLR
FBBFFBFRRR
BBFFBFBRRR
FBFBBFBLRR
FBBFFBBLRR
FBBBBFFRLL
BFBFFFBRLR
FBFBBFBRRL
FFBFBBFRRR
FBFBFFFRLL
BFBBFFBLLR
FBFFFFBRLR
BFBBBFFRLL
FFBBFFBRLR
FFFBBFBRLL
FBBBBBBLRR
FBFFBBBLRR
BFFFFBFLRL
BBFFFFFLRR
BFFBFFBLLR
FFBBBFFRLL
BFBFBFBRLR
FBBFBFBLRR
FBFBBBFRLR
FBFFBBBRRR
FBBFFBFRLL
FBBBFFFRLR
BFBBBBFLLR
BFFFBFFLLR
FFBFFFBRRR
FBFFFBFLLR
FFFFBBBLLR
BFBFFFBRLL
BFFBBFBLRL
BFFBFBFLLR
FFBFFBFRLR
BFBFFFBRRL
FFBBFBFLLL
BFBBBBBRLR
BFBFBFBLRR
FBFFBFBLLR
FBFBFBBRRL
BFBFBBBLLL
FFBBFBBLRL
FBFFFBFRRL
BFBBFFFLRR
BFBFBBFRRR
FBFFFFBLRL
BBFFBBFRRR
FFBFFBBRLR
FBBFBFBLRL
BFBFFFBRRR
FFFBBBFLRL
BFFBFFBRLL
FBFBFFBLRR
FFBFBBFLLL
FFBBBFFLRL
FFBBFFFRLR
BBFFBFBLRL
FFFFBBFRLR
FFFBFFBLRR
BFFBBBFLLR
BFFFBBBRRL
FBBFBFBRLL
BFFBFFFRRR
BBFFFFFLRL
BBFFFBBRLL
BFFFBBBRRR
BFFFBBBLRL
BBFFBFFRRR
BFFBFFBLRL
FBBBBFBRLR
FFFBFBFRRL
BFFBBBBRRL
FBBBBBFLRR
FBFBBBBLLR
FBBBBFBLRR
FFFBFFBRLL
FFBBBBFLLR
FFBBBBBRRL
FBBFFFFLLL
FBFFBBBRLL
FBFBFFBLLR
FBBBBBFRRL
BFFFBFBLLL
FFFBFFFLRL
FFFFBBFRLL
BFBBFFFRLR
BFFFBBBRLR
FFBBBFBLLR
BFFFBFBRRR
BFFBFBBLRL
FFBFBFBLRR
FBBBBFBRRR
FFBFBFFLLR
BBFFFFFLLR
FBBBFBFRRR
BBFFFFBRRL
FBFBFBBLRL
BFBBBFFLLR
BBFFBBFLRL
BFBFFBBRLR
FBFBBBFRRL
FBBBFFBRLL
BBFFFFBLLR
FFBBFBBLRR
FBBBBBBRLR
FFFFBBBRRL
FBFBBBBRLR
BBFFBFFRRL
FBBBFFBLRL
FFBBBFBLRR
BFBFBBBRLL
FBFFFBBLRL
FBFBBBBRLL
BBFFFBBLLL
BFBBFFBLLL
BFFBBBBRRR
FBFBFFBLLL
FBFBFBFRRL
FBBFFFBLLL
BBFFFBFRLR
FBBBBFFLRR
FBFFFBBRLL
FFBBFBFRRR
FBFFFFFLRR
BFBFFBBLRR
FFBFBFFRRR
BFBFFBBRLL
FBBFFFFRRL
BFFBBFBRLL
BFFFFFBLLR
FBFBBFBLLR
BFFBBFBRLR
BFFBFBFRRR
FFBFBBFRLL
FFFBBBBLRR
BFFFBFBLLR
FBBBBFBLRL
FBFBBFFLRL
FFFBFFFRLL
BFFFFBBRRL
FBBFFFBRRR
FBBFBFFLLR
BFBBBBBRRR
BFFBFBFRLL
FFBFBBFRRL
BFBFBFBLLR
FFBFBBFLLR
FFBFFFFLRR
FBBBFBBRRL
BFFBFBFRLR
BFFBFFBRRL
BFBBBFBRLR
BBFFFFBLRL
FBBBFFBRRL
FBFFFBBRRL
FBBBBBBLLL
FFFBFFBLLL
BFBBFBFRLL
FBFBFFBRLR
FFFFBBBRRR
BBFFFBBRLR
BFBBBBFRLR
FBFFBBFLRR
BFFFBFFRLR
FFFBBBBLLR
FBFFFFBLRR
FBFBFBBRLL
FBFFBBBRLR
BFFFFFFLRR
FBFFFFFRLL
FFBFBFFRLL
FFFBBFFRLR
FBBFBFFRRL
FBBBBBBRRR
BFBFBBBLRL
BBFFFFBRRR
FFBFFBBLRL
FBBBBBBLLR
FFBBFFFLRL
FBBBFBBLRR
FFBBBBBRLR
BFBFFFFLLR
BFFBBBBRLL
BFBFBFFLRL
FBBFFFBLRL
BFBFBBBRRL
BFBFBFBLRL
BFBBFBFLRR
BFFFFBFRLR
BFFFBFBRLL
FBFBFBFLLL
FBFFBFFLRL
BFFFFFFRRL
FBBFBFFRLR
FFBBBFFLLR
FBBBBFFLRL
FBBBFBBRLR
BFBBBFFLRL
FBFFBBBLRL
BFFFFBFRRL
BFFFBFFLRR
FFBFBBFLRL
BFBFFFBLRL
BFFFFFBLLL
FBFFBFBLLL
FBFBBBBRRL
FBBFFBBRLR
BFFFBBFRRL
BFBBFBBRLR
FFFBFBBLRR
FFFBFBFRLR
FBFBFBFRLR
BFBFBBBRLR
BFFFFBBLLL
BFFBBFBRRR
BFFBBBFLLL
FFBBBFFRRL
BFBBBFBLLR
FBBFFBBLLR
FBBFBBFLRL
BFFFFFBRRR
FBBBFBBRLL
FBFBFFBRRR
BFFBBBFRRR
FBBBBBBLRL
FFBBBFFLRR
BFFBBBFRLL
BBFFBBFRLL
FBBFBBFRLR
BFBFBFFRRR
BFBFBBFLRL
BFFFFBFRLL
FFBBFBFLLR
BFFBFBBLRR
FBFFBBBRRL
FBBFBBFRLL
FBFFFBBLLR
FFFBBBBRRR
FFFFBBBLRL
FFBBFFFRRL
BFFBBFFRRL
BFFFBBFLRL
BFFFFBBLRR
BBFFBBBLRR
BFBFFFFLRR
FBFBBBBLLL
BBFFFBBLRR
FFFBFBFLRR
FBBFFFFLRL
FFBBBBFRLL
FBFFBFBLRL
BFBBFBBLLL
FBBFBBFLLL
FFBFFBBRLL
BFBFFFFRLR
FBFFBBFRRR
FFFBBFFRRR
FFFBFFBRLR
FBBBBBFLLL
FBBBFFFLRL
FFBBFFFLRR
FFFBBBBRRL
BFBFBBFRLL
BFBFFBBRRL
FBBFBBFRRL
BFBFBBFLLR
BBFFBBBRRR
BFFFBBFRLR
FFFBBBFRLR
BFFBFFFRLL
BFBFFFFRRL
FFBBFFFLLL
FBFBBBBLRR
FBFBFFFLRR
BBFFBFFLRR
FBBBFBBLRL
BFBFBFBLLL
FBFBFFFLLR
BFFBBFBLRR
FBBFFFBRRL
BFFBBFFRRR
FBBFBBBRRL
BFFFFBBLLR
FFBBBBFLLL
BFFBFFBRRR
BFFFFBFRRR
FFFBBBFRRR
FBFBFFFRLR
FBBBFBFLLR
FFBBFFBRLL
FBFBFFFLLL
BFFBFBFRRL
BFBFFBFRRL
BFBBBBFLLL
FBBBFBFRRL
FFBFBFFLLL
BFBBFFFRRL
FFBBFFBLLR
BFFBBBBRLR
FFBBBBBLRR
BFFBFFFRRL
BFFBFBBRLL
FBBBFBFRLR
FBBFFFFLRR
BFFFBBFLLR
FFFBBFBRRL
FFBBFFBLRR
FBBFFFBRLR
BFBBBBBRLL
BBFFFFFRRL
FFBFFBBRRL
BFBFFBFLLR
FBFBBBFLLL
FBFFFFFRRL
BFFFBFBLRR
FBFFFFBLLR
FBBFBFBRRR
FBBBFFFLLR
BBFFBFBLRR
BBFFFBFLLL
FBFFFBFRLR
BFFFBFFLRL
BBFFBFFLRL
BFFFFFFLLR
BBFFBBBLLL
FFBFBBBLLR
FBBFBBBLRL
BFBBFBBLRR
FFBFBFBLLR
FFBFBFBRRL
BFBBFBBRRL
BFFBFFFLLR
FFBBFFBRRL
BBFFBBBRRL
FFFBBFBRLR
BFBBFBFRRR
BFFFFFFRRR
FBBBFFBLLL
BFBFFFFLLL
BBFFBFBLLR
BFBFBBFRLR
FFBFBBBRRR
BFFFBBFLLL
FBFFBBFRLL
FFBBFBFRLL
BFBFBBBLLR
FBBFBFBLLL
BBFFFFBRLL
BBFFBFBLLL
BFFBFFBLRR
BFFBBFBLLL
FFBFFFBLRR
FBBFFBFRRL
FBBBBFBLLL
FFBFFBBLLR
BFFBBBFLRR
FBFBFFBRLL
FFBFFFBRLL
FFBFFBFLLL
FBFBBFBLRL
FBBFBFFRRR
BFBFBFFLLR
FBBFFFBLLR
BFBBBBFRRR
FBBFBBFRRR
BBFFBFFRLR
FBFBBBFRLL
FBBFBBBLLR
BFFFFFFLRL
BFBFFBBRRR
BFFFBFFRLL
BFBBFBFLRL
FFBFFFFRRR
BFFBBFFRLR
FBBBBBFLLR
FBFBFFBLRL
FFFBBFBLLR
FBBFBFBLLR
FFFBFFBRRR
FBFFFFFRLR
FBFBBFBRLR
FBBBFBFLRR
FBFBBBFLRL
BFFBFFFLRL
FFBBBFFRRR
FFBBBBBLLL
FBFFBBFLLR
FFBFBFFLRR
FFFBBBFLRR
BFBFBBFLLL
BBFFBFFLLR
FFBBFBBRLL
FBBFFBBLLL
FBFFBFBRLL
BFBFBFFLRR
FBBBFFBRLR
FFBFFBFRLL
FFFFBBBLLL
FFBFFBBRRR
FBBBBFBRLL
BFFFFBBRRR
FFBBFFFRLL
FFBFBFBRLL
BBFFFFBLLL
FFBBBFBRRL
BFFFFBBLRL
FBBBFBBLLR
FBBBFBBLLL
FFBFBFBLRL
FBBBBFFRRR
FBBFFFFRLR
FFBFFFBRLR
BFBFBFBRRR
FFFBFBBRLL
FBBBFFBRRR
FBBFBFFRLL
BFFBFBFLRR
BFBBBFFRRL
BFFBBFBLLR
FFBBBFBRLL
FBFBFBBLRR
BFBBFFFLRL
BFBFBBFLRR
BFBBBFFRRR
FBBBFFFRRL
FBFBFBFLLR
FBBFFFFLLR
FFBFBBFRLR
FFFBFBBLRL
BBFFFBBLLR
BFFBBBFRLR
FFFFBBBRLR
BBFFBBFRLR
FBFFFFBRLL
FBFBFFFRRR
FBFFFBBLLL
BFBBBBFRLL
FBFBFFBRRL
FFFBFFFRLR
BFBBFBFRRL
FBFFBFFLRR
FBFFFBBLRR
FFBFBBBRLR
FBBFBFFLRR
FBFFFBBRRR
FFBFBBBRLL
FFBBBBBRRR
BFFBBFFLLL
BFBBBBBRRL
BBFFBBBRLL
FBFFFFFLRL
BFFBBFFLRR
FBFFBBFLRL
BFBFFBFRRR
FBFBBFBRLL
BFFFBFBRRL
FBBFFBFLLR
BFFFFFFLLL
FBFBFBFRLL
FBBBBFFRRL
BFBFFBBLLR
FBBFBFBRRL
FFFBFFFLLR
FFBBBBBLRL
FFBFFBBLRR
FFFBFBFRRR
BFBBFBBRLL
BFBBBFBLRR
FFBBBBFLRR
FBBBFFBLLR
BBFFBBBLLR
FBFBBFFRRL
FBBBBBFLRL
FFFBBFFRRL
BFFBBBBLRR
FFFFBBBLRR
FFFFBBFLRR
FBFFFBFLLL
FBFBFBBLLR
BFFBBBBLLL
FFBFFFFRLR
BFBBFFBLRR
FFBBFBFLRL
BFBFBFFLLL
BFFBFBBLLR
BFBBFBBLRL
FFBBBBFLRL
FBBBFFFLLL
FFFBFFBRRL
BFFFFBBRLL
BFFFBBBRLL
BFFBFFFLRR
FFBFBFBRRR
BBFFBBFLLR
FFBBFBBLLR
FFBFFBFRRR
FFBBBFFRLR
BFFBBBBLLR
FFFBFFFLRR
FBFFFFFLLR
FBFFBBBLLL
BBFFBBFLLL
FFBBFBFLRR
BFFBFBFLRL
FBFBBBFRRR
BFBBFBBLLR
FBFFFFBRRL
FFFBBFBLRR
BBFFFFBLRR
BFBBBBFRRL
FFBBBFBLLL
BFBBFBFRLR
BFBBFFBRRL
BFBFBFFRRL
FBBFFBBLRL
FFFBFFBLRL
BFFBBFFRLL
FBBBFFFRLL
FBBFBBFLLR
FFBFFFFLLR
FBBBFBFLRL
BFFFBBBLLR
FBFBBBBRRR
FBBFBFBRLR
FFFBFBFLLR
FFFFBBFRRR
FFFBBFFLRL
BFBFFBFRLL
FFFBFFBLLR
FBBFFFBRLL
FFBBBFBRRR
FFBBFBBRLR
BBFFFFFRRR
FFBFFFFRLL
FBBFFBBRRL
BBFFFBFLRR
FBBFFFFRRR
FFBFFFBRRL
BFBBFBFLLL
BFFFFBFLRR
BBFFFFFLLL
FFBBFBBRRL
FFBFBFFLRL
FBFFBBFRRL
BBFFBFBRLR
BBFFBBFLRR
FBFFBFBRRR
FBBFBBFLRR
FBFFFBFRLL
BFBFFFFLRL
FFFBBFBRRR
BFBBBBBLLR
FBBFFBBRRR
FFBBBFFLLL
FBBBBFBLLR
BBFFFFFRLL
FFBBBBFRLR
FBFBFBBRRR
FBFFBFFLLL
FBFFBBBLLR
FBBBBFBRRL
BFBFBFFRLR
FBBFBBBRLL
BFBBFFFRLL
FBBBFBFLLL
FFBFFFFRRL
FBFBBFFRRR
FBFFFFBLLL
FBBBBBBRLL
BFFBFBBRRR
BBFFBBFRRL
FBBFBFFLRL
FBFFFFBRRR
FBBFFFFRLL
FFFBFFFRRR
FBFFBBFLLL
BFFFFBFLLL
BFFFFBFLLR
FFBFFBFLLR
FFBFFBFLRR
BFFBBBBLRL
FFBBFFBLLL
FBBFBBBLLL
FBFBBBFLLR
BFFBBBFLRL
BFBBFFBRLL
FBFFBFFRRR
FFBFFFBLRL
FFFBBBFRRL
FFBFBBFLRR
FFFBBBBLRL
FFFBBFFLLL
FFFBFBBRRR
FBBFBFFLLL
BFFFBBBLLL
BFFBFFFRLR
FFFBBBBLLL
BFFFFFBRRL
FFBBFFFLLR
BFBBFFFRRR
BFBFFBFLRR
FFFBBBFLLR
FBFBBBFLRR
BBFFBBBRLR
FBFBBFFLRR
FFBBBFBLRL
FFFBBBFRLL
BFFBFFBRLR
BBFFFBBRRR
BFBBBBFLRL
BFBBBFBRRR
FBBBBFFLLL
FFFBFBBLLL
BBFFFFFRLR
BBFFBFFLLL
FFBFBBBLRL
FFBBFBFRLR
BFBBBBBLRR
FFBFFFBLLR
FFBFFBFLRL
BFFBFBBRLR
FBFBFFFRRL
FBBBFFFLRR
FFFBBFFLLR
FBBBBFFRLR
FFBBFBBRRR
BFBBFBBRRR
BFBFBBFRRL
BFFBBBFRRL
FFFBFFFLLL
FBBFFBFLRL
FFFBFBBRLR
BFBBFFFLLR
BFBBFFBRRR
FBFFBFBRRL
FFBBBBBRLL
BFFBFFBLLL
BFFFBBFRRR
FBFFFBFRRR
FFBFBFBRLR
FBFBBFFLLR
FBBFBBBRRR
BFBFFFFRRR
FFBFFFFLLL
FBFBBFFRLL
BFBFFBFLRL
BFBBFFFLLL
FBFBBFBRRR
BFBFFFBLLR
BFBFFFBLLL
BBFFFBFLLR
BBFFBFFRLL
FFBBBBFRRL
BBFFFBFLRL
BBFFBBBLRL
BFBFFFBLRR
FFFBFBFRLL
BFBFFBBLLL
BBFFFBBRRL
BFBBBFFLLL
BFFBBFFLLR
FFBFFBBLLL
BFFBBFBRRL
BFFFFFBLRL
BBFFFFBRLR
FBFBBFFLLL
FFBBBFBRLR
FFFBBFBLLL
FBFFFBBRLR
FFBFBFFRLR
BFFFFFBLRR
FFFBBBBRLL
FFBBFFFRRR
BFFFFFBRLR
FBBBFFBLRR
FBFBFBBRLR
FBBFFFBLRR
BFBFFBBLRL
FBFFBFBRLR
FBFBFFFLRL
BFFFFFBRLL
BFBBBBFLRR
BFFBFFFLLL
FBFFBFFRRL
FFFBBFFRLL
BFFFBFFRRR
FBFFBFFLLR
FFFBBBFLLL
FBFFFBFLRR
BFFBFBBLLL
BFFFBBBLRR
FBBBBBBRRL
FBFFBFFRLR
FBBFFBBRLL
FBBBFFFRRR
BFFBFBBRRL
FFBBFFBRRR
BFBBBFFLRR
FFFBFBBRRL
BFBFBBBLRR
FFFBBFBLRL
FBFFBBFRLR
BFFFBBFLRR
BBFFFBBLRL
FBBFFBFRLR
FFFBFBFLLL
FFFBFFFRRL
BBFBFFFLLL
FBFBFBFLRR
BFBFFFFRLL

25
2020/d06/ex1/ex1.py Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env python
import sys
from collections import defaultdict
from typing import DefaultDict, List, Set
def solve(raw: List[str]) -> int:
answers: DefaultDict[int, Set[str]] = defaultdict(set)
group = 0
for line in raw:
if line == "":
group += 1
continue
answers[group] |= {char for char in line}
return sum(len(answer) for answer in answers.values())
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

2246
2020/d06/ex1/input Normal file

File diff suppressed because it is too large Load diff

31
2020/d06/ex2/ex2.py Executable file
View file

@ -0,0 +1,31 @@
#!/usr/bin/env python
import sys
from collections import defaultdict
from typing import DefaultDict, List, Set
def solve(raw: List[str]) -> int:
answers: DefaultDict[int, Set[str]] = defaultdict(set)
group = 0
first = True
for line in raw:
if line == "":
group += 1
first = True
continue
if not first:
answers[group] &= {char for char in line}
else:
answers[group] = {char for char in line}
first = False
return sum(len(answer) for answer in answers.values())
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

2246
2020/d06/ex2/input Normal file

File diff suppressed because it is too large Load diff

77
2020/d07/ex1/ex1.py Executable file
View file

@ -0,0 +1,77 @@
#!/usr/bin/env python
import re
import sys
from collections import defaultdict
from copy import deepcopy
from dataclasses import dataclass
from typing import Dict, List, Set, Tuple
@dataclass(eq=True, frozen=True) # Hashable
class ColorInfo:
num: int
color: str
Graph = Dict[str, Set[ColorInfo]]
def extract_info(line: str) -> Tuple[str, Set[ColorInfo]]:
color_pattern = re.compile("(.*) contain ")
match = color_pattern.search(line)
assert match is not None
color = match.group(1).replace("bags", "bag")
line = line[match.end() : -1] # Remove period at end of line
if line == "no other bags":
return color, set()
colors: Set[ColorInfo] = set()
pattern = re.compile("([0-9]+) (.*)")
for col in line.split(", "):
match = pattern.search(col)
assert match is not None
colors |= {
ColorInfo(int(match.group(1)), match.group(2).replace("bags", "bag"))
}
return color, colors
def to_graph(raw: List[str]) -> Graph:
return {color: inside for color, inside in map(extract_info, raw)}
def reverse(graph: Graph) -> Graph:
reverse: Graph = defaultdict(set)
for color, contained in graph.items():
for col in contained:
reverse[col.color] |= {ColorInfo(-1, color)}
return reverse
def containing(graph: Graph, col: str) -> Set[ColorInfo]:
res = deepcopy(graph[col])
for contains in graph[col]:
res |= containing(graph, contains.color)
return res
def solve(raw: List[str]) -> int:
graph = to_graph(raw)
reverse_graph = reverse(graph)
return len(containing(reverse_graph, "shiny gold bag"))
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

594
2020/d07/ex1/input Normal file
View file

@ -0,0 +1,594 @@
shiny aqua bags contain 1 dark white bag.
muted blue bags contain 1 vibrant lavender bag, 4 dotted silver bags, 2 dim indigo bags.
drab gray bags contain 5 mirrored white bags, 1 light green bag, 5 shiny lavender bags, 5 faded aqua bags.
muted indigo bags contain 4 muted chartreuse bags, 2 dotted teal bags.
drab white bags contain 2 dull fuchsia bags, 1 vibrant bronze bag.
dim lavender bags contain 4 muted tan bags.
dotted tomato bags contain 1 mirrored lime bag, 2 vibrant white bags.
clear orange bags contain 5 clear violet bags, 2 dull beige bags, 2 dark chartreuse bags.
bright lime bags contain no other bags.
striped brown bags contain 3 bright orange bags.
vibrant green bags contain 3 shiny fuchsia bags.
plaid tomato bags contain 3 faded chartreuse bags, 2 wavy salmon bags, 1 faded white bag, 3 mirrored maroon bags.
drab beige bags contain 2 shiny bronze bags, 4 pale violet bags, 3 bright tomato bags, 4 pale red bags.
posh green bags contain 2 dull lavender bags, 4 clear plum bags, 2 dark gray bags.
dull maroon bags contain 3 dull magenta bags, 1 dull tan bag, 1 faded cyan bag, 5 dull silver bags.
faded crimson bags contain 2 muted purple bags, 4 dotted olive bags, 5 drab silver bags.
wavy bronze bags contain 3 dark orange bags, 2 dark brown bags, 5 bright silver bags.
dark turquoise bags contain 5 dull plum bags.
dull lavender bags contain 4 dotted maroon bags, 3 muted brown bags, 4 drab black bags, 4 dull cyan bags.
dotted plum bags contain 1 shiny bronze bag, 3 clear brown bags, 3 muted indigo bags.
dull white bags contain 3 clear tan bags, 5 shiny gold bags, 2 drab crimson bags.
dull teal bags contain 2 bright tomato bags.
shiny crimson bags contain 3 light green bags, 5 striped brown bags, 3 faded fuchsia bags.
wavy brown bags contain 1 drab crimson bag, 2 wavy indigo bags.
dark tan bags contain 2 faded gray bags, 4 shiny salmon bags.
shiny red bags contain 4 dull chartreuse bags, 5 pale tomato bags.
bright orange bags contain no other bags.
wavy yellow bags contain 5 light indigo bags, 5 dark gray bags, 5 plaid indigo bags, 4 faded red bags.
faded bronze bags contain 4 faded cyan bags, 5 shiny beige bags, 5 muted red bags.
dull bronze bags contain 1 mirrored beige bag, 5 muted violet bags, 1 wavy lime bag.
dark lime bags contain 2 drab maroon bags, 5 bright indigo bags, 4 shiny black bags, 5 dotted turquoise bags.
drab red bags contain 5 bright red bags, 2 vibrant brown bags.
dotted salmon bags contain 3 vibrant turquoise bags, 2 dull beige bags, 3 light turquoise bags.
dull gray bags contain 3 striped green bags, 3 wavy coral bags, 1 dark gray bag, 2 light indigo bags.
faded black bags contain 4 muted fuchsia bags, 4 wavy coral bags, 1 drab tomato bag.
muted magenta bags contain 2 posh chartreuse bags, 4 pale violet bags.
light tan bags contain 2 posh turquoise bags, 3 vibrant white bags, 1 light black bag.
dark blue bags contain 3 plaid indigo bags, 2 posh black bags.
dull indigo bags contain 4 light gray bags, 3 dotted tan bags, 4 dull coral bags.
dim fuchsia bags contain 3 vibrant yellow bags, 3 mirrored cyan bags, 4 mirrored brown bags.
shiny beige bags contain 2 dull silver bags, 3 bright lime bags, 5 dull magenta bags.
light cyan bags contain 3 vibrant violet bags, 2 mirrored tomato bags, 2 vibrant coral bags, 4 mirrored silver bags.
clear turquoise bags contain 4 drab tomato bags, 3 shiny gold bags, 4 drab gold bags.
pale teal bags contain 2 wavy maroon bags, 2 dotted olive bags, 4 shiny white bags, 2 drab turquoise bags.
dark purple bags contain 1 wavy indigo bag, 3 bright black bags, 3 dotted teal bags.
bright white bags contain 5 wavy red bags, 2 mirrored cyan bags, 3 drab green bags.
mirrored aqua bags contain 1 faded violet bag, 5 dotted purple bags.
shiny lime bags contain 4 dark aqua bags.
pale bronze bags contain 1 clear crimson bag.
vibrant white bags contain 5 plaid lavender bags, 1 drab red bag, 4 vibrant brown bags.
plaid tan bags contain 5 dim crimson bags.
posh olive bags contain 3 bright red bags.
plaid brown bags contain 5 vibrant turquoise bags.
mirrored tomato bags contain 2 dotted chartreuse bags, 3 light aqua bags, 3 posh beige bags.
plaid blue bags contain 5 striped green bags, 1 plaid purple bag, 4 muted gold bags.
shiny tan bags contain 5 striped coral bags, 1 dull brown bag.
shiny gold bags contain 1 dull magenta bag, 5 dark white bags, 4 faded turquoise bags.
dull salmon bags contain 2 plaid gold bags, 2 light indigo bags.
striped tomato bags contain 2 striped tan bags, 4 light blue bags, 4 drab tan bags.
drab tomato bags contain 3 dim teal bags, 4 striped yellow bags, 3 bright red bags.
faded olive bags contain 1 drab plum bag, 1 pale aqua bag, 3 light blue bags.
dotted indigo bags contain 2 clear tomato bags.
dark white bags contain 5 light aqua bags, 2 dim teal bags, 2 muted fuchsia bags, 5 light purple bags.
dull orange bags contain 4 pale gold bags, 5 posh brown bags, 2 mirrored brown bags, 3 dark bronze bags.
bright maroon bags contain 1 mirrored yellow bag, 4 light teal bags.
bright silver bags contain 1 vibrant coral bag, 3 dim teal bags, 5 light purple bags.
muted olive bags contain 5 plaid orange bags, 1 muted magenta bag.
dull silver bags contain no other bags.
pale maroon bags contain 2 pale bronze bags.
light gray bags contain 4 vibrant yellow bags, 2 pale red bags.
drab teal bags contain 2 light crimson bags, 3 vibrant brown bags, 3 vibrant tan bags.
bright gold bags contain 1 wavy red bag, 5 wavy coral bags.
plaid chartreuse bags contain 2 dim coral bags, 4 drab silver bags, 5 dim chartreuse bags, 3 light purple bags.
clear blue bags contain 2 pale tomato bags, 4 dull gold bags, 4 dim fuchsia bags, 4 pale coral bags.
vibrant purple bags contain 5 faded orange bags.
plaid aqua bags contain 3 muted cyan bags, 2 wavy gray bags, 4 drab green bags, 4 pale beige bags.
muted lime bags contain 1 muted tan bag.
faded coral bags contain 3 drab turquoise bags, 1 shiny plum bag, 5 mirrored green bags, 5 clear white bags.
vibrant lime bags contain 5 posh coral bags.
faded green bags contain 3 pale orange bags, 5 dull turquoise bags, 1 mirrored crimson bag.
mirrored gray bags contain 5 dim indigo bags.
wavy maroon bags contain 4 mirrored bronze bags, 1 striped olive bag, 2 dull salmon bags, 3 shiny crimson bags.
dark violet bags contain 2 light purple bags.
dark green bags contain 2 dim cyan bags.
pale black bags contain 1 mirrored gold bag.
bright yellow bags contain 2 vibrant crimson bags, 3 plaid lime bags, 2 dotted gold bags.
muted teal bags contain 1 pale violet bag, 4 dull silver bags.
dim beige bags contain 5 wavy red bags.
muted purple bags contain 4 clear cyan bags.
plaid fuchsia bags contain 3 dark coral bags.
plaid bronze bags contain 5 plaid orange bags, 2 drab indigo bags.
faded indigo bags contain 1 dark chartreuse bag, 4 dull green bags, 1 mirrored magenta bag.
posh plum bags contain 3 dark chartreuse bags, 3 dotted turquoise bags, 4 dull maroon bags, 1 posh bronze bag.
pale gold bags contain 4 striped brown bags.
mirrored chartreuse bags contain 4 bright silver bags, 3 mirrored tomato bags, 4 wavy orange bags.
pale orange bags contain 2 posh fuchsia bags, 2 clear salmon bags, 2 bright green bags.
clear brown bags contain 4 light lime bags, 4 bright green bags, 5 pale yellow bags, 2 drab cyan bags.
shiny plum bags contain 5 vibrant gray bags, 3 bright blue bags, 5 dark tomato bags.
wavy white bags contain 4 plaid lime bags, 4 posh maroon bags, 5 drab lime bags, 1 vibrant crimson bag.
faded red bags contain 1 dull coral bag, 5 clear cyan bags, 4 plaid chartreuse bags, 3 plaid orange bags.
plaid red bags contain 5 pale blue bags, 4 light crimson bags, 3 faded fuchsia bags.
bright cyan bags contain 3 dark white bags, 2 light crimson bags, 1 bright aqua bag.
muted lavender bags contain 1 light green bag, 4 striped silver bags, 3 posh crimson bags.
wavy crimson bags contain 1 light purple bag, 4 bright blue bags, 2 dull coral bags, 1 wavy beige bag.
faded aqua bags contain 5 muted brown bags.
mirrored fuchsia bags contain 1 faded beige bag, 3 muted gold bags.
dark chartreuse bags contain 5 bright lime bags.
plaid green bags contain 4 mirrored tan bags, 1 mirrored tomato bag, 5 pale indigo bags, 1 mirrored plum bag.
shiny black bags contain 3 plaid chartreuse bags.
dotted purple bags contain 2 dim teal bags.
faded tan bags contain 2 bright fuchsia bags, 5 shiny fuchsia bags, 1 muted fuchsia bag, 1 mirrored brown bag.
drab brown bags contain 1 striped orange bag, 4 dotted tomato bags.
dull olive bags contain 1 striped black bag, 1 vibrant magenta bag.
mirrored plum bags contain 1 clear gold bag, 5 pale green bags.
dim tomato bags contain 4 drab gold bags, 2 shiny aqua bags.
light lavender bags contain 1 muted violet bag.
dim gray bags contain 3 light purple bags, 1 posh crimson bag, 1 faded brown bag.
muted aqua bags contain 4 dull beige bags, 4 dull red bags.
faded silver bags contain 1 mirrored cyan bag.
shiny green bags contain 5 dull maroon bags.
muted chartreuse bags contain 2 clear tan bags.
plaid plum bags contain 1 dotted lime bag, 4 clear brown bags, 4 dull red bags.
dotted silver bags contain 1 posh coral bag.
dim crimson bags contain 4 faded violet bags, 1 striped silver bag.
bright brown bags contain 1 bright coral bag, 3 posh brown bags, 4 drab tan bags.
wavy cyan bags contain 3 clear gold bags, 1 mirrored salmon bag, 3 bright fuchsia bags, 2 light bronze bags.
dull violet bags contain 5 striped white bags, 4 light blue bags, 4 dim black bags.
vibrant olive bags contain 2 vibrant coral bags.
bright coral bags contain 2 vibrant tan bags, 3 shiny indigo bags, 2 plaid indigo bags.
dim turquoise bags contain 1 pale violet bag.
striped crimson bags contain 2 faded gray bags.
clear green bags contain 3 mirrored olive bags, 3 shiny tomato bags.
faded violet bags contain 2 wavy coral bags, 2 dull tan bags, 1 dull silver bag, 1 bright orange bag.
pale chartreuse bags contain 4 shiny crimson bags, 2 clear bronze bags.
light plum bags contain 3 drab bronze bags, 1 bright bronze bag, 1 posh yellow bag.
pale tomato bags contain 1 dim teal bag, 5 drab cyan bags, 3 muted coral bags, 2 dim chartreuse bags.
plaid coral bags contain 1 striped tan bag, 3 vibrant cyan bags, 3 light beige bags, 2 dotted green bags.
bright gray bags contain 4 mirrored teal bags, 4 striped brown bags, 1 dim green bag, 4 clear cyan bags.
drab fuchsia bags contain 2 mirrored salmon bags, 4 posh orange bags, 3 faded crimson bags, 3 pale plum bags.
light tomato bags contain 2 dotted gold bags, 1 dotted bronze bag.
muted violet bags contain 2 light chartreuse bags.
drab tan bags contain 2 light green bags, 5 bright red bags, 4 shiny beige bags.
drab chartreuse bags contain 2 drab salmon bags, 2 dark brown bags, 4 clear turquoise bags.
drab violet bags contain 4 faded red bags.
posh cyan bags contain 4 bright violet bags.
posh orange bags contain 4 pale plum bags, 5 posh aqua bags.
plaid silver bags contain 1 dotted brown bag, 3 drab gold bags, 4 clear yellow bags.
mirrored silver bags contain 3 shiny beige bags, 1 drab silver bag.
faded gray bags contain no other bags.
wavy tomato bags contain 1 bright brown bag, 3 striped red bags, 2 vibrant maroon bags.
posh violet bags contain 2 dim aqua bags.
bright blue bags contain 5 light lime bags, 2 faded violet bags, 3 light aqua bags, 4 vibrant coral bags.
dark teal bags contain 5 muted fuchsia bags.
striped fuchsia bags contain 1 wavy turquoise bag, 5 wavy green bags, 4 posh gold bags.
posh maroon bags contain 2 dull red bags.
shiny purple bags contain 2 clear tan bags.
wavy lime bags contain 2 dark coral bags, 1 shiny gold bag.
wavy silver bags contain 4 dotted white bags.
shiny silver bags contain 2 plaid gold bags, 2 dim green bags, 5 plaid lime bags, 3 dull red bags.
wavy red bags contain 3 vibrant brown bags, 4 bright indigo bags.
dull chartreuse bags contain 4 dotted lime bags, 2 bright silver bags, 3 dull red bags, 4 wavy maroon bags.
vibrant silver bags contain 1 bright fuchsia bag, 3 drab lavender bags, 2 drab olive bags, 3 dotted teal bags.
striped gray bags contain 5 plaid orange bags, 1 wavy coral bag.
striped green bags contain 4 wavy coral bags, 4 shiny gold bags, 3 dark brown bags, 5 vibrant brown bags.
mirrored violet bags contain 3 dim silver bags, 1 posh tomato bag, 1 light salmon bag.
dull purple bags contain 1 light gray bag, 3 wavy yellow bags, 1 wavy salmon bag.
mirrored beige bags contain 4 dark cyan bags, 5 dull green bags.
posh lime bags contain 3 posh chartreuse bags.
vibrant tan bags contain 2 dull plum bags, 1 striped brown bag, 4 vibrant coral bags.
dotted orange bags contain 1 mirrored olive bag, 5 drab silver bags.
clear indigo bags contain 3 light lime bags, 4 dull coral bags.
pale gray bags contain 1 faded black bag, 3 dim green bags, 4 wavy lavender bags, 2 posh brown bags.
posh gold bags contain 5 dark tan bags, 2 dotted olive bags, 5 dark aqua bags.
striped chartreuse bags contain 2 dull magenta bags, 1 posh tomato bag.
mirrored bronze bags contain 2 faded fuchsia bags.
clear salmon bags contain 4 posh bronze bags, 5 clear plum bags, 5 dull blue bags.
posh purple bags contain 5 dim gray bags, 3 faded brown bags.
faded lime bags contain 5 dim turquoise bags, 3 dark indigo bags, 2 vibrant gray bags, 1 muted silver bag.
wavy beige bags contain 1 dark bronze bag, 4 dull plum bags, 4 mirrored silver bags.
clear yellow bags contain 2 vibrant teal bags.
vibrant plum bags contain 4 muted chartreuse bags, 4 posh silver bags.
striped yellow bags contain 2 dull maroon bags, 5 bright red bags, 2 posh chartreuse bags.
dark coral bags contain 3 dull tan bags.
dull magenta bags contain no other bags.
dark gold bags contain 1 dotted indigo bag, 4 shiny teal bags, 4 dotted silver bags.
dim tan bags contain 1 striped lavender bag, 1 shiny tomato bag.
muted maroon bags contain 2 dull salmon bags, 4 dim chartreuse bags, 3 bright aqua bags, 2 faded indigo bags.
vibrant tomato bags contain 2 dark silver bags, 3 plaid purple bags.
dotted lime bags contain 3 shiny crimson bags, 2 pale yellow bags.
muted fuchsia bags contain 1 dull tan bag.
bright tan bags contain 5 pale gold bags, 5 drab teal bags, 2 light blue bags.
dark crimson bags contain 4 shiny orange bags, 3 faded purple bags, 3 bright white bags.
striped tan bags contain 4 dotted turquoise bags, 4 drab lime bags, 5 dim teal bags.
posh fuchsia bags contain 2 dotted olive bags, 2 mirrored beige bags, 3 shiny bronze bags.
pale silver bags contain 4 vibrant lavender bags, 4 clear beige bags, 4 striped gold bags.
posh aqua bags contain 4 drab lime bags, 4 dull tan bags, 5 vibrant tan bags.
plaid salmon bags contain 5 dim coral bags, 2 wavy bronze bags.
mirrored orange bags contain 4 vibrant gray bags.
dim yellow bags contain 5 pale tan bags, 4 dark black bags.
dotted coral bags contain 4 dotted chartreuse bags, 2 bright red bags, 1 vibrant white bag, 1 vibrant brown bag.
muted crimson bags contain 4 striped orange bags, 5 pale yellow bags, 3 posh blue bags, 1 muted red bag.
striped lavender bags contain 3 striped brown bags.
striped maroon bags contain 2 shiny yellow bags.
vibrant blue bags contain 3 faded cyan bags, 1 shiny lime bag, 3 dark tomato bags.
pale lavender bags contain 4 plaid magenta bags, 4 striped blue bags.
dull tan bags contain 4 shiny indigo bags, 2 light purple bags, 4 faded cyan bags.
dotted beige bags contain 3 drab indigo bags.
light indigo bags contain 1 faded cyan bag, 5 bright aqua bags, 1 shiny indigo bag.
vibrant crimson bags contain 4 dotted fuchsia bags.
wavy blue bags contain 4 wavy teal bags, 1 dull blue bag.
vibrant chartreuse bags contain 4 striped orange bags.
vibrant cyan bags contain 5 wavy coral bags.
faded brown bags contain 5 faded turquoise bags.
faded magenta bags contain 1 dull indigo bag, 4 plaid aqua bags, 4 dim crimson bags.
mirrored coral bags contain 4 drab crimson bags, 2 light salmon bags, 2 clear indigo bags.
faded cyan bags contain no other bags.
dark brown bags contain 5 light purple bags.
wavy violet bags contain 3 dull coral bags, 1 bright aqua bag, 3 shiny lavender bags.
posh tomato bags contain 4 vibrant chartreuse bags, 4 mirrored teal bags.
pale crimson bags contain 1 plaid orange bag, 1 dark violet bag, 3 plaid lavender bags.
dark fuchsia bags contain 4 plaid beige bags, 2 plaid chartreuse bags.
plaid magenta bags contain 3 clear lavender bags, 5 mirrored brown bags, 5 shiny bronze bags.
striped blue bags contain 1 dull bronze bag, 1 dotted fuchsia bag, 1 light lavender bag, 1 clear turquoise bag.
dotted olive bags contain 4 dotted turquoise bags, 5 dotted bronze bags, 3 pale yellow bags, 4 pale red bags.
posh silver bags contain 3 pale violet bags, 1 plaid salmon bag, 1 posh coral bag.
dotted chartreuse bags contain 3 bright blue bags.
light coral bags contain 4 shiny fuchsia bags, 2 pale red bags, 1 muted silver bag, 2 bright cyan bags.
pale brown bags contain 5 light aqua bags.
dotted black bags contain 2 plaid purple bags, 1 mirrored aqua bag, 5 posh beige bags.
posh coral bags contain 3 dark aqua bags, 2 pale yellow bags, 5 plaid blue bags, 4 dim aqua bags.
shiny gray bags contain 1 bright gold bag, 1 muted bronze bag, 5 striped green bags, 5 shiny teal bags.
drab orange bags contain 5 plaid salmon bags, 2 vibrant beige bags.
plaid yellow bags contain 4 clear teal bags, 2 bright red bags.
striped violet bags contain 4 mirrored fuchsia bags, 4 vibrant white bags, 3 dim teal bags.
dim aqua bags contain 1 muted fuchsia bag, 1 dull tan bag.
light orange bags contain 2 bright red bags, 4 dark white bags, 1 dim chartreuse bag, 5 faded fuchsia bags.
faded salmon bags contain 5 wavy gray bags.
shiny yellow bags contain 2 vibrant plum bags, 3 dim teal bags, 1 plaid tan bag, 5 posh plum bags.
vibrant beige bags contain 2 wavy lavender bags, 4 posh chartreuse bags, 3 pale teal bags, 5 wavy lime bags.
light fuchsia bags contain 3 clear brown bags, 3 bright lavender bags.
pale magenta bags contain 4 posh silver bags.
dark maroon bags contain 3 drab turquoise bags.
faded beige bags contain 1 vibrant white bag, 4 drab red bags, 1 drab lavender bag.
bright bronze bags contain 1 pale bronze bag, 3 muted silver bags, 2 striped coral bags, 3 clear gray bags.
light silver bags contain 3 dotted lavender bags, 2 wavy lavender bags.
muted salmon bags contain 2 drab tan bags, 5 wavy tomato bags.
bright black bags contain 5 plaid tan bags.
dim chartreuse bags contain 5 muted gold bags, 5 bright blue bags, 5 faded cyan bags.
shiny white bags contain 4 bright tan bags.
bright red bags contain 3 dull silver bags.
dark aqua bags contain 2 dull red bags.
drab plum bags contain 4 muted brown bags, 5 muted plum bags.
muted yellow bags contain 5 light purple bags, 3 dotted silver bags, 3 faded turquoise bags.
light violet bags contain 1 pale red bag, 4 dim silver bags, 2 mirrored bronze bags.
pale lime bags contain 4 bright lavender bags.
pale tan bags contain 4 striped green bags, 2 dotted chartreuse bags.
dim green bags contain 1 light lime bag, 1 shiny beige bag.
mirrored gold bags contain 4 mirrored white bags.
dim silver bags contain 5 pale coral bags, 3 wavy coral bags.
dull aqua bags contain 3 posh indigo bags, 5 dotted coral bags, 1 dark salmon bag, 3 striped crimson bags.
posh yellow bags contain 1 dark bronze bag, 2 mirrored white bags, 2 light crimson bags.
mirrored magenta bags contain 1 bright violet bag, 2 drab lavender bags, 3 pale violet bags, 2 plaid salmon bags.
shiny chartreuse bags contain 2 dotted purple bags, 5 wavy red bags, 3 plaid beige bags.
light black bags contain 1 dark chartreuse bag, 3 faded tomato bags.
clear plum bags contain 5 vibrant brown bags, 3 dim coral bags, 4 mirrored brown bags, 1 faded black bag.
pale violet bags contain 2 dull tan bags.
bright fuchsia bags contain 4 dull orange bags.
dotted teal bags contain 5 bright red bags, 3 wavy red bags, 1 dull coral bag, 3 clear plum bags.
dotted blue bags contain 2 wavy beige bags, 3 muted purple bags.
muted gray bags contain 3 faded aqua bags, 1 shiny olive bag, 5 clear salmon bags, 1 vibrant violet bag.
dull beige bags contain 1 wavy lavender bag, 4 dark bronze bags, 5 dull tan bags.
drab turquoise bags contain 3 posh gray bags, 5 drab red bags.
vibrant yellow bags contain 2 shiny aqua bags, 4 light chartreuse bags.
posh brown bags contain 3 bright green bags, 5 posh lavender bags.
faded gold bags contain 4 vibrant maroon bags, 4 dotted purple bags.
dotted turquoise bags contain 5 clear plum bags, 3 muted gold bags, 4 dark violet bags.
dotted tan bags contain 5 dim aqua bags, 4 striped violet bags.
posh crimson bags contain 4 striped blue bags, 5 dull magenta bags, 2 bright coral bags.
muted white bags contain 5 dull olive bags.
vibrant teal bags contain 5 dotted turquoise bags, 1 striped tan bag, 1 drab tan bag.
dotted yellow bags contain 3 plaid turquoise bags, 2 posh yellow bags, 4 striped blue bags, 5 posh black bags.
posh magenta bags contain 5 mirrored black bags.
dotted green bags contain 4 dim crimson bags, 1 shiny lavender bag, 4 bright salmon bags, 1 plaid gray bag.
bright green bags contain 3 bright aqua bags, 3 dull maroon bags, 4 dark brown bags.
dark gray bags contain 5 muted purple bags, 2 striped blue bags, 4 faded lavender bags.
bright crimson bags contain 2 striped olive bags, 3 muted blue bags.
muted cyan bags contain 3 shiny tomato bags.
light yellow bags contain 2 striped red bags, 4 shiny crimson bags.
pale aqua bags contain 5 shiny yellow bags, 3 dark lavender bags, 3 posh white bags.
clear red bags contain 1 dotted silver bag, 1 dull teal bag, 1 faded maroon bag, 1 dotted salmon bag.
pale red bags contain 2 faded gray bags.
dotted maroon bags contain 5 posh aqua bags, 3 dull silver bags.
dull blue bags contain 4 light crimson bags, 3 light lime bags, 1 dark orange bag, 5 light indigo bags.
posh turquoise bags contain 1 muted gold bag, 5 striped lavender bags, 3 dull salmon bags, 5 vibrant chartreuse bags.
striped magenta bags contain 1 posh silver bag, 5 dark brown bags.
pale blue bags contain 2 muted gold bags, 4 vibrant brown bags, 1 light lavender bag.
vibrant violet bags contain 5 bright red bags.
faded fuchsia bags contain 2 light lime bags, 4 bright lime bags, 3 pale violet bags.
shiny coral bags contain 1 clear plum bag, 5 muted chartreuse bags, 1 muted violet bag, 5 striped yellow bags.
pale olive bags contain 4 plaid lime bags, 1 posh salmon bag.
wavy tan bags contain 3 faded gray bags.
faded chartreuse bags contain 3 dim coral bags, 1 mirrored bronze bag, 3 posh bronze bags.
mirrored brown bags contain 1 faded violet bag, 4 dull maroon bags, 5 dotted magenta bags.
clear white bags contain 5 muted magenta bags, 4 dull magenta bags, 3 pale plum bags, 4 drab indigo bags.
drab maroon bags contain 2 clear beige bags, 3 wavy beige bags, 5 faded purple bags.
striped silver bags contain 3 drab tomato bags.
faded plum bags contain 1 clear teal bag, 3 bright aqua bags.
plaid violet bags contain 2 drab violet bags, 4 muted turquoise bags, 5 muted indigo bags.
clear black bags contain 5 muted fuchsia bags, 1 muted coral bag, 2 light black bags.
vibrant maroon bags contain 1 dark lavender bag, 1 pale crimson bag, 4 bright indigo bags, 5 mirrored maroon bags.
drab indigo bags contain 2 dim coral bags, 1 drab green bag, 2 shiny lavender bags.
drab olive bags contain 2 dark aqua bags, 4 striped brown bags.
dull crimson bags contain 3 dull cyan bags.
wavy teal bags contain 4 striped orange bags, 2 drab cyan bags.
dark red bags contain 2 dull maroon bags, 4 muted plum bags, 4 dull plum bags.
striped salmon bags contain 3 bright red bags, 1 light aqua bag, 4 wavy gold bags.
mirrored tan bags contain 5 dotted olive bags, 2 dim tomato bags, 2 mirrored tomato bags, 4 clear teal bags.
striped white bags contain 2 pale coral bags, 2 shiny green bags.
shiny tomato bags contain 5 pale coral bags, 5 dull beige bags.
vibrant indigo bags contain 2 dim black bags, 4 dim blue bags, 3 dim white bags.
wavy lavender bags contain 4 faded bronze bags, 4 muted red bags, 3 light lime bags, 4 muted gold bags.
shiny turquoise bags contain 2 dull red bags, 5 faded gray bags, 1 muted turquoise bag.
shiny lavender bags contain 5 bright aqua bags.
posh tan bags contain 1 shiny yellow bag, 3 drab magenta bags.
light green bags contain 4 bright red bags, 1 vibrant coral bag.
drab black bags contain 5 faded tomato bags, 3 dotted chartreuse bags.
clear chartreuse bags contain 3 wavy bronze bags, 4 plaid purple bags, 3 dark orange bags.
dull black bags contain 1 wavy teal bag, 3 light lavender bags, 2 striped indigo bags.
wavy black bags contain 2 clear orange bags, 4 muted purple bags.
pale plum bags contain 1 bright coral bag, 1 drab tan bag, 1 plaid fuchsia bag, 1 dotted fuchsia bag.
dotted violet bags contain 3 bright black bags.
posh red bags contain 3 bright black bags.
plaid lime bags contain 5 posh beige bags, 1 dotted turquoise bag.
wavy aqua bags contain 1 dark yellow bag, 3 drab indigo bags.
dim magenta bags contain 3 dark violet bags.
drab aqua bags contain 5 posh orange bags, 1 dark silver bag, 4 plaid purple bags, 2 wavy teal bags.
dull brown bags contain 4 light lime bags.
striped orange bags contain 5 light crimson bags, 3 muted tan bags, 5 dotted coral bags, 3 plaid blue bags.
muted brown bags contain 1 posh blue bag, 4 dotted magenta bags, 3 dull coral bags.
faded blue bags contain 5 striped black bags, 1 vibrant yellow bag.
plaid indigo bags contain 3 dark brown bags, 5 light purple bags, 4 light aqua bags, 3 light green bags.
plaid turquoise bags contain 5 dotted teal bags.
light turquoise bags contain 2 dull salmon bags, 5 dotted tan bags.
dim purple bags contain 4 muted white bags, 5 drab purple bags.
pale coral bags contain 5 posh gray bags.
clear lime bags contain 3 dim magenta bags, 3 plaid tomato bags, 1 drab magenta bag, 3 shiny purple bags.
dim black bags contain 3 clear gold bags, 4 muted violet bags.
light maroon bags contain 4 muted yellow bags, 1 pale cyan bag, 2 mirrored turquoise bags, 4 dull lavender bags.
clear magenta bags contain 2 shiny magenta bags, 2 muted chartreuse bags.
striped bronze bags contain 5 clear tan bags, 1 drab lavender bag, 2 pale crimson bags.
dark salmon bags contain 1 vibrant plum bag, 5 drab tan bags, 4 drab coral bags, 4 dull tan bags.
vibrant salmon bags contain 2 muted olive bags.
dim gold bags contain 2 dim olive bags, 5 plaid olive bags, 2 posh orange bags.
wavy chartreuse bags contain 4 shiny yellow bags, 4 vibrant blue bags.
vibrant brown bags contain 3 striped brown bags, 4 muted red bags, 2 shiny indigo bags.
plaid maroon bags contain 2 muted teal bags, 2 pale yellow bags, 2 bright beige bags, 5 striped yellow bags.
dim indigo bags contain 4 dull tomato bags, 4 clear cyan bags, 2 shiny salmon bags, 1 bright aqua bag.
muted red bags contain 3 dull tan bags, 4 dull magenta bags, 1 bright aqua bag.
posh beige bags contain 5 shiny black bags, 3 dotted magenta bags, 3 drab blue bags, 2 muted coral bags.
pale fuchsia bags contain 3 dark brown bags, 5 posh gold bags.
dark bronze bags contain 1 dim green bag, 5 posh chartreuse bags.
dim coral bags contain 3 dull coral bags, 3 striped brown bags.
drab crimson bags contain 2 dark bronze bags, 4 shiny indigo bags, 3 dull tan bags.
bright indigo bags contain 3 bright blue bags.
pale yellow bags contain 5 dim aqua bags, 1 vibrant brown bag, 2 vibrant tan bags, 3 wavy lavender bags.
drab salmon bags contain 1 dotted indigo bag, 3 muted chartreuse bags, 5 dark olive bags.
muted orange bags contain 4 faded lime bags, 2 dull coral bags, 5 vibrant magenta bags, 4 dull magenta bags.
striped gold bags contain 2 dull silver bags, 5 bright lavender bags, 5 dim teal bags, 5 dark coral bags.
posh chartreuse bags contain 3 dim teal bags, 5 light aqua bags.
shiny blue bags contain 3 dull tan bags, 5 muted magenta bags.
muted silver bags contain 3 wavy blue bags, 2 dim teal bags, 5 muted bronze bags.
shiny bronze bags contain 1 light green bag, 4 vibrant magenta bags.
wavy coral bags contain no other bags.
shiny orange bags contain 2 muted purple bags.
posh teal bags contain 4 clear plum bags.
striped turquoise bags contain 3 muted indigo bags.
dim bronze bags contain 2 shiny silver bags, 1 light silver bag, 2 dim indigo bags, 4 dim tomato bags.
plaid white bags contain 4 drab turquoise bags.
wavy indigo bags contain 3 clear gold bags, 5 mirrored bronze bags.
faded teal bags contain 4 mirrored white bags.
shiny fuchsia bags contain 3 drab indigo bags.
dim red bags contain 3 clear bronze bags.
dotted brown bags contain 4 wavy maroon bags, 5 drab green bags, 3 dark purple bags.
dark tomato bags contain 3 vibrant coral bags, 5 dull coral bags, 2 drab cyan bags, 1 posh blue bag.
clear teal bags contain 3 dark white bags.
dark silver bags contain 3 dark cyan bags, 4 plaid salmon bags.
wavy fuchsia bags contain 4 bright brown bags, 4 bright aqua bags, 5 light orange bags.
light bronze bags contain 4 clear plum bags.
striped purple bags contain 1 dim indigo bag.
clear tomato bags contain 4 mirrored tomato bags, 3 muted indigo bags, 1 striped tan bag.
muted turquoise bags contain 5 faded beige bags, 4 clear crimson bags, 2 bright teal bags.
dull cyan bags contain 5 mirrored aqua bags, 2 shiny aqua bags, 3 light black bags, 4 bright coral bags.
plaid crimson bags contain 2 mirrored teal bags, 2 dull fuchsia bags.
shiny maroon bags contain 1 posh gold bag.
dim white bags contain 5 striped brown bags, 2 dull magenta bags, 5 plaid tan bags.
muted green bags contain 2 dull magenta bags, 5 clear cyan bags.
plaid teal bags contain 2 dark tan bags, 3 pale lime bags.
dotted lavender bags contain 2 posh aqua bags, 3 dull cyan bags.
light salmon bags contain 5 dark silver bags.
faded white bags contain 2 wavy maroon bags, 3 dull cyan bags.
dull tomato bags contain 2 dim aqua bags, 4 posh lavender bags, 1 faded red bag.
dark olive bags contain 5 clear bronze bags, 2 drab plum bags.
pale indigo bags contain 2 mirrored beige bags, 5 wavy turquoise bags, 4 striped green bags, 2 dotted lavender bags.
plaid purple bags contain 1 light lime bag.
clear purple bags contain 3 vibrant white bags.
dark yellow bags contain 2 pale olive bags, 4 pale cyan bags, 5 bright teal bags.
muted beige bags contain 2 posh lime bags, 5 shiny gray bags, 2 dull blue bags.
vibrant orange bags contain 5 posh crimson bags, 4 light chartreuse bags.
light magenta bags contain 2 plaid maroon bags, 1 posh beige bag, 5 pale salmon bags.
dotted crimson bags contain 5 dark chartreuse bags.
striped coral bags contain 2 dim aqua bags.
striped aqua bags contain 3 posh salmon bags, 3 dull red bags.
mirrored salmon bags contain 5 bright red bags, 2 light green bags, 3 clear black bags, 5 posh brown bags.
posh white bags contain 4 drab violet bags, 2 dotted silver bags.
posh blue bags contain 4 dull maroon bags, 3 vibrant coral bags.
dim orange bags contain 2 dull olive bags.
shiny teal bags contain 1 faded tomato bag, 4 muted violet bags.
mirrored maroon bags contain 3 dull blue bags.
dark lavender bags contain 1 drab red bag, 3 shiny indigo bags, 4 faded beige bags, 1 drab turquoise bag.
shiny olive bags contain 3 dark violet bags, 1 striped gold bag, 2 mirrored lime bags.
bright violet bags contain 2 wavy bronze bags, 3 drab olive bags, 5 mirrored olive bags, 2 wavy lavender bags.
clear olive bags contain 5 faded turquoise bags.
mirrored lavender bags contain 1 light white bag, 4 light purple bags, 3 wavy lavender bags, 2 shiny lime bags.
pale turquoise bags contain 4 dark tan bags.
shiny salmon bags contain 1 shiny gold bag, 5 drab turquoise bags.
vibrant gray bags contain 3 posh brown bags.
dark indigo bags contain 1 mirrored black bag, 5 dull beige bags, 4 shiny beige bags, 3 drab lavender bags.
light teal bags contain 5 dark olive bags, 5 vibrant chartreuse bags, 3 plaid salmon bags, 5 light yellow bags.
clear violet bags contain 3 light crimson bags.
clear tan bags contain 3 striped orange bags, 4 wavy lavender bags, 3 striped silver bags.
clear bronze bags contain 2 plaid beige bags.
clear gray bags contain 4 dotted cyan bags, 4 vibrant plum bags.
drab cyan bags contain 1 light aqua bag, 1 drab teal bag, 3 bright orange bags, 3 dark white bags.
plaid beige bags contain 3 dull green bags.
wavy gold bags contain 4 shiny olive bags, 3 bright tan bags.
clear aqua bags contain 3 posh chartreuse bags, 4 drab silver bags, 5 clear gray bags.
bright chartreuse bags contain 2 light violet bags, 3 vibrant gray bags.
plaid black bags contain 2 posh gray bags.
light beige bags contain 4 dotted olive bags, 5 dull olive bags, 1 faded orange bag.
mirrored teal bags contain 4 mirrored aqua bags.
bright magenta bags contain 1 mirrored magenta bag, 3 bright blue bags, 1 vibrant blue bag, 2 drab gold bags.
dim maroon bags contain 4 light bronze bags, 5 clear violet bags.
light lime bags contain 4 plaid indigo bags.
posh lavender bags contain 4 dark brown bags.
clear beige bags contain 4 posh silver bags, 3 dull coral bags, 2 posh gray bags.
drab bronze bags contain 4 plaid maroon bags.
mirrored purple bags contain 3 dim magenta bags.
dark magenta bags contain 4 faded maroon bags, 1 drab crimson bag, 5 dotted brown bags, 2 bright teal bags.
dim brown bags contain 3 muted olive bags, 5 drab green bags, 1 mirrored olive bag.
dark plum bags contain 2 vibrant tan bags.
bright turquoise bags contain 1 mirrored aqua bag, 3 clear plum bags.
muted black bags contain 5 faded cyan bags, 5 pale tan bags, 2 dotted chartreuse bags.
dotted gray bags contain 3 posh plum bags.
vibrant black bags contain 2 vibrant magenta bags, 5 faded cyan bags.
mirrored cyan bags contain 2 clear cyan bags, 4 light aqua bags, 5 drab blue bags, 1 drab gold bag.
wavy purple bags contain 5 striped magenta bags, 3 clear maroon bags, 1 mirrored green bag, 1 pale black bag.
drab blue bags contain 3 mirrored lime bags, 1 mirrored blue bag.
clear maroon bags contain 5 bright orange bags.
shiny cyan bags contain 2 clear gray bags, 5 pale crimson bags.
pale cyan bags contain 2 wavy turquoise bags, 5 wavy salmon bags.
plaid gold bags contain 1 clear lavender bag, 1 bright beige bag.
mirrored lime bags contain 2 dull tan bags, 3 shiny beige bags.
drab green bags contain 1 vibrant yellow bag.
dull red bags contain 5 plaid blue bags, 5 clear brown bags, 3 pale salmon bags, 2 dark orange bags.
bright beige bags contain 4 dull silver bags, 5 vibrant brown bags, 4 drab red bags, 2 pale violet bags.
clear silver bags contain 4 drab indigo bags, 2 clear salmon bags.
posh bronze bags contain 5 bright indigo bags, 5 dotted purple bags, 1 dark violet bag, 2 dark orange bags.
posh salmon bags contain 5 bright red bags, 3 striped green bags, 3 dark brown bags.
clear cyan bags contain 5 dark chartreuse bags, 1 bright indigo bag, 4 pale yellow bags, 2 vibrant coral bags.
mirrored blue bags contain 2 vibrant white bags.
mirrored yellow bags contain 5 dotted gray bags, 4 dull maroon bags, 2 striped violet bags, 5 clear tomato bags.
striped teal bags contain 2 clear black bags, 3 pale coral bags.
faded orange bags contain 2 dark bronze bags.
mirrored indigo bags contain 3 light tomato bags, 2 shiny crimson bags.
pale green bags contain 4 light chartreuse bags.
plaid cyan bags contain 4 plaid fuchsia bags, 2 shiny teal bags, 3 dotted fuchsia bags, 3 dim red bags.
muted gold bags contain 2 dull tan bags, 1 faded bronze bag, 4 dull maroon bags.
wavy green bags contain 5 pale coral bags, 1 dull blue bag, 4 drab blue bags, 1 striped tan bag.
light chartreuse bags contain 4 striped brown bags, 5 plaid purple bags, 4 drab cyan bags, 3 dull plum bags.
dotted cyan bags contain 4 shiny black bags.
light purple bags contain no other bags.
dotted aqua bags contain 4 light gray bags, 2 light purple bags, 5 mirrored lime bags.
drab gold bags contain 2 bright green bags, 5 bright indigo bags.
posh gray bags contain 5 bright orange bags, 5 bright blue bags.
striped red bags contain 4 drab green bags, 1 clear cyan bag.
dotted bronze bags contain 5 light orange bags.
muted plum bags contain 2 bright black bags, 3 dotted tomato bags, 2 vibrant brown bags.
mirrored black bags contain 3 plaid chartreuse bags, 2 shiny indigo bags, 2 shiny beige bags.
drab lavender bags contain 5 drab cyan bags, 1 muted purple bag, 1 wavy red bag, 3 drab crimson bags.
vibrant turquoise bags contain 3 shiny beige bags, 3 striped brown bags, 5 dim teal bags.
muted tan bags contain 1 plaid purple bag, 3 shiny beige bags, 1 drab gold bag.
pale beige bags contain 5 bright silver bags.
wavy olive bags contain 4 dotted turquoise bags, 4 dull silver bags, 1 bright gold bag.
dim olive bags contain 5 light lavender bags, 4 shiny tomato bags, 4 clear cyan bags.
wavy salmon bags contain 4 bright aqua bags.
dotted gold bags contain 3 shiny red bags, 3 dull fuchsia bags.
shiny violet bags contain 3 dotted tomato bags, 1 drab coral bag.
striped plum bags contain 4 drab beige bags, 3 clear tan bags, 5 light aqua bags, 1 shiny fuchsia bag.
clear lavender bags contain 2 bright aqua bags, 3 dull silver bags, 3 bright green bags, 2 bright orange bags.
faded maroon bags contain 5 dark indigo bags, 1 posh fuchsia bag.
vibrant red bags contain 4 striped fuchsia bags, 3 drab orange bags, 1 clear brown bag, 1 plaid turquoise bag.
dull coral bags contain 2 dim teal bags, 3 faded bronze bags.
pale salmon bags contain 3 dull magenta bags, 1 light crimson bag.
dotted magenta bags contain 4 dull maroon bags, 2 bright lime bags, 4 plaid indigo bags, 4 faded cyan bags.
wavy gray bags contain 4 muted gray bags, 3 shiny magenta bags, 1 posh teal bag.
light red bags contain 4 shiny chartreuse bags.
dim blue bags contain 4 vibrant orange bags.
muted bronze bags contain 5 mirrored aqua bags, 4 dim green bags.
drab lime bags contain 1 drab cyan bag, 3 pale crimson bags, 4 bright green bags, 3 drab lavender bags.
light white bags contain 5 bright green bags.
bright teal bags contain 4 shiny brown bags, 4 dark silver bags.
striped beige bags contain 2 shiny magenta bags.
wavy magenta bags contain 5 pale bronze bags, 5 pale plum bags, 3 muted silver bags.
dark orange bags contain 1 drab tomato bag, 3 striped brown bags, 1 dim teal bag, 5 bright beige bags.
striped indigo bags contain 1 vibrant gold bag, 1 shiny green bag.
clear coral bags contain 2 shiny gray bags.
faded yellow bags contain 4 faded gold bags, 2 bright turquoise bags, 5 dark silver bags, 3 wavy coral bags.
dim plum bags contain 1 clear purple bag, 4 light brown bags.
mirrored turquoise bags contain 5 wavy indigo bags, 3 dark fuchsia bags, 5 plaid white bags, 2 dim turquoise bags.
posh black bags contain 2 striped black bags, 5 dim teal bags, 3 bright silver bags, 5 posh beige bags.
dotted fuchsia bags contain 1 faded turquoise bag, 2 shiny lavender bags, 4 posh salmon bags, 1 clear olive bag.
faded lavender bags contain 2 striped yellow bags, 1 posh lavender bag.
dim lime bags contain 2 wavy gray bags, 5 clear gray bags.
vibrant bronze bags contain 3 drab tomato bags, 5 bright tan bags.
dull plum bags contain 5 bright red bags, 4 dull magenta bags.
dim teal bags contain 4 light purple bags, 4 plaid lavender bags, 1 dull magenta bag.
dull yellow bags contain 4 vibrant orange bags, 1 dark tomato bag, 5 pale tan bags.
dull green bags contain 2 bright blue bags, 5 dull red bags.
light crimson bags contain 5 dull maroon bags, 4 muted gold bags.
dark black bags contain 1 dim silver bag, 3 plaid magenta bags.
bright lavender bags contain 4 muted fuchsia bags.
drab coral bags contain 4 shiny chartreuse bags, 3 posh yellow bags, 3 wavy indigo bags.
mirrored crimson bags contain 3 posh maroon bags, 5 striped olive bags, 3 mirrored magenta bags.
muted coral bags contain 3 wavy violet bags, 1 dotted chartreuse bag, 1 shiny beige bag.
vibrant gold bags contain 2 dull orange bags, 1 clear chartreuse bag.
wavy orange bags contain 5 dark bronze bags.
mirrored white bags contain 5 clear gold bags, 3 drab tomato bags, 4 dotted bronze bags, 3 striped orange bags.
clear gold bags contain 3 drab indigo bags, 4 wavy violet bags, 2 shiny salmon bags, 4 light brown bags.
shiny magenta bags contain 5 drab silver bags, 2 muted gold bags.
dim violet bags contain 1 posh lime bag, 4 shiny orange bags, 2 posh chartreuse bags.
striped olive bags contain 4 plaid indigo bags, 5 dim chartreuse bags, 4 clear lavender bags.
plaid gray bags contain 3 shiny gold bags, 2 dull coral bags.
clear crimson bags contain 4 shiny aqua bags, 3 light crimson bags, 5 dim chartreuse bags.
drab silver bags contain 1 dim teal bag, 3 faded cyan bags, 1 shiny indigo bag.
mirrored green bags contain 5 dotted lime bags, 4 pale cyan bags.
bright aqua bags contain no other bags.
bright plum bags contain 4 dim aqua bags, 2 dull crimson bags, 1 wavy maroon bag.
vibrant lavender bags contain 1 plaid tan bag, 3 vibrant brown bags, 3 drab gold bags, 4 faded red bags.
pale white bags contain 3 bright brown bags, 4 mirrored beige bags.
plaid lavender bags contain 1 dull magenta bag, 2 dull silver bags, 1 shiny indigo bag.
bright salmon bags contain 1 striped coral bag, 4 plaid lavender bags, 1 muted red bag, 1 drab red bag.
plaid olive bags contain 5 faded turquoise bags, 4 dim green bags, 2 striped beige bags.
wavy plum bags contain 1 clear lavender bag, 2 faded brown bags.
clear fuchsia bags contain 1 muted bronze bag.
wavy turquoise bags contain 5 shiny lime bags, 1 drab olive bag, 4 dim white bags, 1 dotted gray bag.
vibrant aqua bags contain 2 faded lavender bags.
dotted white bags contain 3 muted crimson bags, 5 mirrored white bags, 1 mirrored fuchsia bag.
bright purple bags contain 2 dotted chartreuse bags, 4 posh cyan bags, 3 bright plum bags.
light aqua bags contain 1 plaid lavender bag, 3 wavy coral bags, 5 shiny indigo bags.
drab yellow bags contain 4 shiny teal bags, 2 dotted green bags, 5 vibrant silver bags, 3 dotted turquoise bags.
mirrored olive bags contain 1 dull plum bag.
light olive bags contain 1 shiny coral bag, 4 drab white bags, 3 dim turquoise bags, 4 dull gold bags.
shiny indigo bags contain no other bags.
dull gold bags contain 3 dark indigo bags.
bright tomato bags contain 5 muted blue bags.
faded purple bags contain 4 bright orange bags, 2 faded violet bags.
drab magenta bags contain 3 wavy lavender bags, 2 drab cyan bags, 2 clear beige bags, 4 bright indigo bags.
striped lime bags contain 4 light tan bags.
light gold bags contain 2 pale plum bags.
striped black bags contain 1 plaid salmon bag, 2 plaid beige bags, 4 dotted teal bags, 2 posh chartreuse bags.
faded tomato bags contain 2 striped yellow bags, 4 muted red bags.
dull fuchsia bags contain 5 dotted olive bags, 2 muted purple bags.
pale purple bags contain 4 posh silver bags, 4 wavy yellow bags.
bright olive bags contain 5 shiny fuchsia bags, 5 dull crimson bags, 5 drab red bags, 5 posh turquoise bags.
vibrant fuchsia bags contain 1 vibrant beige bag, 5 shiny magenta bags.
faded turquoise bags contain 5 light lime bags, 4 dark white bags.
plaid orange bags contain 5 vibrant coral bags, 4 light crimson bags, 4 plaid chartreuse bags, 1 dull green bag.
posh indigo bags contain 3 wavy green bags, 2 shiny orange bags, 5 faded violet bags, 2 dotted coral bags.
mirrored red bags contain 4 mirrored olive bags, 1 dark silver bag, 1 dull red bag.
dim salmon bags contain 1 striped salmon bag, 5 faded gray bags.
dim cyan bags contain 3 wavy olive bags, 5 drab purple bags, 3 mirrored bronze bags.
light blue bags contain 2 striped bronze bags, 4 dull white bags, 1 posh bronze bag.
dull turquoise bags contain 4 striped red bags, 1 light lavender bag, 5 plaid bronze bags, 1 mirrored brown bag.
vibrant coral bags contain 1 bright orange bag.
striped cyan bags contain 2 dark white bags, 4 drab red bags, 2 plaid salmon bags.
muted tomato bags contain 4 drab red bags, 3 vibrant silver bags, 4 clear fuchsia bags, 3 wavy white bags.
dotted red bags contain 1 light blue bag.
dark beige bags contain 2 posh lime bags, 3 striped black bags.
dark cyan bags contain 1 dim chartreuse bag, 2 shiny beige bags, 4 dotted magenta bags, 4 light chartreuse bags.
dull lime bags contain 3 muted chartreuse bags.
light brown bags contain 3 mirrored brown bags.
vibrant magenta bags contain 1 dim green bag.
shiny brown bags contain 5 bright brown bags, 3 faded cyan bags, 5 clear tan bags, 2 plaid maroon bags.
drab purple bags contain 1 shiny indigo bag, 4 striped yellow bags.

64
2020/d07/ex2/ex2.py Executable file
View file

@ -0,0 +1,64 @@
#!/usr/bin/env python
import re
import sys
from dataclasses import dataclass
from typing import Dict, List, Set, Tuple
@dataclass(eq=True, frozen=True) # Hashable
class ColorInfo:
num: int
color: str
Graph = Dict[str, Set[ColorInfo]]
def extract_info(line: str) -> Tuple[str, Set[ColorInfo]]:
color_pattern = re.compile("(.*) contain ")
match = color_pattern.search(line)
assert match is not None
color = match.group(1).replace("bags", "bag")
line = line[match.end() : -1] # Remove period at end of line
if line == "no other bags":
return color, set()
colors: Set[ColorInfo] = set()
pattern = re.compile("([0-9]+) (.*)")
for col in line.split(", "):
match = pattern.search(col)
assert match is not None
colors |= {
ColorInfo(int(match.group(1)), match.group(2).replace("bags", "bag"))
}
return color, colors
def to_graph(raw: List[str]) -> Graph:
return {color: inside for color, inside in map(extract_info, raw)}
def num_bags(graph: Graph, col: str) -> int:
return sum(
contained.num * (1 + num_bags(graph, contained.color))
for contained in graph[col]
)
def solve(raw: List[str]) -> int:
graph = to_graph(raw)
return num_bags(graph, "shiny gold bag")
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

594
2020/d07/ex2/input Normal file
View file

@ -0,0 +1,594 @@
shiny aqua bags contain 1 dark white bag.
muted blue bags contain 1 vibrant lavender bag, 4 dotted silver bags, 2 dim indigo bags.
drab gray bags contain 5 mirrored white bags, 1 light green bag, 5 shiny lavender bags, 5 faded aqua bags.
muted indigo bags contain 4 muted chartreuse bags, 2 dotted teal bags.
drab white bags contain 2 dull fuchsia bags, 1 vibrant bronze bag.
dim lavender bags contain 4 muted tan bags.
dotted tomato bags contain 1 mirrored lime bag, 2 vibrant white bags.
clear orange bags contain 5 clear violet bags, 2 dull beige bags, 2 dark chartreuse bags.
bright lime bags contain no other bags.
striped brown bags contain 3 bright orange bags.
vibrant green bags contain 3 shiny fuchsia bags.
plaid tomato bags contain 3 faded chartreuse bags, 2 wavy salmon bags, 1 faded white bag, 3 mirrored maroon bags.
drab beige bags contain 2 shiny bronze bags, 4 pale violet bags, 3 bright tomato bags, 4 pale red bags.
posh green bags contain 2 dull lavender bags, 4 clear plum bags, 2 dark gray bags.
dull maroon bags contain 3 dull magenta bags, 1 dull tan bag, 1 faded cyan bag, 5 dull silver bags.
faded crimson bags contain 2 muted purple bags, 4 dotted olive bags, 5 drab silver bags.
wavy bronze bags contain 3 dark orange bags, 2 dark brown bags, 5 bright silver bags.
dark turquoise bags contain 5 dull plum bags.
dull lavender bags contain 4 dotted maroon bags, 3 muted brown bags, 4 drab black bags, 4 dull cyan bags.
dotted plum bags contain 1 shiny bronze bag, 3 clear brown bags, 3 muted indigo bags.
dull white bags contain 3 clear tan bags, 5 shiny gold bags, 2 drab crimson bags.
dull teal bags contain 2 bright tomato bags.
shiny crimson bags contain 3 light green bags, 5 striped brown bags, 3 faded fuchsia bags.
wavy brown bags contain 1 drab crimson bag, 2 wavy indigo bags.
dark tan bags contain 2 faded gray bags, 4 shiny salmon bags.
shiny red bags contain 4 dull chartreuse bags, 5 pale tomato bags.
bright orange bags contain no other bags.
wavy yellow bags contain 5 light indigo bags, 5 dark gray bags, 5 plaid indigo bags, 4 faded red bags.
faded bronze bags contain 4 faded cyan bags, 5 shiny beige bags, 5 muted red bags.
dull bronze bags contain 1 mirrored beige bag, 5 muted violet bags, 1 wavy lime bag.
dark lime bags contain 2 drab maroon bags, 5 bright indigo bags, 4 shiny black bags, 5 dotted turquoise bags.
drab red bags contain 5 bright red bags, 2 vibrant brown bags.
dotted salmon bags contain 3 vibrant turquoise bags, 2 dull beige bags, 3 light turquoise bags.
dull gray bags contain 3 striped green bags, 3 wavy coral bags, 1 dark gray bag, 2 light indigo bags.
faded black bags contain 4 muted fuchsia bags, 4 wavy coral bags, 1 drab tomato bag.
muted magenta bags contain 2 posh chartreuse bags, 4 pale violet bags.
light tan bags contain 2 posh turquoise bags, 3 vibrant white bags, 1 light black bag.
dark blue bags contain 3 plaid indigo bags, 2 posh black bags.
dull indigo bags contain 4 light gray bags, 3 dotted tan bags, 4 dull coral bags.
dim fuchsia bags contain 3 vibrant yellow bags, 3 mirrored cyan bags, 4 mirrored brown bags.
shiny beige bags contain 2 dull silver bags, 3 bright lime bags, 5 dull magenta bags.
light cyan bags contain 3 vibrant violet bags, 2 mirrored tomato bags, 2 vibrant coral bags, 4 mirrored silver bags.
clear turquoise bags contain 4 drab tomato bags, 3 shiny gold bags, 4 drab gold bags.
pale teal bags contain 2 wavy maroon bags, 2 dotted olive bags, 4 shiny white bags, 2 drab turquoise bags.
dark purple bags contain 1 wavy indigo bag, 3 bright black bags, 3 dotted teal bags.
bright white bags contain 5 wavy red bags, 2 mirrored cyan bags, 3 drab green bags.
mirrored aqua bags contain 1 faded violet bag, 5 dotted purple bags.
shiny lime bags contain 4 dark aqua bags.
pale bronze bags contain 1 clear crimson bag.
vibrant white bags contain 5 plaid lavender bags, 1 drab red bag, 4 vibrant brown bags.
plaid tan bags contain 5 dim crimson bags.
posh olive bags contain 3 bright red bags.
plaid brown bags contain 5 vibrant turquoise bags.
mirrored tomato bags contain 2 dotted chartreuse bags, 3 light aqua bags, 3 posh beige bags.
plaid blue bags contain 5 striped green bags, 1 plaid purple bag, 4 muted gold bags.
shiny tan bags contain 5 striped coral bags, 1 dull brown bag.
shiny gold bags contain 1 dull magenta bag, 5 dark white bags, 4 faded turquoise bags.
dull salmon bags contain 2 plaid gold bags, 2 light indigo bags.
striped tomato bags contain 2 striped tan bags, 4 light blue bags, 4 drab tan bags.
drab tomato bags contain 3 dim teal bags, 4 striped yellow bags, 3 bright red bags.
faded olive bags contain 1 drab plum bag, 1 pale aqua bag, 3 light blue bags.
dotted indigo bags contain 2 clear tomato bags.
dark white bags contain 5 light aqua bags, 2 dim teal bags, 2 muted fuchsia bags, 5 light purple bags.
dull orange bags contain 4 pale gold bags, 5 posh brown bags, 2 mirrored brown bags, 3 dark bronze bags.
bright maroon bags contain 1 mirrored yellow bag, 4 light teal bags.
bright silver bags contain 1 vibrant coral bag, 3 dim teal bags, 5 light purple bags.
muted olive bags contain 5 plaid orange bags, 1 muted magenta bag.
dull silver bags contain no other bags.
pale maroon bags contain 2 pale bronze bags.
light gray bags contain 4 vibrant yellow bags, 2 pale red bags.
drab teal bags contain 2 light crimson bags, 3 vibrant brown bags, 3 vibrant tan bags.
bright gold bags contain 1 wavy red bag, 5 wavy coral bags.
plaid chartreuse bags contain 2 dim coral bags, 4 drab silver bags, 5 dim chartreuse bags, 3 light purple bags.
clear blue bags contain 2 pale tomato bags, 4 dull gold bags, 4 dim fuchsia bags, 4 pale coral bags.
vibrant purple bags contain 5 faded orange bags.
plaid aqua bags contain 3 muted cyan bags, 2 wavy gray bags, 4 drab green bags, 4 pale beige bags.
muted lime bags contain 1 muted tan bag.
faded coral bags contain 3 drab turquoise bags, 1 shiny plum bag, 5 mirrored green bags, 5 clear white bags.
vibrant lime bags contain 5 posh coral bags.
faded green bags contain 3 pale orange bags, 5 dull turquoise bags, 1 mirrored crimson bag.
mirrored gray bags contain 5 dim indigo bags.
wavy maroon bags contain 4 mirrored bronze bags, 1 striped olive bag, 2 dull salmon bags, 3 shiny crimson bags.
dark violet bags contain 2 light purple bags.
dark green bags contain 2 dim cyan bags.
pale black bags contain 1 mirrored gold bag.
bright yellow bags contain 2 vibrant crimson bags, 3 plaid lime bags, 2 dotted gold bags.
muted teal bags contain 1 pale violet bag, 4 dull silver bags.
dim beige bags contain 5 wavy red bags.
muted purple bags contain 4 clear cyan bags.
plaid fuchsia bags contain 3 dark coral bags.
plaid bronze bags contain 5 plaid orange bags, 2 drab indigo bags.
faded indigo bags contain 1 dark chartreuse bag, 4 dull green bags, 1 mirrored magenta bag.
posh plum bags contain 3 dark chartreuse bags, 3 dotted turquoise bags, 4 dull maroon bags, 1 posh bronze bag.
pale gold bags contain 4 striped brown bags.
mirrored chartreuse bags contain 4 bright silver bags, 3 mirrored tomato bags, 4 wavy orange bags.
pale orange bags contain 2 posh fuchsia bags, 2 clear salmon bags, 2 bright green bags.
clear brown bags contain 4 light lime bags, 4 bright green bags, 5 pale yellow bags, 2 drab cyan bags.
shiny plum bags contain 5 vibrant gray bags, 3 bright blue bags, 5 dark tomato bags.
wavy white bags contain 4 plaid lime bags, 4 posh maroon bags, 5 drab lime bags, 1 vibrant crimson bag.
faded red bags contain 1 dull coral bag, 5 clear cyan bags, 4 plaid chartreuse bags, 3 plaid orange bags.
plaid red bags contain 5 pale blue bags, 4 light crimson bags, 3 faded fuchsia bags.
bright cyan bags contain 3 dark white bags, 2 light crimson bags, 1 bright aqua bag.
muted lavender bags contain 1 light green bag, 4 striped silver bags, 3 posh crimson bags.
wavy crimson bags contain 1 light purple bag, 4 bright blue bags, 2 dull coral bags, 1 wavy beige bag.
faded aqua bags contain 5 muted brown bags.
mirrored fuchsia bags contain 1 faded beige bag, 3 muted gold bags.
dark chartreuse bags contain 5 bright lime bags.
plaid green bags contain 4 mirrored tan bags, 1 mirrored tomato bag, 5 pale indigo bags, 1 mirrored plum bag.
shiny black bags contain 3 plaid chartreuse bags.
dotted purple bags contain 2 dim teal bags.
faded tan bags contain 2 bright fuchsia bags, 5 shiny fuchsia bags, 1 muted fuchsia bag, 1 mirrored brown bag.
drab brown bags contain 1 striped orange bag, 4 dotted tomato bags.
dull olive bags contain 1 striped black bag, 1 vibrant magenta bag.
mirrored plum bags contain 1 clear gold bag, 5 pale green bags.
dim tomato bags contain 4 drab gold bags, 2 shiny aqua bags.
light lavender bags contain 1 muted violet bag.
dim gray bags contain 3 light purple bags, 1 posh crimson bag, 1 faded brown bag.
muted aqua bags contain 4 dull beige bags, 4 dull red bags.
faded silver bags contain 1 mirrored cyan bag.
shiny green bags contain 5 dull maroon bags.
muted chartreuse bags contain 2 clear tan bags.
plaid plum bags contain 1 dotted lime bag, 4 clear brown bags, 4 dull red bags.
dotted silver bags contain 1 posh coral bag.
dim crimson bags contain 4 faded violet bags, 1 striped silver bag.
bright brown bags contain 1 bright coral bag, 3 posh brown bags, 4 drab tan bags.
wavy cyan bags contain 3 clear gold bags, 1 mirrored salmon bag, 3 bright fuchsia bags, 2 light bronze bags.
dull violet bags contain 5 striped white bags, 4 light blue bags, 4 dim black bags.
vibrant olive bags contain 2 vibrant coral bags.
bright coral bags contain 2 vibrant tan bags, 3 shiny indigo bags, 2 plaid indigo bags.
dim turquoise bags contain 1 pale violet bag.
striped crimson bags contain 2 faded gray bags.
clear green bags contain 3 mirrored olive bags, 3 shiny tomato bags.
faded violet bags contain 2 wavy coral bags, 2 dull tan bags, 1 dull silver bag, 1 bright orange bag.
pale chartreuse bags contain 4 shiny crimson bags, 2 clear bronze bags.
light plum bags contain 3 drab bronze bags, 1 bright bronze bag, 1 posh yellow bag.
pale tomato bags contain 1 dim teal bag, 5 drab cyan bags, 3 muted coral bags, 2 dim chartreuse bags.
plaid coral bags contain 1 striped tan bag, 3 vibrant cyan bags, 3 light beige bags, 2 dotted green bags.
bright gray bags contain 4 mirrored teal bags, 4 striped brown bags, 1 dim green bag, 4 clear cyan bags.
drab fuchsia bags contain 2 mirrored salmon bags, 4 posh orange bags, 3 faded crimson bags, 3 pale plum bags.
light tomato bags contain 2 dotted gold bags, 1 dotted bronze bag.
muted violet bags contain 2 light chartreuse bags.
drab tan bags contain 2 light green bags, 5 bright red bags, 4 shiny beige bags.
drab chartreuse bags contain 2 drab salmon bags, 2 dark brown bags, 4 clear turquoise bags.
drab violet bags contain 4 faded red bags.
posh cyan bags contain 4 bright violet bags.
posh orange bags contain 4 pale plum bags, 5 posh aqua bags.
plaid silver bags contain 1 dotted brown bag, 3 drab gold bags, 4 clear yellow bags.
mirrored silver bags contain 3 shiny beige bags, 1 drab silver bag.
faded gray bags contain no other bags.
wavy tomato bags contain 1 bright brown bag, 3 striped red bags, 2 vibrant maroon bags.
posh violet bags contain 2 dim aqua bags.
bright blue bags contain 5 light lime bags, 2 faded violet bags, 3 light aqua bags, 4 vibrant coral bags.
dark teal bags contain 5 muted fuchsia bags.
striped fuchsia bags contain 1 wavy turquoise bag, 5 wavy green bags, 4 posh gold bags.
posh maroon bags contain 2 dull red bags.
shiny purple bags contain 2 clear tan bags.
wavy lime bags contain 2 dark coral bags, 1 shiny gold bag.
wavy silver bags contain 4 dotted white bags.
shiny silver bags contain 2 plaid gold bags, 2 dim green bags, 5 plaid lime bags, 3 dull red bags.
wavy red bags contain 3 vibrant brown bags, 4 bright indigo bags.
dull chartreuse bags contain 4 dotted lime bags, 2 bright silver bags, 3 dull red bags, 4 wavy maroon bags.
vibrant silver bags contain 1 bright fuchsia bag, 3 drab lavender bags, 2 drab olive bags, 3 dotted teal bags.
striped gray bags contain 5 plaid orange bags, 1 wavy coral bag.
striped green bags contain 4 wavy coral bags, 4 shiny gold bags, 3 dark brown bags, 5 vibrant brown bags.
mirrored violet bags contain 3 dim silver bags, 1 posh tomato bag, 1 light salmon bag.
dull purple bags contain 1 light gray bag, 3 wavy yellow bags, 1 wavy salmon bag.
mirrored beige bags contain 4 dark cyan bags, 5 dull green bags.
posh lime bags contain 3 posh chartreuse bags.
vibrant tan bags contain 2 dull plum bags, 1 striped brown bag, 4 vibrant coral bags.
dotted orange bags contain 1 mirrored olive bag, 5 drab silver bags.
clear indigo bags contain 3 light lime bags, 4 dull coral bags.
pale gray bags contain 1 faded black bag, 3 dim green bags, 4 wavy lavender bags, 2 posh brown bags.
posh gold bags contain 5 dark tan bags, 2 dotted olive bags, 5 dark aqua bags.
striped chartreuse bags contain 2 dull magenta bags, 1 posh tomato bag.
mirrored bronze bags contain 2 faded fuchsia bags.
clear salmon bags contain 4 posh bronze bags, 5 clear plum bags, 5 dull blue bags.
posh purple bags contain 5 dim gray bags, 3 faded brown bags.
faded lime bags contain 5 dim turquoise bags, 3 dark indigo bags, 2 vibrant gray bags, 1 muted silver bag.
wavy beige bags contain 1 dark bronze bag, 4 dull plum bags, 4 mirrored silver bags.
clear yellow bags contain 2 vibrant teal bags.
vibrant plum bags contain 4 muted chartreuse bags, 4 posh silver bags.
striped yellow bags contain 2 dull maroon bags, 5 bright red bags, 2 posh chartreuse bags.
dark coral bags contain 3 dull tan bags.
dull magenta bags contain no other bags.
dark gold bags contain 1 dotted indigo bag, 4 shiny teal bags, 4 dotted silver bags.
dim tan bags contain 1 striped lavender bag, 1 shiny tomato bag.
muted maroon bags contain 2 dull salmon bags, 4 dim chartreuse bags, 3 bright aqua bags, 2 faded indigo bags.
vibrant tomato bags contain 2 dark silver bags, 3 plaid purple bags.
dotted lime bags contain 3 shiny crimson bags, 2 pale yellow bags.
muted fuchsia bags contain 1 dull tan bag.
bright tan bags contain 5 pale gold bags, 5 drab teal bags, 2 light blue bags.
dark crimson bags contain 4 shiny orange bags, 3 faded purple bags, 3 bright white bags.
striped tan bags contain 4 dotted turquoise bags, 4 drab lime bags, 5 dim teal bags.
posh fuchsia bags contain 2 dotted olive bags, 2 mirrored beige bags, 3 shiny bronze bags.
pale silver bags contain 4 vibrant lavender bags, 4 clear beige bags, 4 striped gold bags.
posh aqua bags contain 4 drab lime bags, 4 dull tan bags, 5 vibrant tan bags.
plaid salmon bags contain 5 dim coral bags, 2 wavy bronze bags.
mirrored orange bags contain 4 vibrant gray bags.
dim yellow bags contain 5 pale tan bags, 4 dark black bags.
dotted coral bags contain 4 dotted chartreuse bags, 2 bright red bags, 1 vibrant white bag, 1 vibrant brown bag.
muted crimson bags contain 4 striped orange bags, 5 pale yellow bags, 3 posh blue bags, 1 muted red bag.
striped lavender bags contain 3 striped brown bags.
striped maroon bags contain 2 shiny yellow bags.
vibrant blue bags contain 3 faded cyan bags, 1 shiny lime bag, 3 dark tomato bags.
pale lavender bags contain 4 plaid magenta bags, 4 striped blue bags.
dull tan bags contain 4 shiny indigo bags, 2 light purple bags, 4 faded cyan bags.
dotted beige bags contain 3 drab indigo bags.
light indigo bags contain 1 faded cyan bag, 5 bright aqua bags, 1 shiny indigo bag.
vibrant crimson bags contain 4 dotted fuchsia bags.
wavy blue bags contain 4 wavy teal bags, 1 dull blue bag.
vibrant chartreuse bags contain 4 striped orange bags.
vibrant cyan bags contain 5 wavy coral bags.
faded brown bags contain 5 faded turquoise bags.
faded magenta bags contain 1 dull indigo bag, 4 plaid aqua bags, 4 dim crimson bags.
mirrored coral bags contain 4 drab crimson bags, 2 light salmon bags, 2 clear indigo bags.
faded cyan bags contain no other bags.
dark brown bags contain 5 light purple bags.
wavy violet bags contain 3 dull coral bags, 1 bright aqua bag, 3 shiny lavender bags.
posh tomato bags contain 4 vibrant chartreuse bags, 4 mirrored teal bags.
pale crimson bags contain 1 plaid orange bag, 1 dark violet bag, 3 plaid lavender bags.
dark fuchsia bags contain 4 plaid beige bags, 2 plaid chartreuse bags.
plaid magenta bags contain 3 clear lavender bags, 5 mirrored brown bags, 5 shiny bronze bags.
striped blue bags contain 1 dull bronze bag, 1 dotted fuchsia bag, 1 light lavender bag, 1 clear turquoise bag.
dotted olive bags contain 4 dotted turquoise bags, 5 dotted bronze bags, 3 pale yellow bags, 4 pale red bags.
posh silver bags contain 3 pale violet bags, 1 plaid salmon bag, 1 posh coral bag.
dotted chartreuse bags contain 3 bright blue bags.
light coral bags contain 4 shiny fuchsia bags, 2 pale red bags, 1 muted silver bag, 2 bright cyan bags.
pale brown bags contain 5 light aqua bags.
dotted black bags contain 2 plaid purple bags, 1 mirrored aqua bag, 5 posh beige bags.
posh coral bags contain 3 dark aqua bags, 2 pale yellow bags, 5 plaid blue bags, 4 dim aqua bags.
shiny gray bags contain 1 bright gold bag, 1 muted bronze bag, 5 striped green bags, 5 shiny teal bags.
drab orange bags contain 5 plaid salmon bags, 2 vibrant beige bags.
plaid yellow bags contain 4 clear teal bags, 2 bright red bags.
striped violet bags contain 4 mirrored fuchsia bags, 4 vibrant white bags, 3 dim teal bags.
dim aqua bags contain 1 muted fuchsia bag, 1 dull tan bag.
light orange bags contain 2 bright red bags, 4 dark white bags, 1 dim chartreuse bag, 5 faded fuchsia bags.
faded salmon bags contain 5 wavy gray bags.
shiny yellow bags contain 2 vibrant plum bags, 3 dim teal bags, 1 plaid tan bag, 5 posh plum bags.
vibrant beige bags contain 2 wavy lavender bags, 4 posh chartreuse bags, 3 pale teal bags, 5 wavy lime bags.
light fuchsia bags contain 3 clear brown bags, 3 bright lavender bags.
pale magenta bags contain 4 posh silver bags.
dark maroon bags contain 3 drab turquoise bags.
faded beige bags contain 1 vibrant white bag, 4 drab red bags, 1 drab lavender bag.
bright bronze bags contain 1 pale bronze bag, 3 muted silver bags, 2 striped coral bags, 3 clear gray bags.
light silver bags contain 3 dotted lavender bags, 2 wavy lavender bags.
muted salmon bags contain 2 drab tan bags, 5 wavy tomato bags.
bright black bags contain 5 plaid tan bags.
dim chartreuse bags contain 5 muted gold bags, 5 bright blue bags, 5 faded cyan bags.
shiny white bags contain 4 bright tan bags.
bright red bags contain 3 dull silver bags.
dark aqua bags contain 2 dull red bags.
drab plum bags contain 4 muted brown bags, 5 muted plum bags.
muted yellow bags contain 5 light purple bags, 3 dotted silver bags, 3 faded turquoise bags.
light violet bags contain 1 pale red bag, 4 dim silver bags, 2 mirrored bronze bags.
pale lime bags contain 4 bright lavender bags.
pale tan bags contain 4 striped green bags, 2 dotted chartreuse bags.
dim green bags contain 1 light lime bag, 1 shiny beige bag.
mirrored gold bags contain 4 mirrored white bags.
dim silver bags contain 5 pale coral bags, 3 wavy coral bags.
dull aqua bags contain 3 posh indigo bags, 5 dotted coral bags, 1 dark salmon bag, 3 striped crimson bags.
posh yellow bags contain 1 dark bronze bag, 2 mirrored white bags, 2 light crimson bags.
mirrored magenta bags contain 1 bright violet bag, 2 drab lavender bags, 3 pale violet bags, 2 plaid salmon bags.
shiny chartreuse bags contain 2 dotted purple bags, 5 wavy red bags, 3 plaid beige bags.
light black bags contain 1 dark chartreuse bag, 3 faded tomato bags.
clear plum bags contain 5 vibrant brown bags, 3 dim coral bags, 4 mirrored brown bags, 1 faded black bag.
pale violet bags contain 2 dull tan bags.
bright fuchsia bags contain 4 dull orange bags.
dotted teal bags contain 5 bright red bags, 3 wavy red bags, 1 dull coral bag, 3 clear plum bags.
dotted blue bags contain 2 wavy beige bags, 3 muted purple bags.
muted gray bags contain 3 faded aqua bags, 1 shiny olive bag, 5 clear salmon bags, 1 vibrant violet bag.
dull beige bags contain 1 wavy lavender bag, 4 dark bronze bags, 5 dull tan bags.
drab turquoise bags contain 3 posh gray bags, 5 drab red bags.
vibrant yellow bags contain 2 shiny aqua bags, 4 light chartreuse bags.
posh brown bags contain 3 bright green bags, 5 posh lavender bags.
faded gold bags contain 4 vibrant maroon bags, 4 dotted purple bags.
dotted turquoise bags contain 5 clear plum bags, 3 muted gold bags, 4 dark violet bags.
dotted tan bags contain 5 dim aqua bags, 4 striped violet bags.
posh crimson bags contain 4 striped blue bags, 5 dull magenta bags, 2 bright coral bags.
muted white bags contain 5 dull olive bags.
vibrant teal bags contain 5 dotted turquoise bags, 1 striped tan bag, 1 drab tan bag.
dotted yellow bags contain 3 plaid turquoise bags, 2 posh yellow bags, 4 striped blue bags, 5 posh black bags.
posh magenta bags contain 5 mirrored black bags.
dotted green bags contain 4 dim crimson bags, 1 shiny lavender bag, 4 bright salmon bags, 1 plaid gray bag.
bright green bags contain 3 bright aqua bags, 3 dull maroon bags, 4 dark brown bags.
dark gray bags contain 5 muted purple bags, 2 striped blue bags, 4 faded lavender bags.
bright crimson bags contain 2 striped olive bags, 3 muted blue bags.
muted cyan bags contain 3 shiny tomato bags.
light yellow bags contain 2 striped red bags, 4 shiny crimson bags.
pale aqua bags contain 5 shiny yellow bags, 3 dark lavender bags, 3 posh white bags.
clear red bags contain 1 dotted silver bag, 1 dull teal bag, 1 faded maroon bag, 1 dotted salmon bag.
pale red bags contain 2 faded gray bags.
dotted maroon bags contain 5 posh aqua bags, 3 dull silver bags.
dull blue bags contain 4 light crimson bags, 3 light lime bags, 1 dark orange bag, 5 light indigo bags.
posh turquoise bags contain 1 muted gold bag, 5 striped lavender bags, 3 dull salmon bags, 5 vibrant chartreuse bags.
striped magenta bags contain 1 posh silver bag, 5 dark brown bags.
pale blue bags contain 2 muted gold bags, 4 vibrant brown bags, 1 light lavender bag.
vibrant violet bags contain 5 bright red bags.
faded fuchsia bags contain 2 light lime bags, 4 bright lime bags, 3 pale violet bags.
shiny coral bags contain 1 clear plum bag, 5 muted chartreuse bags, 1 muted violet bag, 5 striped yellow bags.
pale olive bags contain 4 plaid lime bags, 1 posh salmon bag.
wavy tan bags contain 3 faded gray bags.
faded chartreuse bags contain 3 dim coral bags, 1 mirrored bronze bag, 3 posh bronze bags.
mirrored brown bags contain 1 faded violet bag, 4 dull maroon bags, 5 dotted magenta bags.
clear white bags contain 5 muted magenta bags, 4 dull magenta bags, 3 pale plum bags, 4 drab indigo bags.
drab maroon bags contain 2 clear beige bags, 3 wavy beige bags, 5 faded purple bags.
striped silver bags contain 3 drab tomato bags.
faded plum bags contain 1 clear teal bag, 3 bright aqua bags.
plaid violet bags contain 2 drab violet bags, 4 muted turquoise bags, 5 muted indigo bags.
clear black bags contain 5 muted fuchsia bags, 1 muted coral bag, 2 light black bags.
vibrant maroon bags contain 1 dark lavender bag, 1 pale crimson bag, 4 bright indigo bags, 5 mirrored maroon bags.
drab indigo bags contain 2 dim coral bags, 1 drab green bag, 2 shiny lavender bags.
drab olive bags contain 2 dark aqua bags, 4 striped brown bags.
dull crimson bags contain 3 dull cyan bags.
wavy teal bags contain 4 striped orange bags, 2 drab cyan bags.
dark red bags contain 2 dull maroon bags, 4 muted plum bags, 4 dull plum bags.
striped salmon bags contain 3 bright red bags, 1 light aqua bag, 4 wavy gold bags.
mirrored tan bags contain 5 dotted olive bags, 2 dim tomato bags, 2 mirrored tomato bags, 4 clear teal bags.
striped white bags contain 2 pale coral bags, 2 shiny green bags.
shiny tomato bags contain 5 pale coral bags, 5 dull beige bags.
vibrant indigo bags contain 2 dim black bags, 4 dim blue bags, 3 dim white bags.
wavy lavender bags contain 4 faded bronze bags, 4 muted red bags, 3 light lime bags, 4 muted gold bags.
shiny turquoise bags contain 2 dull red bags, 5 faded gray bags, 1 muted turquoise bag.
shiny lavender bags contain 5 bright aqua bags.
posh tan bags contain 1 shiny yellow bag, 3 drab magenta bags.
light green bags contain 4 bright red bags, 1 vibrant coral bag.
drab black bags contain 5 faded tomato bags, 3 dotted chartreuse bags.
clear chartreuse bags contain 3 wavy bronze bags, 4 plaid purple bags, 3 dark orange bags.
dull black bags contain 1 wavy teal bag, 3 light lavender bags, 2 striped indigo bags.
wavy black bags contain 2 clear orange bags, 4 muted purple bags.
pale plum bags contain 1 bright coral bag, 1 drab tan bag, 1 plaid fuchsia bag, 1 dotted fuchsia bag.
dotted violet bags contain 3 bright black bags.
posh red bags contain 3 bright black bags.
plaid lime bags contain 5 posh beige bags, 1 dotted turquoise bag.
wavy aqua bags contain 1 dark yellow bag, 3 drab indigo bags.
dim magenta bags contain 3 dark violet bags.
drab aqua bags contain 5 posh orange bags, 1 dark silver bag, 4 plaid purple bags, 2 wavy teal bags.
dull brown bags contain 4 light lime bags.
striped orange bags contain 5 light crimson bags, 3 muted tan bags, 5 dotted coral bags, 3 plaid blue bags.
muted brown bags contain 1 posh blue bag, 4 dotted magenta bags, 3 dull coral bags.
faded blue bags contain 5 striped black bags, 1 vibrant yellow bag.
plaid indigo bags contain 3 dark brown bags, 5 light purple bags, 4 light aqua bags, 3 light green bags.
plaid turquoise bags contain 5 dotted teal bags.
light turquoise bags contain 2 dull salmon bags, 5 dotted tan bags.
dim purple bags contain 4 muted white bags, 5 drab purple bags.
pale coral bags contain 5 posh gray bags.
clear lime bags contain 3 dim magenta bags, 3 plaid tomato bags, 1 drab magenta bag, 3 shiny purple bags.
dim black bags contain 3 clear gold bags, 4 muted violet bags.
light maroon bags contain 4 muted yellow bags, 1 pale cyan bag, 2 mirrored turquoise bags, 4 dull lavender bags.
clear magenta bags contain 2 shiny magenta bags, 2 muted chartreuse bags.
striped bronze bags contain 5 clear tan bags, 1 drab lavender bag, 2 pale crimson bags.
dark salmon bags contain 1 vibrant plum bag, 5 drab tan bags, 4 drab coral bags, 4 dull tan bags.
vibrant salmon bags contain 2 muted olive bags.
dim gold bags contain 2 dim olive bags, 5 plaid olive bags, 2 posh orange bags.
wavy chartreuse bags contain 4 shiny yellow bags, 4 vibrant blue bags.
vibrant brown bags contain 3 striped brown bags, 4 muted red bags, 2 shiny indigo bags.
plaid maroon bags contain 2 muted teal bags, 2 pale yellow bags, 2 bright beige bags, 5 striped yellow bags.
dim indigo bags contain 4 dull tomato bags, 4 clear cyan bags, 2 shiny salmon bags, 1 bright aqua bag.
muted red bags contain 3 dull tan bags, 4 dull magenta bags, 1 bright aqua bag.
posh beige bags contain 5 shiny black bags, 3 dotted magenta bags, 3 drab blue bags, 2 muted coral bags.
pale fuchsia bags contain 3 dark brown bags, 5 posh gold bags.
dark bronze bags contain 1 dim green bag, 5 posh chartreuse bags.
dim coral bags contain 3 dull coral bags, 3 striped brown bags.
drab crimson bags contain 2 dark bronze bags, 4 shiny indigo bags, 3 dull tan bags.
bright indigo bags contain 3 bright blue bags.
pale yellow bags contain 5 dim aqua bags, 1 vibrant brown bag, 2 vibrant tan bags, 3 wavy lavender bags.
drab salmon bags contain 1 dotted indigo bag, 3 muted chartreuse bags, 5 dark olive bags.
muted orange bags contain 4 faded lime bags, 2 dull coral bags, 5 vibrant magenta bags, 4 dull magenta bags.
striped gold bags contain 2 dull silver bags, 5 bright lavender bags, 5 dim teal bags, 5 dark coral bags.
posh chartreuse bags contain 3 dim teal bags, 5 light aqua bags.
shiny blue bags contain 3 dull tan bags, 5 muted magenta bags.
muted silver bags contain 3 wavy blue bags, 2 dim teal bags, 5 muted bronze bags.
shiny bronze bags contain 1 light green bag, 4 vibrant magenta bags.
wavy coral bags contain no other bags.
shiny orange bags contain 2 muted purple bags.
posh teal bags contain 4 clear plum bags.
striped turquoise bags contain 3 muted indigo bags.
dim bronze bags contain 2 shiny silver bags, 1 light silver bag, 2 dim indigo bags, 4 dim tomato bags.
plaid white bags contain 4 drab turquoise bags.
wavy indigo bags contain 3 clear gold bags, 5 mirrored bronze bags.
faded teal bags contain 4 mirrored white bags.
shiny fuchsia bags contain 3 drab indigo bags.
dim red bags contain 3 clear bronze bags.
dotted brown bags contain 4 wavy maroon bags, 5 drab green bags, 3 dark purple bags.
dark tomato bags contain 3 vibrant coral bags, 5 dull coral bags, 2 drab cyan bags, 1 posh blue bag.
clear teal bags contain 3 dark white bags.
dark silver bags contain 3 dark cyan bags, 4 plaid salmon bags.
wavy fuchsia bags contain 4 bright brown bags, 4 bright aqua bags, 5 light orange bags.
light bronze bags contain 4 clear plum bags.
striped purple bags contain 1 dim indigo bag.
clear tomato bags contain 4 mirrored tomato bags, 3 muted indigo bags, 1 striped tan bag.
muted turquoise bags contain 5 faded beige bags, 4 clear crimson bags, 2 bright teal bags.
dull cyan bags contain 5 mirrored aqua bags, 2 shiny aqua bags, 3 light black bags, 4 bright coral bags.
plaid crimson bags contain 2 mirrored teal bags, 2 dull fuchsia bags.
shiny maroon bags contain 1 posh gold bag.
dim white bags contain 5 striped brown bags, 2 dull magenta bags, 5 plaid tan bags.
muted green bags contain 2 dull magenta bags, 5 clear cyan bags.
plaid teal bags contain 2 dark tan bags, 3 pale lime bags.
dotted lavender bags contain 2 posh aqua bags, 3 dull cyan bags.
light salmon bags contain 5 dark silver bags.
faded white bags contain 2 wavy maroon bags, 3 dull cyan bags.
dull tomato bags contain 2 dim aqua bags, 4 posh lavender bags, 1 faded red bag.
dark olive bags contain 5 clear bronze bags, 2 drab plum bags.
pale indigo bags contain 2 mirrored beige bags, 5 wavy turquoise bags, 4 striped green bags, 2 dotted lavender bags.
plaid purple bags contain 1 light lime bag.
clear purple bags contain 3 vibrant white bags.
dark yellow bags contain 2 pale olive bags, 4 pale cyan bags, 5 bright teal bags.
muted beige bags contain 2 posh lime bags, 5 shiny gray bags, 2 dull blue bags.
vibrant orange bags contain 5 posh crimson bags, 4 light chartreuse bags.
light magenta bags contain 2 plaid maroon bags, 1 posh beige bag, 5 pale salmon bags.
dotted crimson bags contain 5 dark chartreuse bags.
striped coral bags contain 2 dim aqua bags.
striped aqua bags contain 3 posh salmon bags, 3 dull red bags.
mirrored salmon bags contain 5 bright red bags, 2 light green bags, 3 clear black bags, 5 posh brown bags.
posh white bags contain 4 drab violet bags, 2 dotted silver bags.
posh blue bags contain 4 dull maroon bags, 3 vibrant coral bags.
dim orange bags contain 2 dull olive bags.
shiny teal bags contain 1 faded tomato bag, 4 muted violet bags.
mirrored maroon bags contain 3 dull blue bags.
dark lavender bags contain 1 drab red bag, 3 shiny indigo bags, 4 faded beige bags, 1 drab turquoise bag.
shiny olive bags contain 3 dark violet bags, 1 striped gold bag, 2 mirrored lime bags.
bright violet bags contain 2 wavy bronze bags, 3 drab olive bags, 5 mirrored olive bags, 2 wavy lavender bags.
clear olive bags contain 5 faded turquoise bags.
mirrored lavender bags contain 1 light white bag, 4 light purple bags, 3 wavy lavender bags, 2 shiny lime bags.
pale turquoise bags contain 4 dark tan bags.
shiny salmon bags contain 1 shiny gold bag, 5 drab turquoise bags.
vibrant gray bags contain 3 posh brown bags.
dark indigo bags contain 1 mirrored black bag, 5 dull beige bags, 4 shiny beige bags, 3 drab lavender bags.
light teal bags contain 5 dark olive bags, 5 vibrant chartreuse bags, 3 plaid salmon bags, 5 light yellow bags.
clear violet bags contain 3 light crimson bags.
clear tan bags contain 3 striped orange bags, 4 wavy lavender bags, 3 striped silver bags.
clear bronze bags contain 2 plaid beige bags.
clear gray bags contain 4 dotted cyan bags, 4 vibrant plum bags.
drab cyan bags contain 1 light aqua bag, 1 drab teal bag, 3 bright orange bags, 3 dark white bags.
plaid beige bags contain 3 dull green bags.
wavy gold bags contain 4 shiny olive bags, 3 bright tan bags.
clear aqua bags contain 3 posh chartreuse bags, 4 drab silver bags, 5 clear gray bags.
bright chartreuse bags contain 2 light violet bags, 3 vibrant gray bags.
plaid black bags contain 2 posh gray bags.
light beige bags contain 4 dotted olive bags, 5 dull olive bags, 1 faded orange bag.
mirrored teal bags contain 4 mirrored aqua bags.
bright magenta bags contain 1 mirrored magenta bag, 3 bright blue bags, 1 vibrant blue bag, 2 drab gold bags.
dim maroon bags contain 4 light bronze bags, 5 clear violet bags.
light lime bags contain 4 plaid indigo bags.
posh lavender bags contain 4 dark brown bags.
clear beige bags contain 4 posh silver bags, 3 dull coral bags, 2 posh gray bags.
drab bronze bags contain 4 plaid maroon bags.
mirrored purple bags contain 3 dim magenta bags.
dark magenta bags contain 4 faded maroon bags, 1 drab crimson bag, 5 dotted brown bags, 2 bright teal bags.
dim brown bags contain 3 muted olive bags, 5 drab green bags, 1 mirrored olive bag.
dark plum bags contain 2 vibrant tan bags.
bright turquoise bags contain 1 mirrored aqua bag, 3 clear plum bags.
muted black bags contain 5 faded cyan bags, 5 pale tan bags, 2 dotted chartreuse bags.
dotted gray bags contain 3 posh plum bags.
vibrant black bags contain 2 vibrant magenta bags, 5 faded cyan bags.
mirrored cyan bags contain 2 clear cyan bags, 4 light aqua bags, 5 drab blue bags, 1 drab gold bag.
wavy purple bags contain 5 striped magenta bags, 3 clear maroon bags, 1 mirrored green bag, 1 pale black bag.
drab blue bags contain 3 mirrored lime bags, 1 mirrored blue bag.
clear maroon bags contain 5 bright orange bags.
shiny cyan bags contain 2 clear gray bags, 5 pale crimson bags.
pale cyan bags contain 2 wavy turquoise bags, 5 wavy salmon bags.
plaid gold bags contain 1 clear lavender bag, 1 bright beige bag.
mirrored lime bags contain 2 dull tan bags, 3 shiny beige bags.
drab green bags contain 1 vibrant yellow bag.
dull red bags contain 5 plaid blue bags, 5 clear brown bags, 3 pale salmon bags, 2 dark orange bags.
bright beige bags contain 4 dull silver bags, 5 vibrant brown bags, 4 drab red bags, 2 pale violet bags.
clear silver bags contain 4 drab indigo bags, 2 clear salmon bags.
posh bronze bags contain 5 bright indigo bags, 5 dotted purple bags, 1 dark violet bag, 2 dark orange bags.
posh salmon bags contain 5 bright red bags, 3 striped green bags, 3 dark brown bags.
clear cyan bags contain 5 dark chartreuse bags, 1 bright indigo bag, 4 pale yellow bags, 2 vibrant coral bags.
mirrored blue bags contain 2 vibrant white bags.
mirrored yellow bags contain 5 dotted gray bags, 4 dull maroon bags, 2 striped violet bags, 5 clear tomato bags.
striped teal bags contain 2 clear black bags, 3 pale coral bags.
faded orange bags contain 2 dark bronze bags.
mirrored indigo bags contain 3 light tomato bags, 2 shiny crimson bags.
pale green bags contain 4 light chartreuse bags.
plaid cyan bags contain 4 plaid fuchsia bags, 2 shiny teal bags, 3 dotted fuchsia bags, 3 dim red bags.
muted gold bags contain 2 dull tan bags, 1 faded bronze bag, 4 dull maroon bags.
wavy green bags contain 5 pale coral bags, 1 dull blue bag, 4 drab blue bags, 1 striped tan bag.
light chartreuse bags contain 4 striped brown bags, 5 plaid purple bags, 4 drab cyan bags, 3 dull plum bags.
dotted cyan bags contain 4 shiny black bags.
light purple bags contain no other bags.
dotted aqua bags contain 4 light gray bags, 2 light purple bags, 5 mirrored lime bags.
drab gold bags contain 2 bright green bags, 5 bright indigo bags.
posh gray bags contain 5 bright orange bags, 5 bright blue bags.
striped red bags contain 4 drab green bags, 1 clear cyan bag.
dotted bronze bags contain 5 light orange bags.
muted plum bags contain 2 bright black bags, 3 dotted tomato bags, 2 vibrant brown bags.
mirrored black bags contain 3 plaid chartreuse bags, 2 shiny indigo bags, 2 shiny beige bags.
drab lavender bags contain 5 drab cyan bags, 1 muted purple bag, 1 wavy red bag, 3 drab crimson bags.
vibrant turquoise bags contain 3 shiny beige bags, 3 striped brown bags, 5 dim teal bags.
muted tan bags contain 1 plaid purple bag, 3 shiny beige bags, 1 drab gold bag.
pale beige bags contain 5 bright silver bags.
wavy olive bags contain 4 dotted turquoise bags, 4 dull silver bags, 1 bright gold bag.
dim olive bags contain 5 light lavender bags, 4 shiny tomato bags, 4 clear cyan bags.
wavy salmon bags contain 4 bright aqua bags.
dotted gold bags contain 3 shiny red bags, 3 dull fuchsia bags.
shiny violet bags contain 3 dotted tomato bags, 1 drab coral bag.
striped plum bags contain 4 drab beige bags, 3 clear tan bags, 5 light aqua bags, 1 shiny fuchsia bag.
clear lavender bags contain 2 bright aqua bags, 3 dull silver bags, 3 bright green bags, 2 bright orange bags.
faded maroon bags contain 5 dark indigo bags, 1 posh fuchsia bag.
vibrant red bags contain 4 striped fuchsia bags, 3 drab orange bags, 1 clear brown bag, 1 plaid turquoise bag.
dull coral bags contain 2 dim teal bags, 3 faded bronze bags.
pale salmon bags contain 3 dull magenta bags, 1 light crimson bag.
dotted magenta bags contain 4 dull maroon bags, 2 bright lime bags, 4 plaid indigo bags, 4 faded cyan bags.
wavy gray bags contain 4 muted gray bags, 3 shiny magenta bags, 1 posh teal bag.
light red bags contain 4 shiny chartreuse bags.
dim blue bags contain 4 vibrant orange bags.
muted bronze bags contain 5 mirrored aqua bags, 4 dim green bags.
drab lime bags contain 1 drab cyan bag, 3 pale crimson bags, 4 bright green bags, 3 drab lavender bags.
light white bags contain 5 bright green bags.
bright teal bags contain 4 shiny brown bags, 4 dark silver bags.
striped beige bags contain 2 shiny magenta bags.
wavy magenta bags contain 5 pale bronze bags, 5 pale plum bags, 3 muted silver bags.
dark orange bags contain 1 drab tomato bag, 3 striped brown bags, 1 dim teal bag, 5 bright beige bags.
striped indigo bags contain 1 vibrant gold bag, 1 shiny green bag.
clear coral bags contain 2 shiny gray bags.
faded yellow bags contain 4 faded gold bags, 2 bright turquoise bags, 5 dark silver bags, 3 wavy coral bags.
dim plum bags contain 1 clear purple bag, 4 light brown bags.
mirrored turquoise bags contain 5 wavy indigo bags, 3 dark fuchsia bags, 5 plaid white bags, 2 dim turquoise bags.
posh black bags contain 2 striped black bags, 5 dim teal bags, 3 bright silver bags, 5 posh beige bags.
dotted fuchsia bags contain 1 faded turquoise bag, 2 shiny lavender bags, 4 posh salmon bags, 1 clear olive bag.
faded lavender bags contain 2 striped yellow bags, 1 posh lavender bag.
dim lime bags contain 2 wavy gray bags, 5 clear gray bags.
vibrant bronze bags contain 3 drab tomato bags, 5 bright tan bags.
dull plum bags contain 5 bright red bags, 4 dull magenta bags.
dim teal bags contain 4 light purple bags, 4 plaid lavender bags, 1 dull magenta bag.
dull yellow bags contain 4 vibrant orange bags, 1 dark tomato bag, 5 pale tan bags.
dull green bags contain 2 bright blue bags, 5 dull red bags.
light crimson bags contain 5 dull maroon bags, 4 muted gold bags.
dark black bags contain 1 dim silver bag, 3 plaid magenta bags.
bright lavender bags contain 4 muted fuchsia bags.
drab coral bags contain 4 shiny chartreuse bags, 3 posh yellow bags, 3 wavy indigo bags.
mirrored crimson bags contain 3 posh maroon bags, 5 striped olive bags, 3 mirrored magenta bags.
muted coral bags contain 3 wavy violet bags, 1 dotted chartreuse bag, 1 shiny beige bag.
vibrant gold bags contain 2 dull orange bags, 1 clear chartreuse bag.
wavy orange bags contain 5 dark bronze bags.
mirrored white bags contain 5 clear gold bags, 3 drab tomato bags, 4 dotted bronze bags, 3 striped orange bags.
clear gold bags contain 3 drab indigo bags, 4 wavy violet bags, 2 shiny salmon bags, 4 light brown bags.
shiny magenta bags contain 5 drab silver bags, 2 muted gold bags.
dim violet bags contain 1 posh lime bag, 4 shiny orange bags, 2 posh chartreuse bags.
striped olive bags contain 4 plaid indigo bags, 5 dim chartreuse bags, 4 clear lavender bags.
plaid gray bags contain 3 shiny gold bags, 2 dull coral bags.
clear crimson bags contain 4 shiny aqua bags, 3 light crimson bags, 5 dim chartreuse bags.
drab silver bags contain 1 dim teal bag, 3 faded cyan bags, 1 shiny indigo bag.
mirrored green bags contain 5 dotted lime bags, 4 pale cyan bags.
bright aqua bags contain no other bags.
bright plum bags contain 4 dim aqua bags, 2 dull crimson bags, 1 wavy maroon bag.
vibrant lavender bags contain 1 plaid tan bag, 3 vibrant brown bags, 3 drab gold bags, 4 faded red bags.
pale white bags contain 3 bright brown bags, 4 mirrored beige bags.
plaid lavender bags contain 1 dull magenta bag, 2 dull silver bags, 1 shiny indigo bag.
bright salmon bags contain 1 striped coral bag, 4 plaid lavender bags, 1 muted red bag, 1 drab red bag.
plaid olive bags contain 5 faded turquoise bags, 4 dim green bags, 2 striped beige bags.
wavy plum bags contain 1 clear lavender bag, 2 faded brown bags.
clear fuchsia bags contain 1 muted bronze bag.
wavy turquoise bags contain 5 shiny lime bags, 1 drab olive bag, 4 dim white bags, 1 dotted gray bag.
vibrant aqua bags contain 2 faded lavender bags.
dotted white bags contain 3 muted crimson bags, 5 mirrored white bags, 1 mirrored fuchsia bag.
bright purple bags contain 2 dotted chartreuse bags, 4 posh cyan bags, 3 bright plum bags.
light aqua bags contain 1 plaid lavender bag, 3 wavy coral bags, 5 shiny indigo bags.
drab yellow bags contain 4 shiny teal bags, 2 dotted green bags, 5 vibrant silver bags, 3 dotted turquoise bags.
mirrored olive bags contain 1 dull plum bag.
light olive bags contain 1 shiny coral bag, 4 drab white bags, 3 dim turquoise bags, 4 dull gold bags.
shiny indigo bags contain no other bags.
dull gold bags contain 3 dark indigo bags.
bright tomato bags contain 5 muted blue bags.
faded purple bags contain 4 bright orange bags, 2 faded violet bags.
drab magenta bags contain 3 wavy lavender bags, 2 drab cyan bags, 2 clear beige bags, 4 bright indigo bags.
striped lime bags contain 4 light tan bags.
light gold bags contain 2 pale plum bags.
striped black bags contain 1 plaid salmon bag, 2 plaid beige bags, 4 dotted teal bags, 2 posh chartreuse bags.
faded tomato bags contain 2 striped yellow bags, 4 muted red bags.
dull fuchsia bags contain 5 dotted olive bags, 2 muted purple bags.
pale purple bags contain 4 posh silver bags, 4 wavy yellow bags.
bright olive bags contain 5 shiny fuchsia bags, 5 dull crimson bags, 5 drab red bags, 5 posh turquoise bags.
vibrant fuchsia bags contain 1 vibrant beige bag, 5 shiny magenta bags.
faded turquoise bags contain 5 light lime bags, 4 dark white bags.
plaid orange bags contain 5 vibrant coral bags, 4 light crimson bags, 4 plaid chartreuse bags, 1 dull green bag.
posh indigo bags contain 3 wavy green bags, 2 shiny orange bags, 5 faded violet bags, 2 dotted coral bags.
mirrored red bags contain 4 mirrored olive bags, 1 dark silver bag, 1 dull red bag.
dim salmon bags contain 1 striped salmon bag, 5 faded gray bags.
dim cyan bags contain 3 wavy olive bags, 5 drab purple bags, 3 mirrored bronze bags.
light blue bags contain 2 striped bronze bags, 4 dull white bags, 1 posh bronze bag.
dull turquoise bags contain 4 striped red bags, 1 light lavender bag, 5 plaid bronze bags, 1 mirrored brown bag.
vibrant coral bags contain 1 bright orange bag.
striped cyan bags contain 2 dark white bags, 4 drab red bags, 2 plaid salmon bags.
muted tomato bags contain 4 drab red bags, 3 vibrant silver bags, 4 clear fuchsia bags, 3 wavy white bags.
dotted red bags contain 1 light blue bag.
dark beige bags contain 2 posh lime bags, 3 striped black bags.
dark cyan bags contain 1 dim chartreuse bag, 2 shiny beige bags, 4 dotted magenta bags, 4 light chartreuse bags.
dull lime bags contain 3 muted chartreuse bags.
light brown bags contain 3 mirrored brown bags.
vibrant magenta bags contain 1 dim green bag.
shiny brown bags contain 5 bright brown bags, 3 faded cyan bags, 5 clear tan bags, 2 plaid maroon bags.
drab purple bags contain 1 shiny indigo bag, 4 striped yellow bags.

51
2020/d08/ex1/ex1.py Executable file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env python
import sys
from typing import List, Tuple
def run(code: List[Tuple[str, int]]) -> int:
accumulator = 0
rip = 0
def acc(val: int) -> None:
nonlocal accumulator
nonlocal rip
accumulator += val
rip += 1
def nop(val: int) -> None:
nonlocal rip
rip += 1
def jmp(val: int) -> None:
nonlocal rip
rip += val
instrs = {
"acc": acc,
"jmp": jmp,
"nop": nop,
}
seen = set()
while rip not in seen:
seen |= {rip}
func = instrs[code[rip][0]]
func(code[rip][1])
return accumulator
def solve(raw: List[str]) -> int:
return run([(line[:3], int(line[3:])) for line in raw])
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

675
2020/d08/ex1/input Normal file
View file

@ -0,0 +1,675 @@
acc -8
jmp +5
acc +0
acc +44
acc +42
jmp +324
acc -17
jmp +1
acc -17
jmp +51
acc -13
acc +4
jmp +1
nop +608
jmp +274
acc -17
jmp +169
acc +28
nop +508
jmp +1
jmp +570
acc +22
acc -14
jmp +377
acc -13
acc +27
jmp +474
acc -5
jmp +1
acc +12
jmp +37
jmp +184
acc +36
acc +32
acc -8
jmp +465
acc -13
acc +18
jmp +169
acc +20
acc +26
acc +23
jmp +333
jmp +584
acc +9
acc +28
acc +28
nop +571
jmp +143
acc +39
acc +39
acc -16
jmp +361
acc +48
acc +3
acc +15
nop +4
jmp +504
acc +6
jmp +285
acc +26
acc +33
jmp +1
acc +36
jmp +577
acc +36
jmp +6
nop +498
acc +42
jmp +496
acc +10
jmp +74
acc +17
acc +16
acc +30
jmp +254
acc -3
acc +16
acc -2
nop +106
jmp +541
acc -15
jmp +579
jmp +165
acc +22
acc -6
acc +29
acc -19
jmp +342
acc -19
jmp +340
acc +13
acc +25
acc +29
jmp +269
acc -14
acc +27
acc +41
acc +49
jmp +181
nop +350
jmp +1
nop +437
acc +34
jmp +494
acc +19
acc +2
acc +44
jmp +558
acc +10
jmp +44
nop +4
nop -80
nop +540
jmp +16
acc +28
jmp +14
acc +13
nop +399
acc +29
nop -60
jmp -6
acc +41
acc +30
jmp +232
acc +28
nop +495
acc +15
acc +48
jmp +157
nop +483
jmp -59
acc +5
acc +30
acc +30
acc +2
jmp +349
acc +11
acc +27
acc +1
jmp +367
acc +8
acc +45
acc +11
jmp +171
jmp -113
acc +48
jmp -38
acc +12
jmp +145
acc +8
nop +29
nop +319
jmp +154
nop +166
jmp +395
nop +15
jmp +237
acc +22
acc +3
acc +42
acc +1
jmp +288
jmp -63
nop +489
acc +33
jmp +247
jmp +1
acc -8
acc +9
jmp +413
acc -17
acc +3
acc +3
jmp +432
nop -17
acc +36
nop +198
acc +45
jmp +109
nop +242
acc +40
acc +11
jmp +448
jmp +437
acc +3
acc +49
acc +27
jmp +221
nop +158
jmp +143
acc +50
jmp -70
acc +46
acc +8
acc +35
acc -3
jmp +104
acc +11
acc +0
jmp +34
nop +132
jmp +425
jmp +219
acc -12
acc +48
jmp +21
jmp +434
acc +30
acc +1
acc +40
jmp +435
jmp +132
acc +40
jmp +236
jmp +179
jmp -149
acc +25
acc +40
acc -9
acc +49
jmp +445
nop +399
acc -14
nop +374
acc +0
jmp +152
acc +39
nop +322
acc +49
nop +117
jmp -19
acc +24
jmp +385
acc +17
acc +39
acc +44
acc -8
jmp -58
acc -18
nop -76
jmp +66
acc +14
jmp +427
acc +11
acc +47
acc +9
jmp +1
acc +42
jmp -7
acc -16
acc -13
jmp +409
acc +1
acc +35
acc +34
jmp +371
acc +24
acc +46
acc -4
jmp +367
acc +19
acc +27
acc -8
acc +41
jmp -184
nop -185
acc +23
acc -8
acc +35
jmp -9
acc -7
nop -101
nop +121
acc +37
jmp -72
acc +24
jmp +1
nop -124
jmp +163
acc +37
acc -12
jmp +331
acc -12
acc +1
jmp +232
jmp -233
jmp -72
acc +28
jmp +169
acc +43
acc +18
nop +108
jmp -184
acc -4
acc -10
nop +317
acc +48
jmp +173
nop +45
jmp -73
acc +35
jmp +198
acc -15
acc +46
acc +31
jmp +41
nop +169
jmp +1
nop -92
nop -271
jmp -113
jmp +1
nop -42
jmp +42
nop -283
acc +22
nop +200
jmp -17
jmp +1
acc +49
nop +35
nop -185
jmp +298
acc +1
jmp +1
nop +301
acc +19
jmp -34
jmp +163
jmp +1
acc +49
jmp -115
jmp -62
acc +8
acc +5
acc -6
jmp -146
acc -4
nop -202
acc +47
jmp -114
acc +8
jmp +57
acc +37
jmp +61
jmp +267
acc +2
acc +28
nop -20
jmp -186
acc +24
nop +269
acc +48
acc +45
jmp -22
acc +11
acc +36
jmp -267
acc +7
nop -45
nop -231
jmp +32
nop +220
acc +19
jmp -250
acc +33
jmp -169
acc +45
acc -13
acc +0
acc +44
jmp +6
acc +42
jmp +84
acc +48
jmp -332
jmp +213
acc -16
acc +31
acc +17
acc +3
jmp -75
jmp +1
acc +11
acc +4
jmp -271
acc -12
nop +97
nop +11
jmp -43
acc +30
jmp +1
jmp +49
jmp -379
nop -51
acc +0
acc -8
nop -191
jmp -346
jmp -255
acc +2
acc +21
acc -16
nop +217
jmp -30
acc +31
jmp -270
jmp -324
jmp +130
acc +49
nop +179
jmp -37
acc +11
acc +15
acc +29
acc +17
jmp -237
acc +47
acc -13
acc +6
jmp +169
nop +54
acc -12
jmp -233
nop +33
acc +17
acc +14
acc +21
jmp -275
acc -8
acc +1
nop +229
jmp +1
jmp +119
jmp -193
nop +217
jmp +95
acc -2
acc +1
acc +41
jmp -332
acc +44
nop -343
acc +23
jmp -165
acc +7
acc -12
nop -339
jmp +9
nop -390
acc -17
acc +43
jmp -138
nop -247
acc +42
acc +0
jmp +170
acc +48
jmp -139
acc +6
acc +13
acc +35
jmp -85
nop -117
jmp -307
acc +25
acc -10
acc -14
acc +0
jmp -355
jmp +102
acc -8
acc +47
acc +36
jmp +42
acc +33
acc +17
acc +46
jmp -331
jmp +1
acc -11
jmp +1
acc +27
jmp +147
acc -14
nop -28
acc +32
jmp -482
acc +11
nop -390
jmp -485
acc -12
acc +37
acc +33
acc +28
jmp -32
acc +42
acc -11
jmp -460
acc +36
acc +6
acc +39
jmp +80
nop +123
acc -13
jmp -97
acc +25
acc +46
acc +13
nop -450
jmp +84
acc +3
nop -260
jmp +1
acc +22
jmp -510
acc -4
acc +17
acc -19
jmp -420
acc -14
acc +26
acc +29
acc +17
jmp -458
acc -10
acc +23
nop -2
jmp -196
acc -5
jmp -416
acc +49
jmp -165
acc +4
acc +7
acc +20
nop -217
jmp +103
jmp +5
acc -1
acc +2
jmp +1
jmp +84
acc -14
jmp -518
jmp +1
acc +30
acc +21
jmp -202
nop -18
jmp -344
jmp -88
nop -472
acc -5
acc +13
jmp -295
nop -315
acc +41
nop -317
jmp -299
nop +105
jmp -86
acc +7
jmp -226
nop -277
acc +21
acc +13
acc +47
jmp -283
acc -11
acc -1
jmp -408
acc +47
nop -553
acc +37
acc -11
jmp -468
acc +43
nop -299
acc +40
acc +2
jmp -275
acc +24
acc -14
acc +13
acc +36
jmp -249
acc +35
jmp -45
acc +47
acc +31
acc -19
jmp -151
jmp -33
acc +6
jmp -160
jmp -553
acc +25
jmp +1
nop -267
jmp -430
acc +23
nop +63
acc +37
jmp -434
nop -579
jmp +11
acc +25
acc -17
acc +22
acc +27
jmp +15
jmp -546
acc -4
acc +41
acc +0
jmp -261
acc +20
jmp -404
jmp -408
acc +26
jmp -464
acc +34
nop -80
acc -12
jmp -43
jmp -410
acc -13
acc -3
jmp -310
nop -433
acc -7
acc -11
acc +9
jmp -29
nop -564
acc -5
acc -16
acc +36
jmp -587
jmp -115
acc +24
acc +35
nop -638
jmp -573
acc +31
acc +14
jmp -609
acc +25
acc -10
acc +18
jmp -308
acc +25
acc +33
acc +21
acc -12
jmp -172
nop -37
acc +12
jmp -316
acc +41
acc +14
jmp -415
acc +40
jmp -112
jmp -613
acc +26
nop -151
jmp -471
acc +50
acc +16
nop -119
acc +46
jmp +1

62
2020/d08/ex2/ex2.py Executable file
View file

@ -0,0 +1,62 @@
#!/usr/bin/env python
import sys
from copy import deepcopy
from typing import List, Tuple
def run(code: List[Tuple[str, int]]) -> Tuple[int, bool]:
accumulator = 0
rip = 0
def acc(val: int) -> None:
nonlocal accumulator
nonlocal rip
accumulator += val
rip += 1
def nop(val: int) -> None:
nonlocal rip
rip += 1
def jmp(val: int) -> None:
nonlocal rip
rip += val
instrs = {
"acc": acc,
"jmp": jmp,
"nop": nop,
}
seen = set()
while rip not in seen and rip < len(code):
seen |= {rip}
func = instrs[code[rip][0]]
func(code[rip][1])
return accumulator, rip == len(code)
def solve(raw: List[str]) -> int:
code = [(line[:3], int(line[3:])) for line in raw]
lut = {"jmp": "nop", "nop": "jmp"}
for i in range(len(code)):
if code[i][0] not in lut:
continue
new_code = deepcopy(code)
new_code[i] = lut[new_code[i][0]], new_code[i][1]
val, halted = run(new_code)
if halted:
return val
assert False # Sanity check
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

675
2020/d08/ex2/input Normal file
View file

@ -0,0 +1,675 @@
acc -8
jmp +5
acc +0
acc +44
acc +42
jmp +324
acc -17
jmp +1
acc -17
jmp +51
acc -13
acc +4
jmp +1
nop +608
jmp +274
acc -17
jmp +169
acc +28
nop +508
jmp +1
jmp +570
acc +22
acc -14
jmp +377
acc -13
acc +27
jmp +474
acc -5
jmp +1
acc +12
jmp +37
jmp +184
acc +36
acc +32
acc -8
jmp +465
acc -13
acc +18
jmp +169
acc +20
acc +26
acc +23
jmp +333
jmp +584
acc +9
acc +28
acc +28
nop +571
jmp +143
acc +39
acc +39
acc -16
jmp +361
acc +48
acc +3
acc +15
nop +4
jmp +504
acc +6
jmp +285
acc +26
acc +33
jmp +1
acc +36
jmp +577
acc +36
jmp +6
nop +498
acc +42
jmp +496
acc +10
jmp +74
acc +17
acc +16
acc +30
jmp +254
acc -3
acc +16
acc -2
nop +106
jmp +541
acc -15
jmp +579
jmp +165
acc +22
acc -6
acc +29
acc -19
jmp +342
acc -19
jmp +340
acc +13
acc +25
acc +29
jmp +269
acc -14
acc +27
acc +41
acc +49
jmp +181
nop +350
jmp +1
nop +437
acc +34
jmp +494
acc +19
acc +2
acc +44
jmp +558
acc +10
jmp +44
nop +4
nop -80
nop +540
jmp +16
acc +28
jmp +14
acc +13
nop +399
acc +29
nop -60
jmp -6
acc +41
acc +30
jmp +232
acc +28
nop +495
acc +15
acc +48
jmp +157
nop +483
jmp -59
acc +5
acc +30
acc +30
acc +2
jmp +349
acc +11
acc +27
acc +1
jmp +367
acc +8
acc +45
acc +11
jmp +171
jmp -113
acc +48
jmp -38
acc +12
jmp +145
acc +8
nop +29
nop +319
jmp +154
nop +166
jmp +395
nop +15
jmp +237
acc +22
acc +3
acc +42
acc +1
jmp +288
jmp -63
nop +489
acc +33
jmp +247
jmp +1
acc -8
acc +9
jmp +413
acc -17
acc +3
acc +3
jmp +432
nop -17
acc +36
nop +198
acc +45
jmp +109
nop +242
acc +40
acc +11
jmp +448
jmp +437
acc +3
acc +49
acc +27
jmp +221
nop +158
jmp +143
acc +50
jmp -70
acc +46
acc +8
acc +35
acc -3
jmp +104
acc +11
acc +0
jmp +34
nop +132
jmp +425
jmp +219
acc -12
acc +48
jmp +21
jmp +434
acc +30
acc +1
acc +40
jmp +435
jmp +132
acc +40
jmp +236
jmp +179
jmp -149
acc +25
acc +40
acc -9
acc +49
jmp +445
nop +399
acc -14
nop +374
acc +0
jmp +152
acc +39
nop +322
acc +49
nop +117
jmp -19
acc +24
jmp +385
acc +17
acc +39
acc +44
acc -8
jmp -58
acc -18
nop -76
jmp +66
acc +14
jmp +427
acc +11
acc +47
acc +9
jmp +1
acc +42
jmp -7
acc -16
acc -13
jmp +409
acc +1
acc +35
acc +34
jmp +371
acc +24
acc +46
acc -4
jmp +367
acc +19
acc +27
acc -8
acc +41
jmp -184
nop -185
acc +23
acc -8
acc +35
jmp -9
acc -7
nop -101
nop +121
acc +37
jmp -72
acc +24
jmp +1
nop -124
jmp +163
acc +37
acc -12
jmp +331
acc -12
acc +1
jmp +232
jmp -233
jmp -72
acc +28
jmp +169
acc +43
acc +18
nop +108
jmp -184
acc -4
acc -10
nop +317
acc +48
jmp +173
nop +45
jmp -73
acc +35
jmp +198
acc -15
acc +46
acc +31
jmp +41
nop +169
jmp +1
nop -92
nop -271
jmp -113
jmp +1
nop -42
jmp +42
nop -283
acc +22
nop +200
jmp -17
jmp +1
acc +49
nop +35
nop -185
jmp +298
acc +1
jmp +1
nop +301
acc +19
jmp -34
jmp +163
jmp +1
acc +49
jmp -115
jmp -62
acc +8
acc +5
acc -6
jmp -146
acc -4
nop -202
acc +47
jmp -114
acc +8
jmp +57
acc +37
jmp +61
jmp +267
acc +2
acc +28
nop -20
jmp -186
acc +24
nop +269
acc +48
acc +45
jmp -22
acc +11
acc +36
jmp -267
acc +7
nop -45
nop -231
jmp +32
nop +220
acc +19
jmp -250
acc +33
jmp -169
acc +45
acc -13
acc +0
acc +44
jmp +6
acc +42
jmp +84
acc +48
jmp -332
jmp +213
acc -16
acc +31
acc +17
acc +3
jmp -75
jmp +1
acc +11
acc +4
jmp -271
acc -12
nop +97
nop +11
jmp -43
acc +30
jmp +1
jmp +49
jmp -379
nop -51
acc +0
acc -8
nop -191
jmp -346
jmp -255
acc +2
acc +21
acc -16
nop +217
jmp -30
acc +31
jmp -270
jmp -324
jmp +130
acc +49
nop +179
jmp -37
acc +11
acc +15
acc +29
acc +17
jmp -237
acc +47
acc -13
acc +6
jmp +169
nop +54
acc -12
jmp -233
nop +33
acc +17
acc +14
acc +21
jmp -275
acc -8
acc +1
nop +229
jmp +1
jmp +119
jmp -193
nop +217
jmp +95
acc -2
acc +1
acc +41
jmp -332
acc +44
nop -343
acc +23
jmp -165
acc +7
acc -12
nop -339
jmp +9
nop -390
acc -17
acc +43
jmp -138
nop -247
acc +42
acc +0
jmp +170
acc +48
jmp -139
acc +6
acc +13
acc +35
jmp -85
nop -117
jmp -307
acc +25
acc -10
acc -14
acc +0
jmp -355
jmp +102
acc -8
acc +47
acc +36
jmp +42
acc +33
acc +17
acc +46
jmp -331
jmp +1
acc -11
jmp +1
acc +27
jmp +147
acc -14
nop -28
acc +32
jmp -482
acc +11
nop -390
jmp -485
acc -12
acc +37
acc +33
acc +28
jmp -32
acc +42
acc -11
jmp -460
acc +36
acc +6
acc +39
jmp +80
nop +123
acc -13
jmp -97
acc +25
acc +46
acc +13
nop -450
jmp +84
acc +3
nop -260
jmp +1
acc +22
jmp -510
acc -4
acc +17
acc -19
jmp -420
acc -14
acc +26
acc +29
acc +17
jmp -458
acc -10
acc +23
nop -2
jmp -196
acc -5
jmp -416
acc +49
jmp -165
acc +4
acc +7
acc +20
nop -217
jmp +103
jmp +5
acc -1
acc +2
jmp +1
jmp +84
acc -14
jmp -518
jmp +1
acc +30
acc +21
jmp -202
nop -18
jmp -344
jmp -88
nop -472
acc -5
acc +13
jmp -295
nop -315
acc +41
nop -317
jmp -299
nop +105
jmp -86
acc +7
jmp -226
nop -277
acc +21
acc +13
acc +47
jmp -283
acc -11
acc -1
jmp -408
acc +47
nop -553
acc +37
acc -11
jmp -468
acc +43
nop -299
acc +40
acc +2
jmp -275
acc +24
acc -14
acc +13
acc +36
jmp -249
acc +35
jmp -45
acc +47
acc +31
acc -19
jmp -151
jmp -33
acc +6
jmp -160
jmp -553
acc +25
jmp +1
nop -267
jmp -430
acc +23
nop +63
acc +37
jmp -434
nop -579
jmp +11
acc +25
acc -17
acc +22
acc +27
jmp +15
jmp -546
acc -4
acc +41
acc +0
jmp -261
acc +20
jmp -404
jmp -408
acc +26
jmp -464
acc +34
nop -80
acc -12
jmp -43
jmp -410
acc -13
acc -3
jmp -310
nop -433
acc -7
acc -11
acc +9
jmp -29
nop -564
acc -5
acc -16
acc +36
jmp -587
jmp -115
acc +24
acc +35
nop -638
jmp -573
acc +31
acc +14
jmp -609
acc +25
acc -10
acc +18
jmp -308
acc +25
acc +33
acc +21
acc -12
jmp -172
nop -37
acc +12
jmp -316
acc +41
acc +14
jmp -415
acc +40
jmp -112
jmp -613
acc +26
nop -151
jmp -471
acc +50
acc +16
nop -119
acc +46
jmp +1

32
2020/d09/ex1/ex1.py Executable file
View file

@ -0,0 +1,32 @@
#!/usr/bin/env python
import itertools
import sys
from typing import List
def find_invalid(nums: List[int]) -> int:
for i in range(25, len(nums)):
num = nums[i]
found = False
for lhs, rhs in itertools.combinations(nums[i - 25 : i], 2):
if lhs + rhs == num:
found = True
break
if not found:
return num
assert False # Sanity check
def solve(raw: List[str]) -> int:
return find_invalid([int(line) for line in raw])
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

1000
2020/d09/ex1/input Normal file

File diff suppressed because it is too large Load diff

42
2020/d09/ex2/ex2.py Executable file
View file

@ -0,0 +1,42 @@
#!/usr/bin/env python
import itertools
import sys
from typing import List
def find_invalid(nums: List[int]) -> int:
for i in range(25, len(nums)):
num = nums[i]
found = False
for lhs, rhs in itertools.combinations(nums[i - 25 : i], 2):
if lhs + rhs == num:
found = True
break
if not found:
return num
assert False # Sanity check
def find_weakness(nums: List[int], invalid: int) -> int:
for i in range(len(nums) - 2):
for j in range(i + 2, len(nums)):
if sum(nums[i:j]) == invalid:
return min(nums[i:j]) + max(nums[i:j])
assert False # Sanity check((
def solve(raw: List[str]) -> int:
nums = [int(line) for line in raw]
invalid = find_invalid(nums)
return find_weakness(nums, invalid)
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

Some files were not shown because too many files have changed in this diff Show more