diff --git a/2017/07/7.md b/2017/07/7.md index 68c5742..5295d85 100644 --- a/2017/07/7.md +++ b/2017/07/7.md @@ -67,6 +67,48 @@ larger.) Before you\'re ready to help them, you need to make sure your information is correct. *What is the name of the bottom program?* -To begin, [get your puzzle input](7/input). +Your puzzle answer was `xegshds`. -Answer: +## \-\-- Part Two \-\-- {#part2} + +The programs explain the situation: they can\'t get down. Rather, they +*could* get down, if they weren\'t expending all of their energy trying +to keep the tower balanced. Apparently, one program has the *wrong +weight*, and until it\'s fixed, they\'re stuck here. + +For any program holding a disc, each program standing on that disc forms +a sub-tower. Each of those sub-towers are supposed to be the same +weight, or the disc itself isn\'t balanced. The weight of a tower is the +sum of the weights of the programs in that tower. + +In the example above, this means that for `ugml`\'s disc to be balanced, +`gyxo`, `ebii`, and `jptl` must all have the same weight, and they do: +`61`. + +However, for `tknk` to be balanced, each of the programs standing on its +disc *and all programs above it* must each match. This means that the +following sums must all be the same: + +- `ugml` + (`gyxo` + `ebii` + `jptl`) = 68 + (61 + 61 + 61) = 251 +- `padx` + (`pbga` + `havc` + `qoyq`) = 45 + (66 + 66 + 66) = 243 +- `fwft` + (`ktlj` + `cntj` + `xhth`) = 72 + (57 + 57 + 57) = 243 + +As you can see, `tknk`\'s disc is unbalanced: `ugml`\'s stack is heavier +than the other two. Even though the nodes above `ugml` are balanced, +`ugml` itself is too heavy: it needs to be `8` units lighter for its +stack to weigh `243` and keep the towers balanced. If this change were +made, its weight would be `60`. + +Given that exactly one program is the wrong weight, *what would its +weight need to be* to balance the entire tower? + +Your puzzle answer was `299`. + +Both parts of this puzzle are complete! They provide two gold stars: +\*\* + +At this point, you should [return to your Advent calendar](/2017) and +try another puzzle. + +If you still want to see it, you can [get your puzzle +input](7/input). diff --git a/2017/07/solution.py b/2017/07/solution.py index 0167b7b..1e53b41 100644 --- a/2017/07/solution.py +++ b/2017/07/solution.py @@ -1,8 +1,9 @@ #!/bin/python3 import sys, re from pprint import pprint +from collections import Counter -input_f = 'test' +input_f = 'input' part = 2 @@ -11,7 +12,8 @@ part = 2 # Part 1 # # # ######################################### -if part == 1: + +def part1(): children = [] mains = [] with open(input_f)as file: @@ -27,7 +29,10 @@ if part == 1: for x in mains: if x not in children: - print(x) + return x + +if part == 1: + print(part1()) @@ -36,17 +41,136 @@ if part == 1: # Part 2 # # # ######################################### + +def find_children(x,grid): + # x will be a string like 'tknk' + print('Testing ',x) + found = [] + for i in grid: + if i.startswith(x): + + match = re.search(r"-> (.+)", i) + if match: + found = [item.strip() for item in match.group(1).split(",")] + print(found) + else: + print([i for i in grid if i.startswith(x)]) + if found != None: + for j in found: + find_children(j,grid) + +def calculate_weights(node, tree, weights, total_weights): + # Compute total weight for the current node + total = weights[node] + for child in tree[node]: + total += calculate_weights(child, tree, weights, total_weights) + total_weights[node] = total + return total + +def find_outlier(lst): + count = Counter(lst) + outlier = None + reference = None + for num, freq in count.items(): + if freq == 1 or freq < len(lst) - 1: + outlier = num + else: + reference = num + return outlier,reference + +def find_unbalanced(node, tree, weights, total_weights): + child_weights = [total_weights[child] for child in tree[node]] + if len(set(child_weights)) == 1: + return None + + weight_counts = {w: child_weights.count(w) for w in child_weights} + incorrect_weight = next(w for w, count in weight_counts.items() if count == 1) + correct_weight = next(w for w, count in weight_counts.items() if count > 1) + unbalanced_child = tree[node][child_weights.index(incorrect_weight)] + + deeper_issue = find_unbalanced(unbalanced_child, tree, weights, total_weights) + if deeper_issue: + return deeper_issue + else: + return unbalanced_child, weights[unbalanced_child] + (correct_weight - incorrect_weight) + if part == 2: children = [] mains = [] + grid = [] with open(input_f)as file: for line in file: l = line.rstrip() - if '->' in l: - x = l.split('->') - for i in x[1].split(','): - children.append(i.strip()) - match = re.match(r"^(\S+)",x[0]) - if match: - mains.append(match.group(1)) - \ No newline at end of file + grid.append(l) + + tree = {} + weights = {} + for line in grid: + match = re.match(r"(\w+) \((\d+)\)(?: -> (.+))?", line) + if match: + name = match.group(1) + weight = int(match.group(2)) + children = match.group(3).split(", ") if match.group(3) else [] + tree[name] = children + weights[name] = weight + + total_weights = {} + + calculate_weights(part1(),tree,weights,total_weights) + result = find_unbalanced(part1(), tree, weights, total_weights) + print(result) + #unbalanced_values = [] + #for key,value in tree.items(): + # if value: + # t_values = [] + # max_v = 0 + # change = 0 + # for i in value: + # t_values.append(int(total_weights[i])) + # if all(v == t_values[0] for v in t_values): + # continue + # else: + # print('STOP') + # print(t_values) + # input() + # unbalanced_values.append(t_values) + + + #print(unbalanced_values) + #unbalanced_values = list(reversed(unbalanced_values)) + #print(unbalanced_values) + + #for t_values in unbalanced_values: + # outlier,reference = find_outlier(t_values) + # change = max(outlier,reference) - min(outlier,reference) + # max_v = max(outlier,reference) + + #if t_values[0] == t_values[1]: + # if t_values[0] == t_values[2]: + # if t_values[1] == t_values[2]: + # change = t_values[1] - t_values[2] + # max_v = max(t_values[1],t_values[2]) + # else: + # change = t_values[0]-t_values[2] + # max_v = max(t_values[0],t_values[2]) + #else: + # change = t_values[0] - t_values[1] + # max_v = max(t_values[0],t_values[1]) + + # print(change) + # print(max_v) + + + + # new_val = max_v-change + # print(new_val) + + # for odx,o in enumerate(t_values): + # if o == max_v: + # total_weights[value[odx]] = new_val + + #for kx,x in total_weights.items(): + # if x == max_v: + # print(weights[kx]) + # print(weights[kx]-change) + \ No newline at end of file