comparison 2017/day07.d @ 7:52fdca7ea9be

day 7
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Fri, 08 Dec 2017 11:58:41 -0500
parents
children
comparison
equal deleted inserted replaced
6:94a2bb2aad6a 7:52fdca7ea9be
1 import std.array: array, assocArray, byPair;
2 import std.stdio;
3 import std.algorithm: map, filter, uniq, group;
4 import std.regex;
5 import std.string: split;
6 import std.conv: to;
7
8 struct Node(numType) {
9 numType weight;
10 string[] childNames;
11 numType[string] subweights;
12 bool balanced;
13 string parent;
14 }
15
16 Node!int[string] index;
17
18 void parseLine(string line) {
19 static nodeRegex = regex(
20 r"(?P<name>\w+) \((?P<weight>\d+)\)( -> (?P<children>[\w, ]+))?"
21 );
22 auto row = matchFirst(line, nodeRegex);
23 Node!int n = {
24 weight: to!int(row["weight"]),
25 childNames: row["children"].split(", "),
26 balanced: true,
27 };
28 index[row["name"]] = n;
29 }
30
31 void connectNodes() {
32 foreach(parent, node; index) {
33 foreach(child; node.childNames) {
34 index[child].parent = parent;
35 }
36 }
37 }
38
39 auto findRoot() {
40 foreach(name, node; index) {
41 if(!node.parent) {
42 return name;
43 }
44 }
45 return "";
46 }
47
48 void computeSubWeights(string name) {
49 auto node = index[name];
50 foreach(subname; node.childNames) {
51 computeSubWeights(subname);
52 auto subnode = index[subname];
53 auto subsum = 0;
54 foreach(subweight; subnode.subweights) {
55 subsum += subweight;
56 }
57 node.subweights[subname] = subnode.weight + subsum;
58 }
59 node.balanced = node.subweights.values.uniq.array.length <= 1;
60 index[name] = node;
61 }
62
63 string findUnbalanced(string name) {
64 auto node = index[name];
65 foreach(subname; node.childNames) {
66 auto subnode = index[subname];
67 if(!subnode.balanced) {
68 return findUnbalanced(subname);
69 }
70 }
71 return name;
72 }
73
74 auto balanceTilty(string tilty) {
75 auto node = index[tilty];
76 auto weightCounts = node.subweights.values.group.assocArray;
77 auto badweight = weightCounts.byPair.filter!(x => x[1] == 1).array[0][0];
78 auto goodweight = weightCounts.byPair.filter!(x => x[1] > 1).array[0][0];
79 auto badname =
80 node
81 .subweights
82 .byPair
83 .filter!(x => x[1] == badweight)
84 .array[0][0];
85
86 return index[badname].weight + (goodweight-badweight);
87 }
88
89 void main(string[] args) {
90 foreach(line; File(args[1]).byLineCopy) {
91 parseLine(line);
92 }
93 connectNodes();
94 auto root = findRoot();
95 writeln(root);
96 computeSubWeights(root);
97 auto tilty = findUnbalanced(root);
98 auto balancedValue = balanceTilty(tilty);
99 writeln(balancedValue);
100 }