Skip to content

Commit

Permalink
Using min failure - pretty fast
Browse files Browse the repository at this point in the history
  • Loading branch information
derailed-dash committed Jan 1, 2025
1 parent 38e57ca commit 17b7111
Showing 1 changed file with 57 additions and 62 deletions.
119 changes: 57 additions & 62 deletions src/AoC_2024/Dazbo's_Advent_of_Code_2024.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -9589,7 +9589,7 @@
},
{
"cell_type": "code",
"execution_count": 32,
"execution_count": 76,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -9605,69 +9605,56 @@
"\n",
" Returns:\n",
" bool: True if the addition is valid, False otherwise.\n",
" \"\"\" \n",
" # wires_copy = wires.copy() # work with a fresh copy of wires with each validation\n",
" wires_copy = {k: 0 for k in wires if k.startswith(\"x\") or k.startswith(\"y\")} # Create a smaller structure\n",
" wires_copy.update({k: v for k, v in wires.items() if not (k.startswith(\"x\") or k.startswith(\"y\"))})\n",
" \n",
" \"\"\" \n",
" # Set each x and y wire to 1 or 0, \n",
" # based on the respective bit index of the supplied x / y values.\n",
" # I.e. isolate the bit of input value, and set the corresponding wire to this bit\n",
" for wire in wires.keys():\n",
" if wire.startswith(\"x\"):\n",
" bit_idx = int(wire[1:]) # E.g. 4\n",
" wires_copy[wire] = (x >> bit_idx) & 1 \n",
" wires[wire] = (x >> bit_idx) & 1 \n",
" \n",
" if wire.startswith(\"y\"):\n",
" bit_idx = int(wire[1:])\n",
" wires_copy[wire] = (y >> bit_idx) & 1\n",
" wires[wire] = (y >> bit_idx) & 1\n",
" \n",
" for output in operations.keys():\n",
" if output.startswith(\"z\"):\n",
" process_gates_dfs(output, wires_copy, operations)\n",
" process_gates_dfs(output, wires, operations)\n",
" \n",
" z_out = get_output_for_wire_type(wires_copy, \"z\")\n",
" z_out = get_output_for_wire_type(wires, \"z\")\n",
" return x + y == z_out # perform the check \n",
"\n",
"def get_failures(wires: dict, operations: dict, to_validate: Iterable) -> list:\n",
"def get_failures(wires: dict, operations: dict, wires_count:int, start=2) -> list:\n",
" \"\"\" Identify which bit positions fail the validation, \n",
" i.e. when the z value does not represent the sum of the x and y wires.\n",
" \"\"\"\n",
"\n",
" # Validate specific x and y values\n",
" big_x = 30626032511001\n",
" big_y = 28716883075641\n",
" \n",
" to_validate: an interable that stores the bit positions to check. \"\"\"\n",
" failures = set() # To store the bit positions that fail validation\n",
" \n",
" x_single_bit = 0\n",
" x_bits_so_far = 0\n",
" for i in to_validate: # this bit set to 1\n",
" x_single_bit = 2**i # Same as 1 << i\n",
" y_single_bit = 2**i # Same as 1 << i\n",
" x_bits_so_far += x_single_bit\n",
" for i in range(start, wires_count): # this bit set to 1\n",
" x = 2**(i-2) + 2**(i-1) + 2**i # Set three consecutive bits to test carry-over\n",
" y = 2**(i-2) + 2**(i-1) + 2**i\n",
" \n",
" # Try adding 1 and seeing where it fails\n",
" if not validate_addition(wires, operations, x_single_bit, 1):\n",
" failures.add(i)\n",
" if not validate_addition(wires.copy(), operations.copy(), x, 1):\n",
" return i\n",
" \n",
" # Try adding pairs of True bits and seeing where it fails\n",
" if not validate_addition(wires, operations, x_single_bit, y_single_bit):\n",
" failures.add(i)\n",
" if not validate_addition(wires.copy(), operations.copy(), x, y):\n",
" return i\n",
" \n",
" # Validate specific x and y values if provided\n",
" x = 30626032511001\n",
" y = 28716883075641\n",
" for i in to_validate:\n",
" # Create a mask with all bits set up to the ith position\n",
" mask = (1 << (i + 1)) - 1 # A mask with bits 0 through i set to 1\n",
" mask = (1 << (i + 1)) - 1 # A mask with bits 0 through i set to 1, e.g. 0b111\n",
" test_x = big_x & mask\n",
" test_y = big_y & mask\n",
"\n",
" # Extract all bits up to the ith position for x and y\n",
" test_x = x & mask\n",
" test_y = y & mask\n",
"\n",
" # Validate with the current bit isolated\n",
" if i not in failures:\n",
" if not validate_addition(wires, operations, test_x, test_y):\n",
" failures.add(i) \n",
" if not validate_addition(wires.copy(), operations.copy(), test_x, test_y):\n",
" return i \n",
" \n",
" return sorted(failures)\n",
" return -1\n",
"\n",
"def solve_part2(data: str, swaps_required=4):\n",
" wires, operations = process_input(data)\n",
Expand All @@ -9676,15 +9663,15 @@
" y_wires_count = len([wire for wire in wires if wire.startswith(\"y\")])\n",
" assert x_wires_count == y_wires_count, \"There should be same number of x and y wires\"\n",
" \n",
" failures = get_failures(wires, operations, list(range(x_wires_count)))\n",
" failures = get_failures(wires.copy(), operations.copy(), x_wires_count)\n",
" logger.debug(f\"Initial failures: {failures}\")\n",
" \n",
" swap_candidates = []\n",
" valid = False\n",
" ignore = set()\n",
" prev_ops = []\n",
" while not valid or len(swap_candidates) != swaps_required: \n",
" swap_candidates, local_ops = find_swap_candidates(wires, operations, failures, ignore=ignore)\n",
" while not valid or len(swap_candidates) != swaps_required: \n",
" swap_candidates, local_ops = find_swap_candidates(wires.copy(), operations.copy(), failures, ignore=ignore)\n",
" \n",
" if local_ops == prev_ops:\n",
" logger.debug(\"No solution found\")\n",
Expand Down Expand Up @@ -9714,23 +9701,21 @@
" swaps += [item for pair in swap_candidates for item in pair] # extend the list\n",
" return \",\".join(sorted(swaps))\n",
"\n",
"def find_swap_candidates(wires, operations, failures, ignore):\n",
"def find_swap_candidates(wires, ops, lowest_failure:int, ignore):\n",
" logger.debug(\"find_swap_candidates()\")\n",
" local_wires = wires.copy()\n",
" local_ops = operations.copy()\n",
" local_failures = failures.copy()\n",
" new_failures = local_failures.copy()\n",
" x_wires_count = len([wire for wire in wires if wire.startswith(\"x\")])\n",
" swap_candidates = []\n",
" \n",
" logger.debug(f\"{local_wires=}\")\n",
" logger.debug(f\"{local_ops=}\")\n",
" logger.debug(f\"Initial failures: {local_failures}\")\n",
" logger.debug(f\"{wires=}\")\n",
" logger.debug(f\"{ops=}\")\n",
" logger.debug(f\"Lowest failures: {lowest_failure}\")\n",
" logger.debug(f\"{ignore=}\")\n",
" \n",
" while new_failures:\n",
" new_lowest = lowest_failure\n",
" while new_lowest != -1:\n",
" # Loop until we've tried every pair - or there are no more failures\n",
" for op_x in local_ops: # E.g. fkp\n",
" for op_y in local_ops: # E.g. z06\n",
" for op_x in ops: # E.g. fkp\n",
" for op_y in ops: # E.g. z06\n",
" if op_x == op_y: \n",
" continue\n",
" \n",
Expand All @@ -9744,24 +9729,24 @@
" continue\n",
" \n",
" # Swap these two operations and test if we can remove lowest bit failure\n",
" local_ops[op_x], local_ops[op_y] = local_ops[op_y], local_ops[op_x]\n",
" ops[op_x], ops[op_y] = ops[op_y], ops[op_x]\n",
" try:\n",
" new_failures = get_failures(local_wires, local_ops, local_failures)\n",
" if not new_failures: # if we've run out of failures\n",
" new_lowest = get_failures(wires, ops, x_wires_count, start=lowest_failure)\n",
" if new_lowest == -1: # if we've run out of failures\n",
" logger.debug(\"No failures remaining\")\n",
" break\n",
" \n",
" if len(new_failures) < len(local_failures):\n",
" local_failures = new_failures\n",
" logger.debug(f\"Failures reduced: {local_failures}\")\n",
" if new_lowest > lowest_failure:\n",
" lowest_failure = new_lowest\n",
" logger.debug(f\"Lowest failure updated: {lowest_failure}\")\n",
" swap_candidates.append(tuple(sorted((op_x, op_y))))\n",
" logger.debug(swap_candidates)\n",
" break # Go to next x\n",
" except RecursionError as e:\n",
" pass # If no valid solution with this swap, we undo it\n",
" \n",
" # Undo swap\n",
" local_ops[op_x], local_ops[op_y] = local_ops[op_y], local_ops[op_x]\n",
" ops[op_x], ops[op_y] = ops[op_y], ops[op_x]\n",
" else: # Only execute if we complete without a break\n",
" continue\n",
" \n",
Expand All @@ -9771,15 +9756,25 @@
" logger.warning(\"No candidates found.\")\n",
" break\n",
" \n",
" return swap_candidates, local_ops\n",
" return swap_candidates, ops\n",
" "
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 75,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[34m17:53:11.746:aoc2024 - DBG: wires={'x00': 1, 'x01': 0, 'x02': 0, 'x03': 1, 'x04': 1, 'x05': 0, 'x06': 0, 'x07': 0, 'x08': 0, 'x09': 0, 'x10': 0, 'x11': 1, 'x12': 0, 'x13': 1, 'x14': 1, 'x15': 1, 'x16': 1, 'x17': 0, 'x18': 0, 'x19': 1, 'x20': 0, 'x21': 0, 'x22': 1, 'x23': 1, 'x24': 1, 'x25': 0, 'x26': 1, 'x27': 1, 'x28': 0, 'x29': 1, 'x30': 0, 'x31': 1, 'x32': 0, 'x33': 1, 'x34': 0, 'x35': 1, 'x36': 1, 'x37': 0, 'x38': 1, 'x39': 1, 'x40': 1, 'x41': 1, 'x42': 0, 'x43': 1, 'x44': 1, 'y00': 1, 'y01': 0, 'y02': 0, 'y03': 1, 'y04': 1, 'y05': 1, 'y06': 0, 'y07': 0, 'y08': 0, 'y09': 1, 'y10': 0, 'y11': 0, 'y12': 0, 'y13': 1, 'y14': 1, 'y15': 0, 'y16': 1, 'y17': 0, 'y18': 1, 'y19': 1, 'y20': 1, 'y21': 0, 'y22': 0, 'y23': 1, 'y24': 1, 'y25': 1, 'y26': 0, 'y27': 1, 'y28': 0, 'y29': 1, 'y30': 0, 'y31': 0, 'y32': 0, 'y33': 1, 'y34': 1, 'y35': 1, 'y36': 1, 'y37': 0, 'y38': 0, 'y39': 0, 'y40': 0, 'y41': 1, 'y42': 0, 'y43': 1, 'y44': 1}\u001b[39m\n",
"\u001b[34m17:53:11.747:aoc2024 - DBG: connections_lines=['x36 AND y36 -> rpc', 'swn OR jrk -> kfm', 'x36 XOR y36 -> mvv', 'y28 XOR x28 -> rnh', 'bfp OR wqc -> rgb', 'tkc OR mfm -> brs', 'kmb XOR gfj -> z16', 'x25 AND y25 -> mdt', 'mpp AND hfd -> gjp', 'dhd AND mvb -> vrf', 'y14 XOR x14 -> qvt', 'shc OR bkk -> wvr', 'x29 AND y29 -> gdn', 'x11 XOR y11 -> jpp', 'rws OR fts -> mpp', 'wmq OR ngr -> knj', 'x24 XOR y24 -> gfg', 'tpf AND mgq -> tkc', 'wvr XOR jgw -> fkp', 'brs AND nmr -> qpb', 'x18 AND y18 -> qsw', 'pnb OR vjh -> sfh', 'x44 XOR y44 -> gcd', 'x22 AND y22 -> mhd', 'x37 XOR y37 -> dgg', 'vfj XOR dmh -> z15', 'x30 XOR y30 -> qgd', 'rpw OR gdn -> wrv', 'ptj OR vqm -> vjn', 'gfg AND pqf -> pnb', 'x17 XOR y17 -> rtv', 'y19 AND x19 -> wpt', 'sfp AND sbq -> tcv', 'hvv OR vmr -> kpq', 'pgc XOR fvj -> z02', 'knj AND ctw -> vqm', 'y42 XOR x42 -> vfb', 'y13 XOR x13 -> vdk', 'x43 AND y43 -> nhd', 'krg XOR dkw -> z43', 'y32 AND x32 -> vdm', 'hfd XOR mpp -> z08', 'nfq OR qgm -> cqq', 'x02 AND y02 -> nss', 'rvw XOR dtb -> z10', 'qvt AND qqv -> rgj', 'mvv XOR sgr -> z36', 'y11 AND x11 -> wmq', 'cnd XOR jqv -> z29', 'vdk XOR vjn -> z13', 'x34 AND y34 -> kjj', 'qvt XOR qqv -> z14', 'y18 XOR x18 -> mkt', 'bwk OR krn -> pqf', 'nhs XOR cqq -> z41', 'y31 AND x31 -> z31', 'y23 AND x23 -> bwk', 'sfh AND pmf -> ctp', 'rvw AND dtb -> sgv', 'tns AND chq -> dwv', 'rqt XOR snv -> z22', 'jqv AND cnd -> rpw', 'x33 AND y33 -> vtd', 'ctw XOR knj -> z12', 'bpp OR ghf -> z06', 'ffn AND rdj -> shc', 'cfw OR tnc -> sgr', 'wdm AND psv -> fwc', 'vwn OR wpt -> bvc', 'jkn OR gvk -> z45', 'x00 XOR y00 -> z00', 'qpf XOR mkt -> z18', 'y12 AND x12 -> ptj', 'dvq XOR rkm -> z04', 'x15 XOR y15 -> dmh', 'qrm OR nss -> wdm', 'mhv OR mnv -> rcs', 'qtq OR cqn -> nwk', 'x20 XOR y20 -> tpw', 'x04 AND y04 -> ptd', 'nhd OR pnk -> mdn', 'hjc OR hth -> pgc', 'x20 AND y20 -> qtq', 'gcd XOR mdn -> z44', 'mgq XOR tpf -> mfm', 'x30 AND y30 -> bbk', 'dmh AND vfj -> cpc', 'x44 AND y44 -> gvk', 'dwv OR jvf -> jjj', 'pkh AND fkp -> rws', 'x39 AND y39 -> wqc', 'fwc OR nbc -> rkm', 'bdc AND bbd -> dnc', 'x26 XOR y26 -> tns', 'csh AND mst -> vwn', 'x43 XOR y43 -> dkw', 'bvc XOR tpw -> z20', 'nwk XOR ngm -> z21', 'rtv XOR kfm -> z17', 'x06 AND y06 -> bpp', 'x10 XOR y10 -> dtb', 'y29 XOR x29 -> cnd', 'y08 XOR x08 -> hfd', 'y03 XOR x03 -> psv', 'rgj OR bph -> vfj', 'psv XOR wdm -> z03', 'dnc OR vtd -> mvb', 'gcn AND tqf -> krn', 'y38 XOR x38 -> krj', 'x24 AND y24 -> vjh', 'y41 AND x41 -> vmr', 'jgw AND wvr -> ghf', 'x09 XOR y09 -> sfp', 'y28 AND x28 -> wpw', 'x40 XOR y40 -> mkc', 'hsn AND dgg -> snc', 'jpp XOR stv -> ngr', 'mjb OR cpc -> gfj', 'rcs XOR rnh -> z28', 'sfp XOR sbq -> z09', 'rtv AND kfm -> jfr', 'tjh OR wpw -> jqv', 'x16 XOR y16 -> kmb', 'bgn OR wnm -> snv', 'nmr XOR brs -> z32', 'rpc OR dvm -> hsn', 'gfg XOR pqf -> z24', 'dkw AND krg -> pnk', 'kmb AND gfj -> jrk', 'skt XOR kjn -> z01', 'gcn XOR tqf -> z23', 'jjj XOR rhc -> z27', 'y07 AND x07 -> fts', 'y21 AND x21 -> wnm', 'kvd OR snc -> ntr', 'nht XOR hsp -> z39', 'wrv XOR qgd -> z30', 'y07 XOR x07 -> pkh', 'tdv OR krj -> hsp', 'stv AND jpp -> z11', 'x27 AND y27 -> mhv', 'bdc XOR bbd -> z33', 'x12 XOR y12 -> ctw', 'mvv AND sgr -> dvm', 'x27 XOR y27 -> rhc', 'x21 XOR y21 -> ngm', 'mhn XOR mdg -> z35', 'x19 XOR y19 -> csh', 'y35 XOR x35 -> mhn', 'snv AND rqt -> tfs', 'rkm AND dvq -> cjp', 'pgc AND fvj -> qrm', 'kpq XOR vfb -> z42', 'qgd AND wrv -> gqt', 'y26 AND x26 -> jvf', 'x39 XOR y39 -> nht', 'vdk AND vjn -> jqm', 'bvc AND tpw -> cqn', 'y32 XOR x32 -> nmr', 'x25 XOR y25 -> pmf', 'y09 AND x09 -> prs', 'y14 AND x14 -> bph', 'qpb OR vdm -> bdc', 'gqt OR bbk -> tpf', 'x40 AND y40 -> qgm', 'sfh XOR pmf -> z25', 'x22 XOR y22 -> rqt', 'rhc AND jjj -> mnv', 'csh XOR mst -> z19', 'x42 AND y42 -> krw', 'x34 XOR y34 -> dhd', 'x35 AND y35 -> tnc', 'ngm AND nwk -> bgn', 'tdh OR jqm -> qqv', 'y00 AND x00 -> skt', 'y41 XOR x41 -> nhs', 'ntr XOR bpt -> z38', 'vrf OR kjj -> mdg', 'kvf OR krw -> krg', 'x03 AND y03 -> nbc', 'dhd XOR mvb -> z34', 'qpf AND mkt -> rsd', 'y01 XOR x01 -> kjn', 'x17 AND y17 -> bvg', 'jfr OR bvg -> qpf', 'y13 AND x13 -> tdh', 'bpb OR gjp -> sbq', 'x16 AND y16 -> swn', 'x02 XOR y02 -> fvj', 'y15 AND x15 -> mjb', 'x23 XOR y23 -> tqf', 'rnh AND rcs -> tjh', 'x05 AND y05 -> bkk', 'hsn XOR dgg -> z37', 'qsw OR rsd -> mst', 'sgv OR qnf -> stv', 'y01 AND x01 -> hth', 'y38 AND x38 -> bpt', 'rgb AND mkc -> nfq', 'y33 XOR x33 -> bbd', 'tns XOR chq -> z26', 'ctp OR mdt -> chq', 'nhs AND cqq -> hvv', 'pkh XOR fkp -> z07', 'rdj XOR ffn -> z05', 'mhd OR tfs -> gcn', 'y10 AND x10 -> qnf', 'hsp AND nht -> bfp', 'gcd AND mdn -> jkn', 'ntr AND bpt -> tdv', 'prs OR tcv -> rvw', 'x05 XOR y05 -> ffn', 'y04 XOR x04 -> dvq', 'x31 XOR y31 -> mgq', 'y08 AND x08 -> bpb', 'mhn AND mdg -> cfw', 'y37 AND x37 -> kvd', 'rgb XOR mkc -> z40', 'cjp OR ptd -> rdj', 'x06 XOR y06 -> jgw', 'skt AND kjn -> hjc', 'vfb AND kpq -> kvf']\u001b[39m\n",
"\u001b[34m17:56:06.715:aoc2024 - DBG: Initial failures: 3\u001b[39m\n"
]
}
],
"source": [
"logger.setLevel(logging.DEBUG)\n",
"soln = solve_part2(input_data)\n",
Expand Down

0 comments on commit 17b7111

Please sign in to comment.