This December I participated in Advent of Code.

This one had me thinking.
- In part 1, I need to create program copies of areas defined by their common letter. For this I create a list of the letters represented, make a copy of the map for each letter, and throw away all but one letter from each map.
- But then I have to test, whether each area is actually connected or there are 2 (or more) areas with the same letter, so my program copy has to be split up. For this I use a little recursion, because a split area may need to be split some more. Also, I think I finally became friends with global variables! And side effects, oh yeah… But, I have a function starting in a random place, marking all the places it can reach in the map, and then it’s easy to ask, was the whole map converted?
- Next, I have to figure out the size (easy) and periphery (hard) of each map. For the periphery I visit all the parts of the map. If this part of the map is in the area, and a neighboring part isn’t, we’ve found a part of the periphery.
- For part 2, I additionally test, whether someone before me already registered this part of the periphery.
Part 1:
<?php
$input = file_get_contents('./d12input1.txt', true);
foreach(preg_split("/((\r?\n)|(\r\n?))/", $input) as $line) {
if(strlen($line)>2) {
$map[] = str_split($line);
}
}
$mapx = sizeof($map);
$mapy = sizeof($map[0]);
// name possible areas
$names = array();
for($i=0;$i<sizeof($map);$i++) {
for($j=0;$j<sizeof($map[$i]);$j++) {
$names[$map[$i][$j]] = 1;
}
}
// convert names
$names2 = array();
foreach($names as $key => $val) {
$names2[] = $key;
}
$names = $names2;
// thin areas out
$areas = array();
for($k=0;$k<sizeof($names);$k++) {
$lett = $names[$k];
$tmp = $map;
for($i=0;$i<$mapx;$i++) {
for($j=0;$j<$mapy;$j++) {
if($tmp[$i][$j] != $lett) {
unset($tmp[$i][$j]);
}
}
}
$areas[$k] = $tmp;
}
function subtst($i, $j) {
global $tmpb;
//print_r($tmpb);
if(isset($tmpb[$i-1][$j])) {
if($tmpb[$i-1][$j] != "*") {
$tmpb[$i-1][$j] = "*";
subtst($i-1, $j);
}
}
if(isset($tmpb[$i+1][$j])) {
if($tmpb[$i+1][$j] != "*") {
$tmpb[$i+1][$j] = "*";
subtst($i+1, $j);
}
}
if(isset($tmpb[$i][$j-1])) {
if($tmpb[$i][$j-1] != "*") {
$tmpb[$i][$j-1] = "*";
subtst($i, $j-1);
}
}
if(isset($tmpb[$i][$j+1])) {
if($tmpb[$i][$j+1] != "*") {
$tmpb[$i][$j+1] = "*";
subtst($i, $j+1);
}
}
}
function atst() {
global $tmp, $map, $tmpb, $key, $mapx, $mapy, $areas;
// grab random beginning point
$lett = "";
for($i=0;$i<$mapx;$i++) {
for($j=0;$j<$mapy;$j++) {
if(isset($tmp[$i][$j])) {
$lett = $tmp[$i][$j];
$x = $i;
$y = $j;
break 2;
}
}
}
// can I reach all points from here?
$tmpb = $tmp;
$tmpb[$x][$y] = "*";
subtst($x, $y);
if(sizeof(array_count_values(array_merge(...$tmpb))) > 1) {
$new1 = $tmpb;
for($i=0;$i<$mapx;$i++) {
for($j=0;$j<$mapy;$j++) {
if(isset($new1[$i][$j])) {
if($new1[$i][$j] == $lett) {
unset($new1[$i][$j]);
} else {
$new1[$i][$j] = $lett;
}
}
}
}
$new2 = $tmpb;
for($i=0;$i<$mapx;$i++) {
for($j=0;$j<$mapy;$j++) {
if(isset($new2[$i][$j])) {
if($new2[$i][$j] != $lett) {
unset($new2[$i][$j]);
}
}
}
}
$areas[$key] = $new1;
$areas[] = $new2;
}
}
// if areas aren't actually connected, split up
$areaz = 0;
while($areaz < sizeof($areas)) {
$areaz = sizeof($areas);
foreach($areas as $key => $area) {
$tmp = $area;
atst();
}
}
$sum = 0;
foreach($areas as $key => $area) {
$sz1 = array_count_values(array_merge(...$area));
$sz2 = array_pop($sz1);
$per = 0;
for($i=0;$i<$mapx;$i++) {
for($j=0;$j<$mapy;$j++) {
if(isset($area[$i][$j])) {
if(!isset($area[$i-1][$j])) {
$per++;
}
if(!isset($area[$i+1][$j])) {
$per++;
}
if(!isset($area[$i][$j-1])) {
$per++;
}
if(!isset($area[$i][$j+1])) {
$per++;
}
}
}
}
$sum += $sz2 * $per;
}
print("$sum\n");
?>
Part 2:
<?php
$input = file_get_contents('./d12input2.txt', true);
foreach(preg_split("/((\r?\n)|(\r\n?))/", $input) as $line) {
if(strlen($line)>2) {
$map[] = str_split($line);
}
}
$mapx = sizeof($map);
$mapy = sizeof($map[0]);
// name possible areas
$names = array();
for($i=0;$i<sizeof($map);$i++) {
for($j=0;$j<sizeof($map[$i]);$j++) {
$names[$map[$i][$j]] = 1;
}
}
// convert names
$names2 = array();
foreach($names as $key => $val) {
$names2[] = $key;
}
$names = $names2;
// thin areas out
$areas = array();
for($k=0;$k<sizeof($names);$k++) {
$lett = $names[$k];
$tmp = $map;
for($i=0;$i<$mapx;$i++) {
for($j=0;$j<$mapy;$j++) {
if($tmp[$i][$j] != $lett) {
unset($tmp[$i][$j]);
}
}
}
$areas[$k] = $tmp;
}
//print_r($areas);
function subtst($i, $j) {
global $tmpb;
if(isset($tmpb[$i-1][$j])) {
if($tmpb[$i-1][$j] != "*") {
$tmpb[$i-1][$j] = "*";
subtst($i-1, $j);
}
}
if(isset($tmpb[$i+1][$j])) {
if($tmpb[$i+1][$j] != "*") {
$tmpb[$i+1][$j] = "*";
subtst($i+1, $j);
}
}
if(isset($tmpb[$i][$j-1])) {
if($tmpb[$i][$j-1] != "*") {
$tmpb[$i][$j-1] = "*";
subtst($i, $j-1);
}
}
if(isset($tmpb[$i][$j+1])) {
if($tmpb[$i][$j+1] != "*") {
$tmpb[$i][$j+1] = "*";
subtst($i, $j+1);
}
}
}
function atst() {
global $tmp, $map, $tmpb, $key, $mapx, $mapy, $areas;
// grab random beginning point
$lett = "";
for($i=0;$i<$mapx;$i++) {
for($j=0;$j<$mapy;$j++) {
if(isset($tmp[$i][$j])) {
$lett = $tmp[$i][$j];
$x = $i;
$y = $j;
break 2;
}
}
}
// can I reach all points from here?
$tmpb = $tmp;
$tmpb[$x][$y] = "*";
subtst($x, $y);
if(sizeof(array_count_values(array_merge(...$tmpb))) > 1) {
//print("alert\n");
$new1 = $tmpb;
for($i=0;$i<$mapx;$i++) {
for($j=0;$j<$mapy;$j++) {
if(isset($new1[$i][$j])) {
if($new1[$i][$j] == $lett) {
unset($new1[$i][$j]);
} else {
$new1[$i][$j] = $lett;
}
}
}
}
$new2 = $tmpb;
for($i=0;$i<$mapx;$i++) {
for($j=0;$j<$mapy;$j++) {
if(isset($new2[$i][$j])) {
if($new2[$i][$j] != $lett) {
unset($new2[$i][$j]);
}
}
}
}
$areas[$key] = $new1;
$areas[] = $new2;
}
}
// if areas aren't actually connected, split up
$areaz = 0;
while($areaz < sizeof($areas)) {
$areaz = sizeof($areas);
foreach($areas as $key => $area) {
$tmp = $area;
atst();
}
}
$sum = 0;
foreach($areas as $key => $area) {
$sz1 = array_count_values(array_merge(...$area));
$sz2 = array_pop($sz1);
$per = 0;
for($i=0;$i<$mapx;$i++) {
for($j=0;$j<$mapy;$j++) {
if(isset($area[$i][$j])) {
// above
if(!isset($area[$i-1][$j])) {
// already counted?
if(isset($area[$i][$j-1]) && !isset($area[$i-1][$j-1])) {
} else {
$per++;
}
}
// below
if(!isset($area[$i+1][$j])) {
// already counted?
if(isset($area[$i][$j-1]) && !isset($area[$i+1][$j-1])) {
} else {
$per++;
}
}
// to the left
if(!isset($area[$i][$j-1])) {
// already counted?
if(isset($area[$i-1][$j]) && !isset($area[$i-1][$j-1])) {
} else {
$per++;
}
}
// to the right
if(!isset($area[$i][$j+1])) {
// already counted?
if(isset($area[$i-1][$j]) && !isset($area[$i-1][$j+1])) {
} else {
$per++;
}
}
}
}
}
$sum += $sz2 * $per;
}
print("$sum\n");
?>