Advent of Code, day 12

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");
?>

Skriv en kommentar