|
| 1 | +# -------------------------------- Input data ---------------------------------------- # |
| 2 | +import os, grid, graph, dot, assembly, re, itertools, copy, functools |
| 3 | +from collections import Counter, deque, defaultdict |
| 4 | + |
| 5 | +from compass import * |
| 6 | + |
| 7 | + |
| 8 | +# This functions come from https://github.com/mcpower/adventofcode - Thanks! |
| 9 | +def lmap(func, *iterables): |
| 10 | + return list(map(func, *iterables)) |
| 11 | + |
| 12 | + |
| 13 | +def ints(s: str): |
| 14 | + return lmap(int, re.findall(r"-?\d+", s)) # thanks mserrano! |
| 15 | + |
| 16 | + |
| 17 | +def positive_ints(s: str): |
| 18 | + return lmap(int, re.findall(r"\d+", s)) # thanks mserrano! |
| 19 | + |
| 20 | + |
| 21 | +def floats(s: str): |
| 22 | + return lmap(float, re.findall(r"-?\d+(?:\.\d+)?", s)) |
| 23 | + |
| 24 | + |
| 25 | +def positive_floats(s: str): |
| 26 | + return lmap(float, re.findall(r"\d+(?:\.\d+)?", s)) |
| 27 | + |
| 28 | + |
| 29 | +def words(s: str): |
| 30 | + return re.findall(r"[a-zA-Z]+", s) |
| 31 | + |
| 32 | + |
| 33 | +test_data = {} |
| 34 | + |
| 35 | +test = 1 |
| 36 | +test_data[test] = { |
| 37 | + "input": """on x=10..12,y=10..12,z=10..12 |
| 38 | +on x=11..13,y=11..13,z=11..13 |
| 39 | +off x=9..11,y=9..11,z=9..11 |
| 40 | +on x=10..10,y=10..10,z=10..10""", |
| 41 | + "expected": ["39", "Unknown"], |
| 42 | +} |
| 43 | + |
| 44 | +test += 1 |
| 45 | +test_data[test] = { |
| 46 | + "input": """on x=-5..47,y=-31..22,z=-19..33 |
| 47 | +on x=-44..5,y=-27..21,z=-14..35 |
| 48 | +on x=-49..-1,y=-11..42,z=-10..38 |
| 49 | +on x=-20..34,y=-40..6,z=-44..1 |
| 50 | +off x=26..39,y=40..50,z=-2..11 |
| 51 | +on x=-41..5,y=-41..6,z=-36..8 |
| 52 | +off x=-43..-33,y=-45..-28,z=7..25 |
| 53 | +on x=-33..15,y=-32..19,z=-34..11 |
| 54 | +off x=35..47,y=-46..-34,z=-11..5 |
| 55 | +on x=-14..36,y=-6..44,z=-16..29 |
| 56 | +on x=-57795..-6158,y=29564..72030,z=20435..90618 |
| 57 | +on x=36731..105352,y=-21140..28532,z=16094..90401 |
| 58 | +on x=30999..107136,y=-53464..15513,z=8553..71215 |
| 59 | +on x=13528..83982,y=-99403..-27377,z=-24141..23996 |
| 60 | +on x=-72682..-12347,y=18159..111354,z=7391..80950 |
| 61 | +on x=-1060..80757,y=-65301..-20884,z=-103788..-16709 |
| 62 | +on x=-83015..-9461,y=-72160..-8347,z=-81239..-26856 |
| 63 | +on x=-52752..22273,y=-49450..9096,z=54442..119054 |
| 64 | +on x=-29982..40483,y=-108474..-28371,z=-24328..38471 |
| 65 | +on x=-4958..62750,y=40422..118853,z=-7672..65583 |
| 66 | +on x=55694..108686,y=-43367..46958,z=-26781..48729 |
| 67 | +on x=-98497..-18186,y=-63569..3412,z=1232..88485 |
| 68 | +on x=-726..56291,y=-62629..13224,z=18033..85226 |
| 69 | +on x=-110886..-34664,y=-81338..-8658,z=8914..63723 |
| 70 | +on x=-55829..24974,y=-16897..54165,z=-121762..-28058 |
| 71 | +on x=-65152..-11147,y=22489..91432,z=-58782..1780 |
| 72 | +on x=-120100..-32970,y=-46592..27473,z=-11695..61039 |
| 73 | +on x=-18631..37533,y=-124565..-50804,z=-35667..28308 |
| 74 | +on x=-57817..18248,y=49321..117703,z=5745..55881 |
| 75 | +on x=14781..98692,y=-1341..70827,z=15753..70151 |
| 76 | +on x=-34419..55919,y=-19626..40991,z=39015..114138 |
| 77 | +on x=-60785..11593,y=-56135..2999,z=-95368..-26915 |
| 78 | +on x=-32178..58085,y=17647..101866,z=-91405..-8878 |
| 79 | +on x=-53655..12091,y=50097..105568,z=-75335..-4862 |
| 80 | +on x=-111166..-40997,y=-71714..2688,z=5609..50954 |
| 81 | +on x=-16602..70118,y=-98693..-44401,z=5197..76897 |
| 82 | +on x=16383..101554,y=4615..83635,z=-44907..18747 |
| 83 | +off x=-95822..-15171,y=-19987..48940,z=10804..104439 |
| 84 | +on x=-89813..-14614,y=16069..88491,z=-3297..45228 |
| 85 | +on x=41075..99376,y=-20427..49978,z=-52012..13762 |
| 86 | +on x=-21330..50085,y=-17944..62733,z=-112280..-30197 |
| 87 | +on x=-16478..35915,y=36008..118594,z=-7885..47086 |
| 88 | +off x=-98156..-27851,y=-49952..43171,z=-99005..-8456 |
| 89 | +off x=2032..69770,y=-71013..4824,z=7471..94418 |
| 90 | +on x=43670..120875,y=-42068..12382,z=-24787..38892 |
| 91 | +off x=37514..111226,y=-45862..25743,z=-16714..54663 |
| 92 | +off x=25699..97951,y=-30668..59918,z=-15349..69697 |
| 93 | +off x=-44271..17935,y=-9516..60759,z=49131..112598 |
| 94 | +on x=-61695..-5813,y=40978..94975,z=8655..80240 |
| 95 | +off x=-101086..-9439,y=-7088..67543,z=33935..83858 |
| 96 | +off x=18020..114017,y=-48931..32606,z=21474..89843 |
| 97 | +off x=-77139..10506,y=-89994..-18797,z=-80..59318 |
| 98 | +off x=8476..79288,y=-75520..11602,z=-96624..-24783 |
| 99 | +on x=-47488..-1262,y=24338..100707,z=16292..72967 |
| 100 | +off x=-84341..13987,y=2429..92914,z=-90671..-1318 |
| 101 | +off x=-37810..49457,y=-71013..-7894,z=-105357..-13188 |
| 102 | +off x=-27365..46395,y=31009..98017,z=15428..76570 |
| 103 | +off x=-70369..-16548,y=22648..78696,z=-1892..86821 |
| 104 | +on x=-53470..21291,y=-120233..-33476,z=-44150..38147 |
| 105 | +off x=-93533..-4276,y=-16170..68771,z=-104985..-24507""", |
| 106 | + "expected": ["Unknown", "2758514936282235"], |
| 107 | +} |
| 108 | + |
| 109 | +test = "real" |
| 110 | +input_file = os.path.join( |
| 111 | + os.path.dirname(__file__), |
| 112 | + "Inputs", |
| 113 | + os.path.basename(__file__).replace(".py", ".txt"), |
| 114 | +) |
| 115 | +test_data[test] = { |
| 116 | + "input": open(input_file, "r+").read(), |
| 117 | + "expected": ["582644", "1263804707062415"], |
| 118 | +} |
| 119 | + |
| 120 | + |
| 121 | +# -------------------------------- Control program execution ------------------------- # |
| 122 | + |
| 123 | +case_to_test = "real" |
| 124 | +part_to_test = 2 |
| 125 | + |
| 126 | +# -------------------------------- Initialize some variables ------------------------- # |
| 127 | + |
| 128 | +puzzle_input = test_data[case_to_test]["input"] |
| 129 | +puzzle_expected_result = test_data[case_to_test]["expected"][part_to_test - 1] |
| 130 | +puzzle_actual_result = "Unknown" |
| 131 | + |
| 132 | + |
| 133 | +# -------------------------------- Actual code execution ----------------------------- # |
| 134 | + |
| 135 | +# Conver integer to 36-character binary |
| 136 | +# str_value = "{0:>036b}".format(value) |
| 137 | +# Convert binary string to number |
| 138 | +# value = int(str_value, 2) |
| 139 | + |
| 140 | + |
| 141 | +class ListDict(object): |
| 142 | + def __init__(self): |
| 143 | + self.item_to_position = {} |
| 144 | + self.items = [] |
| 145 | + |
| 146 | + def add_item(self, item): |
| 147 | + if item in self.item_to_position: |
| 148 | + return |
| 149 | + self.items.append(item) |
| 150 | + self.item_to_position[item] = len(self.items) - 1 |
| 151 | + |
| 152 | + def remove_item(self, item): |
| 153 | + if item not in self.item_to_position: |
| 154 | + return |
| 155 | + position = self.item_to_position.pop(item) |
| 156 | + last_item = self.items.pop() |
| 157 | + if position != len(self.items): |
| 158 | + self.items[position] = last_item |
| 159 | + self.item_to_position[last_item] = position |
| 160 | + |
| 161 | + def __len__(self): |
| 162 | + return len(self.items) |
| 163 | + |
| 164 | + |
| 165 | +if part_to_test == 1: |
| 166 | + on = ListDict() |
| 167 | + for i, string in enumerate(puzzle_input.split("\n")): |
| 168 | + coords = ints(string) |
| 169 | + if ( |
| 170 | + coords[0] < -50 |
| 171 | + or coords[1] > 50 |
| 172 | + or coords[2] < -50 |
| 173 | + or coords[3] > 50 |
| 174 | + or coords[4] < -50 |
| 175 | + or coords[5] > 50 |
| 176 | + ): |
| 177 | + print(i, "skipped") |
| 178 | + continue |
| 179 | + for x in range(coords[0], coords[1] + 1): |
| 180 | + if x < -50 or x > 50: |
| 181 | + continue |
| 182 | + for y in range(coords[2], coords[3] + 1): |
| 183 | + if y < -50 or y > 50: |
| 184 | + continue |
| 185 | + for z in range(coords[4], coords[5] + 1): |
| 186 | + if z < -50 or z > 50: |
| 187 | + continue |
| 188 | + if string[0:3] == "on ": |
| 189 | + on.add_item((x, y, z)) |
| 190 | + else: |
| 191 | + on.remove_item((x, y, z)) |
| 192 | + print(i, len(on)) |
| 193 | + |
| 194 | + puzzle_actual_result = len(on) |
| 195 | + |
| 196 | + |
| 197 | +else: |
| 198 | + cuboids = [] |
| 199 | + for i, string in enumerate(puzzle_input.split("\n")): |
| 200 | + new_cube = ints(string) |
| 201 | + new_power = 1 if string[0:3] == "on " else -1 |
| 202 | + for cuboid, power in cuboids.copy(): |
| 203 | + intersection = [ |
| 204 | + max(new_cube[0], cuboid[0]), |
| 205 | + min(new_cube[1], cuboid[1]), |
| 206 | + max(new_cube[2], cuboid[2]), |
| 207 | + min(new_cube[3], cuboid[3]), |
| 208 | + max(new_cube[4], cuboid[4]), |
| 209 | + min(new_cube[5], cuboid[5]), |
| 210 | + ] |
| 211 | + # print (cuboid, new_cube, intersection) |
| 212 | + if ( |
| 213 | + intersection[0] <= intersection[1] |
| 214 | + and intersection[2] <= intersection[3] |
| 215 | + and intersection[4] <= intersection[5] |
| 216 | + ): |
| 217 | + cuboids.append((intersection, -power)) |
| 218 | + |
| 219 | + if new_power == 1: |
| 220 | + cuboids.append((new_cube, new_power)) |
| 221 | + # print (i, string, len(cuboids)) |
| 222 | + # print (cuboids) |
| 223 | + nb_on = sum( |
| 224 | + [ |
| 225 | + (coords[1] - coords[0] + 1) |
| 226 | + * (coords[3] - coords[2] + 1) |
| 227 | + * (coords[5] - coords[4] + 1) |
| 228 | + * power |
| 229 | + for coords, power in cuboids |
| 230 | + ] |
| 231 | + ) |
| 232 | + |
| 233 | + puzzle_actual_result = nb_on |
| 234 | + |
| 235 | + |
| 236 | +# -------------------------------- Outputs / results --------------------------------- # |
| 237 | + |
| 238 | +print("Case :", case_to_test, "- Part", part_to_test) |
| 239 | +print("Expected result : " + str(puzzle_expected_result)) |
| 240 | +print("Actual result : " + str(puzzle_actual_result)) |
| 241 | +# Date created: 2021-12-22 08:23:07.073476 |
| 242 | +# Part 1: 2021-12-22 08:37:38 |
| 243 | +# Part 2: 2021-12-22 09:12:31 |
0 commit comments