Move solutions out of the source itself
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
91
data/Y23/day1/Day1.php
Normal file
91
data/Y23/day1/Day1.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace trizz\AdventOfCode\Y23;
|
||||
|
||||
use trizz\AdventOfCode\Solution;
|
||||
|
||||
final class Day1 extends Solution
|
||||
{
|
||||
/**
|
||||
* @var array<string,int>
|
||||
*/
|
||||
private const array NUMBER_STRING = [
|
||||
'one' => 1,
|
||||
'two' => 2,
|
||||
'three' => 3,
|
||||
'four' => 4,
|
||||
'five' => 5,
|
||||
'six' => 6,
|
||||
'seven' => 7,
|
||||
'eight' => 8,
|
||||
'nine' => 9,
|
||||
];
|
||||
|
||||
public static null|int|string $part1ExampleResult = 142;
|
||||
|
||||
public static null|int|string $part1Result = 53974;
|
||||
|
||||
public static null|int|string $part2ExampleResult = 281;
|
||||
|
||||
public static null|int|string $part2Result = 52840;
|
||||
|
||||
#[\Override]
|
||||
public function part1(array $data): int
|
||||
{
|
||||
$total = 0;
|
||||
|
||||
foreach ($data as $line) {
|
||||
$total += $this->extractNumbersFromLine($line);
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function part2(array $data): int
|
||||
{
|
||||
$total = 0;
|
||||
|
||||
foreach ($data as $line) {
|
||||
$total += $this->extractNumbersFromLineWithText($line);
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
private function extractNumbersFromLine(string $line): int
|
||||
{
|
||||
preg_match_all('#\d#', $line, $numbers);
|
||||
|
||||
if (empty($numbers[0])) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$first = $numbers[0][0];
|
||||
$last = $numbers[0][array_key_last($numbers[0])];
|
||||
|
||||
return (int) ($first.$last);
|
||||
}
|
||||
|
||||
private function extractNumbersFromLineWithText(string $line): int
|
||||
{
|
||||
preg_match_all('#\d|'.implode('|', array_keys(self::NUMBER_STRING)).'#', $line, $numbersStart);
|
||||
|
||||
// Same regex, but match everything in reverse, so the last is the first.
|
||||
$keys = implode('|', array_map(static fn (string $k): string => '('.strrev($k).')', array_keys(self::NUMBER_STRING)));
|
||||
preg_match_all('#\d|'.$keys.'#', strrev($line), $numbersEnd);
|
||||
|
||||
$first = $numbersStart[0][0];
|
||||
$last = strrev((string) $numbersEnd[0][0]);
|
||||
|
||||
if (!ctype_digit((string) $first)) {
|
||||
$first = self::NUMBER_STRING[$first];
|
||||
}
|
||||
|
||||
if (!ctype_digit($last)) {
|
||||
$last = self::NUMBER_STRING[$last];
|
||||
}
|
||||
|
||||
return (int) ($first.$last);
|
||||
}
|
||||
}
|
108
data/Y23/day2/Day2.php
Normal file
108
data/Y23/day2/Day2.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace trizz\AdventOfCode\Y23;
|
||||
|
||||
use trizz\AdventOfCode\Solution;
|
||||
|
||||
final class Day2 extends Solution
|
||||
{
|
||||
public static null|int|string $part1ExampleResult = 8;
|
||||
|
||||
public static null|int|string $part1Result = 2810;
|
||||
|
||||
public static null|int|string $part2ExampleResult = 2286;
|
||||
|
||||
public static null|int|string $part2Result = 69110;
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, int>>
|
||||
*/
|
||||
private static array $colorData = [
|
||||
'red' => ['max' => 12],
|
||||
'green' => ['max' => 13],
|
||||
'blue' => ['max' => 14],
|
||||
];
|
||||
|
||||
#[\Override]
|
||||
public function part1(array $data): int
|
||||
{
|
||||
$score = 0;
|
||||
foreach ($data as $line) {
|
||||
[$gameId, $hands] = $this->getHand($line);
|
||||
$validGame = true;
|
||||
foreach ($hands as $hand) {
|
||||
if ($this->isValidHand($hand)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$validGame = false;
|
||||
}
|
||||
|
||||
if ($validGame) {
|
||||
$score += (int) $gameId;
|
||||
}
|
||||
}
|
||||
|
||||
return (int) $score;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function part2(array $data): int
|
||||
{
|
||||
$score = 0;
|
||||
foreach ($data as $line) {
|
||||
[$gameId, $hands] = $this->getHand($line);
|
||||
$handData = ['red' => 0, 'green' => 0, 'blue' => 0];
|
||||
foreach ($hands as $hand) {
|
||||
$colorsInHand = $this->extractColors($hand);
|
||||
foreach ($handData as $color => $value) {
|
||||
if (($colorsInHand[$color] ?? 0) > $value) {
|
||||
$handData[$color] = $colorsInHand[$color];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$score += array_product($handData);
|
||||
}
|
||||
|
||||
return (int) $score;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<int, string>>
|
||||
*/
|
||||
private function getHand(string $line): array
|
||||
{
|
||||
[$gameId, $gameData] = explode(':', $line, 2);
|
||||
[$_, $gameId] = explode(' ', $gameId);
|
||||
|
||||
$hands = explode(';', $gameData);
|
||||
|
||||
return [$gameId, $hands];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, int>
|
||||
*/
|
||||
private function extractColors(string $hand): array
|
||||
{
|
||||
$colors = [];
|
||||
foreach (explode(',', $hand) as $part) {
|
||||
[$number, $color] = explode(' ', trim($part));
|
||||
$colors[$color] = (int) $number;
|
||||
}
|
||||
|
||||
return $colors;
|
||||
}
|
||||
|
||||
private function isValidHand(string $hand): bool
|
||||
{
|
||||
$lineData = ['red' => 0, 'green' => 0, 'blue' => 0];
|
||||
foreach (explode(',', $hand) as $part) {
|
||||
[$number, $color] = explode(' ', trim($part));
|
||||
$lineData[$color] += (int) $number;
|
||||
}
|
||||
|
||||
return !($lineData['red'] > self::$colorData['red']['max'] || $lineData['green'] > self::$colorData['green']['max'] || $lineData['blue'] > self::$colorData['blue']['max']);
|
||||
}
|
||||
}
|
159
data/Y23/day3/Day3.php
Normal file
159
data/Y23/day3/Day3.php
Normal file
@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
namespace trizz\AdventOfCode\Y23;
|
||||
|
||||
use trizz\AdventOfCode\Solution;
|
||||
|
||||
final class Day3 extends Solution
|
||||
{
|
||||
public static null|int|string $part1ExampleResult = 4361;
|
||||
|
||||
public static null|int|string $part1Result = 539637;
|
||||
|
||||
public static null|int|string $part2ExampleResult = 467835;
|
||||
|
||||
public static null|int|string $part2Result = 82_818_007;
|
||||
|
||||
/**
|
||||
* @var string[][]
|
||||
*/
|
||||
private array $matrix = [];
|
||||
|
||||
#[\Override]
|
||||
public function part1(array $data): int
|
||||
{
|
||||
$this->createMatrix($data);
|
||||
$score = 0;
|
||||
|
||||
foreach ($this->matrix as $row => $line) {
|
||||
foreach (array_keys($line) as $col) {
|
||||
$numbers = $this->checkLocation($row, $col);
|
||||
$top = (int) $this->processNumbers($numbers['top'], sum: true);
|
||||
$bottom = (int) $this->processNumbers($numbers['bottom'], sum: true);
|
||||
|
||||
$score += $top + $bottom + max($numbers['left']) + max($numbers['right']);
|
||||
}
|
||||
}
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function part2(array $data): int
|
||||
{
|
||||
$this->createMatrix($data);
|
||||
$score = 0;
|
||||
|
||||
foreach ($this->matrix as $row => $line) {
|
||||
foreach (array_keys($line) as $col) {
|
||||
if ($this->matrix[$row][$col] !== '*') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$numbers = $this->checkLocation($row, $col);
|
||||
|
||||
$top = (array) $this->processNumbers($numbers['top']);
|
||||
$bottom = (array) $this->processNumbers($numbers['bottom']);
|
||||
$left = max($numbers['left']);
|
||||
$right = max($numbers['right']);
|
||||
|
||||
$filteredResults = array_filter(array_values(array_merge_recursive($top, $bottom, [$left, $right])));
|
||||
|
||||
if (count($filteredResults) !== 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$score += array_product($filteredResults);
|
||||
}
|
||||
}
|
||||
|
||||
return (int) $score;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $numbers
|
||||
*
|
||||
* @return int|int[]
|
||||
*/
|
||||
private function processNumbers(array $numbers, bool $sum = false): array|int
|
||||
{
|
||||
$result = [];
|
||||
if ($numbers[0] !== 0 && $numbers[1] === 0 && $numbers[2] !== 0) {
|
||||
$result[] = $numbers[0];
|
||||
$result[] = $numbers[2];
|
||||
} else {
|
||||
$result[] = max($numbers);
|
||||
}
|
||||
|
||||
if ($sum) {
|
||||
return array_sum($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $data
|
||||
*/
|
||||
private function createMatrix(array $data): void
|
||||
{
|
||||
$this->matrix = array_map(static fn ($line): array => str_split((string) $line), $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<int,int>>
|
||||
*/
|
||||
private function checkLocation(int $row, int $col): array
|
||||
{
|
||||
$current = $this->matrix[$row][$col] ?? '.';
|
||||
if ($current === '.' || ctype_digit($current)) {
|
||||
return ['top' => [0, 0, 0], 'left' => [0], 'right' => [0], 'bottom' => [0, 0, 0]];
|
||||
}
|
||||
|
||||
$numbers = array_fill_keys(['top', 'left', 'right', 'bottom'], []);
|
||||
$positions = [
|
||||
'top' => [[$row - 1, $col - 1], [$row - 1, $col], [$row - 1, $col + 1]],
|
||||
'left' => [[$row, $col - 1]],
|
||||
'right' => [[$row, $col + 1]],
|
||||
'bottom' => [[$row + 1, $col - 1], [$row + 1, $col], [$row + 1, $col + 1]],
|
||||
];
|
||||
|
||||
foreach ($positions as $direction => $coords) {
|
||||
foreach ($coords as $coord) {
|
||||
$numbers[$direction][] = (int) $this->getNumber(...$coord);
|
||||
}
|
||||
}
|
||||
|
||||
return $numbers;
|
||||
}
|
||||
|
||||
private function getNumber(int $row, int $col, string $direction = null): ?string
|
||||
{
|
||||
$number = $this->matrix[$row][$col] ?? null;
|
||||
|
||||
if ($number === null || $number === '.' || !ctype_digit($number)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$toLeft = null;
|
||||
$toRight = null;
|
||||
|
||||
if ($direction === null || $direction === 'left') {
|
||||
$toLeft = $this->getNumber($row, $col - 1, 'left');
|
||||
}
|
||||
|
||||
if ($direction === null || $direction === 'right') {
|
||||
$toRight = $this->getNumber($row, $col + 1, 'right');
|
||||
}
|
||||
|
||||
if ($toLeft !== null) {
|
||||
$number = $toLeft.$number;
|
||||
}
|
||||
|
||||
if ($toRight !== null) {
|
||||
return $number.$toRight;
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user