diff --git a/Makefile b/Makefile index 270dca7..1d0d3e9 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,8 @@ day6: php day6/main.php day7: + php day7/main.php + day8: day9: day10: diff --git a/day7/main.php b/day7/main.php new file mode 100644 index 0000000..1f3acd3 --- /dev/null +++ b/day7/main.php @@ -0,0 +1,121 @@ + ', $line); + + // Split number from name + list($masterName, $masterNumber) = explode(' ', $master); + + // Map up children + if (!empty($child)) { + $children = array_merge($children, explode(', ', $child)); + } + + $names[] = $masterName; + } + + // Flip children for faster lookup + $children = array_flip($children); + + foreach ($names as $name) { + if (!isset($children[$name])) { + return $name; + } + } +} + +function puzzle2(string $input) : int +{ + $lines = explode(PHP_EOL, $input); + $familyTree = []; + $names = []; + $grandparent = puzzle1($input); + $parentPoints = []; + + foreach ($lines as $line) { + // Split away master from children data + list($master, $child) = explode(' -> ', $line); + + // Split number from name and clean up the number + list($masterName, $masterNumber) = explode(' ', $master); + $masterNumber = str_replace(['(', ')'], '', $masterNumber); + + // Map up children + if (!empty($child)) { + $familyTree[$masterName] = explode(', ', $child); + } + + $names[$masterName] = $masterNumber; + } + + function treePoints(array $familyTree, array $names, array &$wrongTrees, string $name) : int { + $points = 0; + + if (isset($familyTree[$name])) { + $subtreePoints = []; + + foreach ($familyTree[$name] as $subname) { + $subtreePoints[$subname] = $names[$subname] + treePoints($familyTree, $names, $wrongTrees, $subname); + + $points += $names[$subname] + treePoints($familyTree, $names, $wrongTrees, $subname); + } + + // If we have some error in this tree, put it into the list of wrongtrees + $copy = array_unique($subtreePoints); + if (count($copy) > 1) { + $wrongTrees[] = $subtreePoints; + } + } + + return $points; + }; + + $wrongTrees = []; + + // Extract the core family + foreach ($familyTree[$grandparent] as $name) { + $parentPoints[$name] = $names[$name] + treePoints($familyTree, $names, $wrongTrees, $name); + } + + // Find which subtree that contains the error + $wrongTree = []; + foreach ($wrongTrees as $tree) { + foreach ($wrongTrees as $subtree) { + if (json_encode($tree) === json_encode($subtree)) { + $wrongTree = $tree; + break 2; + } + } + } + + // Find a value that only exists once in the wrong tree + $errorNumber = 0; + $notErrorNumber = 0; + foreach (array_count_values($wrongTree) as $number => $count) { + if ($count === 1) { + $errorNumber = $number; + } else { + $notErrorNumber = $number; + } + } + + // Find the broken name + $errorName = array_search($errorNumber, $wrongTree); + + // calculate diff + $diff = $errorNumber - $notErrorNumber; + + // Find original value of the errornus name + $errorNameOriginalValue = $names[$errorName]; + + // Calucalete correct value + return $errorNameOriginalValue - $diff; +}