Apply rector, phpstan and php-cs-fixer
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:
parent
f35c24d35d
commit
b07b0b2ae8
15
.drone.yml
15
.drone.yml
@ -9,22 +9,29 @@ steps:
|
|||||||
- composer install
|
- composer install
|
||||||
|
|
||||||
- name: phpstan
|
- name: phpstan
|
||||||
image: php:8
|
image: php:8.1
|
||||||
depends_on:
|
depends_on:
|
||||||
- install
|
- install
|
||||||
commands:
|
commands:
|
||||||
- vendor/bin/phpstan analyse
|
- vendor/bin/phpstan analyse
|
||||||
|
|
||||||
|
- name: rector
|
||||||
|
image: php:8.1
|
||||||
|
depends_on:
|
||||||
|
- install
|
||||||
|
commands:
|
||||||
|
- vendor/bin/rector process --dry-run
|
||||||
|
|
||||||
- name: phpunit
|
- name: phpunit
|
||||||
image: php:8
|
image: php:8.1
|
||||||
depends_on:
|
depends_on:
|
||||||
- install
|
- install
|
||||||
commands:
|
commands:
|
||||||
- vendor/bin/phpunit
|
- vendor/bin/phpunit
|
||||||
|
|
||||||
- name: style check
|
- name: style check
|
||||||
image: php:8
|
image: php:8.1
|
||||||
depends_on:
|
depends_on:
|
||||||
- install
|
- install
|
||||||
commands:
|
commands:
|
||||||
- PHP_CS_FIXER_IGNORE_ENV=true vendor/bin/php-cs-fixer fix
|
- vendor/bin/php-cs-fixer fix
|
||||||
|
@ -14,7 +14,6 @@ return $config
|
|||||||
'phpdoc_order' => true,
|
'phpdoc_order' => true,
|
||||||
'ordered_class_elements' => true,
|
'ordered_class_elements' => true,
|
||||||
'multiline_whitespace_before_semicolons' => false,
|
'multiline_whitespace_before_semicolons' => false,
|
||||||
'no_superfluous_phpdoc_tags' => false,
|
|
||||||
'phpdoc_annotation_without_dot' => false,
|
'phpdoc_annotation_without_dot' => false,
|
||||||
'phpdoc_types_order' => [
|
'phpdoc_types_order' => [
|
||||||
'null_adjustment' => 'always_last',
|
'null_adjustment' => 'always_last',
|
||||||
|
54
Taskfile.yaml
Normal file
54
Taskfile.yaml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# https://taskfile.dev
|
||||||
|
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
vars:
|
||||||
|
PHP_IMAGE: php:8.1
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
cmds:
|
||||||
|
- task --list-all
|
||||||
|
silent: true
|
||||||
|
|
||||||
|
check:
|
||||||
|
cmds:
|
||||||
|
- task: echo_title
|
||||||
|
vars: {TITLE: Running php-cs-fixer...}
|
||||||
|
- task: style
|
||||||
|
- task: echo_title
|
||||||
|
vars: {TITLE: Running phpstan...}
|
||||||
|
- task: phpstan
|
||||||
|
- task: echo_title
|
||||||
|
vars: { TITLE: Running rector... }
|
||||||
|
- task: rector
|
||||||
|
- task: echo_title
|
||||||
|
vars: {TITLE: Running phpunit}
|
||||||
|
- task: phpunit
|
||||||
|
|
||||||
|
style:
|
||||||
|
cmds:
|
||||||
|
- php vendor/bin/php-cs-fixer fix
|
||||||
|
silent: true
|
||||||
|
|
||||||
|
phpstan:
|
||||||
|
cmds:
|
||||||
|
- php vendor/bin/phpstan --configuration=./phpstan.neon analyse
|
||||||
|
silent: true
|
||||||
|
|
||||||
|
rector:
|
||||||
|
cmds:
|
||||||
|
- php vendor/bin/rector process
|
||||||
|
silent: true
|
||||||
|
|
||||||
|
phpunit:
|
||||||
|
cmds:
|
||||||
|
- php vendor/bin/phpunit
|
||||||
|
silent: true
|
||||||
|
|
||||||
|
echo_title:
|
||||||
|
silent: true
|
||||||
|
cmds:
|
||||||
|
- echo ------------------------
|
||||||
|
- echo {{.TITLE}}
|
||||||
|
- echo ------------------------
|
8
aoc
8
aoc
@ -7,11 +7,15 @@ use Symfony\Component\Console\Application;
|
|||||||
use trizz\AdventOfCode\ExecuteDay;
|
use trizz\AdventOfCode\ExecuteDay;
|
||||||
use trizz\AdventOfCode\Puzzle;
|
use trizz\AdventOfCode\Puzzle;
|
||||||
|
|
||||||
(new CollisionProvider)->register();
|
(new CollisionProvider())->register();
|
||||||
|
|
||||||
$application = new Application();
|
$application = new Application('Advent of Code by trizz');
|
||||||
|
|
||||||
$application->add(new Puzzle());
|
$application->add(new Puzzle());
|
||||||
$application->add(new ExecuteDay());
|
$application->add(new ExecuteDay());
|
||||||
|
|
||||||
|
try {
|
||||||
$application->run();
|
$application->run();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
@ -12,16 +12,17 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"php": "^8.1",
|
"php": "^8.1",
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
"symfony/console": "^5",
|
"cebe/markdown": "^1.2",
|
||||||
"cebe/markdown": "^1.2"
|
|
||||||
"phppkg/cli-markdown": "^2.0",
|
"phppkg/cli-markdown": "^2.0",
|
||||||
|
"symfony/console": "^6"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"friendsofphp/php-cs-fixer": "^3.3",
|
"friendsofphp/php-cs-fixer": "^3.3",
|
||||||
"jetbrains/phpstorm-attributes": "^1.0",
|
"jetbrains/phpstorm-attributes": "^1.0",
|
||||||
"nunomaduro/collision": "^5.10",
|
"nunomaduro/collision": "^6",
|
||||||
"phpstan/phpstan": "^1.2",
|
"phpstan/phpstan": "^1.2",
|
||||||
"phpunit/phpunit": "^9.5",
|
"phpunit/phpunit": "^9.5",
|
||||||
|
"rector/rector": "^0.14.8",
|
||||||
"symfony/var-dumper": "^6.0"
|
"symfony/var-dumper": "^6.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -34,11 +35,6 @@
|
|||||||
"Tests\\": "tests/"
|
"Tests\\": "tests/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
|
||||||
"test": "vendor/bin/phpunit",
|
|
||||||
"style": "PHP_CS_FIXER_IGNORE_ENV=true vendor/bin/php-cs-fixer fix",
|
|
||||||
"phpstan": "vendor/bin/phpstan analyse"
|
|
||||||
},
|
|
||||||
"config": {
|
"config": {
|
||||||
"sort-packages": true,
|
"sort-packages": true,
|
||||||
"optimize-autoloader": true
|
"optimize-autoloader": true
|
||||||
|
1552
composer.lock
generated
1552
composer.lock
generated
File diff suppressed because it is too large
Load Diff
56
phpstan-baseline.neon
Normal file
56
phpstan-baseline.neon
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
parameters:
|
||||||
|
ignoreErrors:
|
||||||
|
-
|
||||||
|
message: "#^Method trizz\\\\AdventOfCode\\\\Y21\\\\Day4\\:\\:arrayHasSingleValue\\(\\) has parameter \\$array with no value type specified in iterable type array\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Y21/Day4.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Method trizz\\\\AdventOfCode\\\\Y21\\\\Day4\\:\\:checkCards\\(\\) has parameter \\$cards with no value type specified in iterable type array\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Y21/Day4.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Method trizz\\\\AdventOfCode\\\\Y21\\\\Day4\\:\\:checkCards\\(\\) has parameter \\$finishedCards with no value type specified in iterable type array\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Y21/Day4.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Parameter \\#1 \\$array of function array_values expects array, array\\<mixed, int\\|false\\>\\|string given\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Y21/Day4.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Parameter \\#1 \\$numberList of method trizz\\\\AdventOfCode\\\\Y21\\\\Day4\\:\\:explodeNumbers\\(\\) expects string, array\\<mixed, int\\|false\\>\\|string given\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Y21/Day4.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Method trizz\\\\AdventOfCode\\\\Y21\\\\Day6\\:\\:processDay\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Y21/Day6.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Parameter \\#1 \\$state of method trizz\\\\AdventOfCode\\\\Y21\\\\Day6\\:\\:processDay\\(\\) expects array\\{int\\: int\\}, array given\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Y21/Day6.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Method trizz\\\\AdventOfCode\\\\Y21\\\\Day7\\:\\:calculateFuel\\(\\) should return int but returns int\\<0, max\\>\\|false\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Y21/Day7.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Method trizz\\\\AdventOfCode\\\\Y21\\\\Day8\\:\\:mapDigits\\(\\) has parameter \\$patterns with no value type specified in iterable type array\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Y21/Day8.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Property trizz\\\\AdventOfCode\\\\Y21\\\\Day8\\:\\:\\$digitPatterns type has no value type specified in iterable type array\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Y21/Day8.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Property trizz\\\\AdventOfCode\\\\Y21\\\\Day8\\:\\:\\$patternDigits type has no value type specified in iterable type array\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Y21/Day8.php
|
@ -3,3 +3,6 @@ parameters:
|
|||||||
paths:
|
paths:
|
||||||
- src
|
- src
|
||||||
- tests
|
- tests
|
||||||
|
|
||||||
|
includes:
|
||||||
|
- phpstan-baseline.neon
|
||||||
|
33
rector.php
Normal file
33
rector.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
|
||||||
|
use Rector\Config\RectorConfig;
|
||||||
|
use Rector\Set\ValueObject\LevelSetList;
|
||||||
|
use Rector\Set\ValueObject\SetList;
|
||||||
|
|
||||||
|
return static function (RectorConfig $rectorConfig): void {
|
||||||
|
$rectorConfig->paths(
|
||||||
|
[
|
||||||
|
__DIR__.'/src',
|
||||||
|
__DIR__.'/tests',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// register a single rule
|
||||||
|
$rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
|
||||||
|
|
||||||
|
// define sets of rules
|
||||||
|
$rectorConfig->sets(
|
||||||
|
[
|
||||||
|
LevelSetList::UP_TO_PHP_81,
|
||||||
|
SetList::CODE_QUALITY,
|
||||||
|
SetList::CODING_STYLE,
|
||||||
|
SetList::TYPE_DECLARATION_STRICT,
|
||||||
|
SetList::NAMING,
|
||||||
|
SetList::PRIVATIZATION,
|
||||||
|
SetList::EARLY_RETURN,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
};
|
@ -7,19 +7,14 @@ use Symfony\Component\Console\Input\InputArgument;
|
|||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
class ExecuteDay extends Command
|
final class ExecuteDay extends Command
|
||||||
{
|
{
|
||||||
protected int $day;
|
private int $day;
|
||||||
|
|
||||||
|
private int $year;
|
||||||
|
|
||||||
protected int $year;
|
|
||||||
/**
|
|
||||||
* @var string The title.
|
|
||||||
*/
|
|
||||||
private string $title;
|
private string $title;
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the command.
|
|
||||||
*/
|
|
||||||
protected function configure(): void
|
protected function configure(): void
|
||||||
{
|
{
|
||||||
$this
|
$this
|
||||||
@ -29,10 +24,6 @@ class ExecuteDay extends Command
|
|||||||
->addArgument('year', InputArgument::OPTIONAL, 'The year', date('y'));
|
->addArgument('year', InputArgument::OPTIONAL, 'The year', date('y'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the command after the input has been bound and before the input
|
|
||||||
* is validated.
|
|
||||||
*/
|
|
||||||
protected function initialize(InputInterface $input, OutputInterface $output): void
|
protected function initialize(InputInterface $input, OutputInterface $output): void
|
||||||
{
|
{
|
||||||
$this->day = $input->getArgument('day');
|
$this->day = $input->getArgument('day');
|
||||||
@ -45,14 +36,10 @@ class ExecuteDay extends Command
|
|||||||
$output->writeln(str_repeat('-', strlen($this->title)));
|
$output->writeln(str_repeat('-', strlen($this->title)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the current command.
|
|
||||||
*
|
|
||||||
* @return int 0 if everything went fine, or an exit code
|
|
||||||
*/
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$className = sprintf('%s\\Y%d\\Day%d', __NAMESPACE__, $this->year, $this->day);
|
$className = sprintf('%s\\Y%d\\Day%d', __NAMESPACE__, $this->year, $this->day);
|
||||||
|
|
||||||
/** @var Solution $class */
|
/** @var Solution $class */
|
||||||
$class = new $className();
|
$class = new $className();
|
||||||
$class->loadData();
|
$class->loadData();
|
||||||
|
@ -2,25 +2,23 @@
|
|||||||
|
|
||||||
namespace trizz\AdventOfCode;
|
namespace trizz\AdventOfCode;
|
||||||
|
|
||||||
|
use PhpPkg\CliMarkdown\CliMarkdown;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use trizz\AdventOfCode\Utils\SymfonyConsoleMarkdown;
|
|
||||||
|
|
||||||
class Puzzle extends Command
|
final class Puzzle extends Command
|
||||||
{
|
{
|
||||||
protected function configure(): void
|
protected function configure(): void
|
||||||
{
|
{
|
||||||
$this
|
$this
|
||||||
->setName('puzzle')
|
->setName('puzzle')
|
||||||
|
->setDescription('Show the puzzle description.')
|
||||||
->addArgument('day', InputArgument::REQUIRED, 'The day number.')
|
->addArgument('day', InputArgument::REQUIRED, 'The day number.')
|
||||||
->addArgument('year', InputArgument::OPTIONAL, 'The year', date('y'));
|
->addArgument('year', InputArgument::OPTIONAL, 'The year', date('y'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$contents = file_get_contents(
|
$contents = file_get_contents(
|
||||||
@ -31,7 +29,14 @@ class Puzzle extends Command
|
|||||||
(int) $input->getArgument('day')
|
(int) $input->getArgument('day')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$rendered = (new SymfonyConsoleMarkdown())->render($contents);
|
|
||||||
|
if (!$contents) {
|
||||||
|
$output->writeln('Can not read puzzle.');
|
||||||
|
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rendered = (new CliMarkdown())->render($contents);
|
||||||
|
|
||||||
$output->writeln($rendered);
|
$output->writeln($rendered);
|
||||||
|
|
||||||
|
@ -16,12 +16,14 @@ abstract class Solution
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[] The data to use.
|
* @var string[] The data to use.
|
||||||
|
*
|
||||||
* @psalm-suppress PropertyNotSetInConstructor
|
* @psalm-suppress PropertyNotSetInConstructor
|
||||||
*/
|
*/
|
||||||
public ?array $data = null;
|
public ?array $data = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[] The example data.
|
* @var string[] The example data.
|
||||||
|
*
|
||||||
* @psalm-suppress PropertyNotSetInConstructor
|
* @psalm-suppress PropertyNotSetInConstructor
|
||||||
*/
|
*/
|
||||||
public ?array $exampleData = null;
|
public ?array $exampleData = null;
|
||||||
@ -50,7 +52,7 @@ abstract class Solution
|
|||||||
return 'n/a';
|
return 'n/a';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadData()
|
public function loadData(): void
|
||||||
{
|
{
|
||||||
$dataFile = sprintf('%s/../data/Y%d/day%d/data.txt', __DIR__, $this->year(), $this->day());
|
$dataFile = sprintf('%s/../data/Y%d/day%d/data.txt', __DIR__, $this->year(), $this->day());
|
||||||
$dataExampleFile = sprintf('%s/../data/Y%d/day%d/example.txt', __DIR__, $this->year(), $this->day());
|
$dataExampleFile = sprintf('%s/../data/Y%d/day%d/example.txt', __DIR__, $this->year(), $this->day());
|
||||||
@ -80,16 +82,19 @@ abstract class Solution
|
|||||||
return (int) substr(explode('\\', static::class)[3], 3);
|
return (int) substr(explode('\\', static::class)[3], 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasData()
|
public function hasData(): bool
|
||||||
{
|
{
|
||||||
return !empty($this->data);
|
return !empty($this->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasExampleData()
|
public function hasExampleData(): bool
|
||||||
{
|
{
|
||||||
return !empty($this->exampleData);
|
return !empty($this->exampleData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{part1: int|string, part2: int|string}
|
||||||
|
*/
|
||||||
#[ArrayShape(['part1' => 'int|string', 'part2' => 'int|string'])]
|
#[ArrayShape(['part1' => 'int|string', 'part2' => 'int|string'])]
|
||||||
public function results(bool $useExampleData = true): array
|
public function results(bool $useExampleData = true): array
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace trizz\AdventOfCode\Utils;
|
namespace trizz\AdventOfCode\Utils;
|
||||||
|
|
||||||
class Arr
|
final class Arr
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Flatten a multi-dimensional array into a single level.
|
* Flatten a multi-dimensional array into a single level.
|
||||||
@ -11,12 +11,11 @@ class Arr
|
|||||||
*
|
*
|
||||||
* @see https://github.com/laravel/framework/blob/c16367a1af68d8f3a1addc1a819f9864334e2c66/src/Illuminate/Collections/Arr.php#L221-L249
|
* @see https://github.com/laravel/framework/blob/c16367a1af68d8f3a1addc1a819f9864334e2c66/src/Illuminate/Collections/Arr.php#L221-L249
|
||||||
*
|
*
|
||||||
* @param iterable $array
|
* @param array<mixed> $array
|
||||||
* @param float|int $depth
|
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array<mixed>
|
||||||
*/
|
*/
|
||||||
public static function flatten(iterable $array, float|int $depth = INF)
|
public static function flatten(iterable $array, float|int $depth = INF): array
|
||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace trizz\AdventOfCode\Utils;
|
namespace trizz\AdventOfCode\Utils;
|
||||||
|
|
||||||
class Str
|
final class Str
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Check if the entirety of string two matches string one.
|
* Check if the entirety of string two matches string one.
|
||||||
|
@ -4,12 +4,14 @@ namespace trizz\AdventOfCode\Y21;
|
|||||||
|
|
||||||
use trizz\AdventOfCode\Solution;
|
use trizz\AdventOfCode\Solution;
|
||||||
|
|
||||||
class Day1 extends Solution
|
final class Day1 extends Solution
|
||||||
{
|
{
|
||||||
public static int|string|null $part1ExampleResult = 7;
|
public static int|string|null $part1ExampleResult = 7;
|
||||||
|
|
||||||
public static int|string|null $part1Result = 1688;
|
public static int|string|null $part1Result = 1688;
|
||||||
|
|
||||||
public static int|string|null $part2ExampleResult = 5;
|
public static int|string|null $part2ExampleResult = 5;
|
||||||
|
|
||||||
public static int|string|null $part2Result = 1728;
|
public static int|string|null $part2Result = 1728;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,13 +4,15 @@ namespace trizz\AdventOfCode\Y21;
|
|||||||
|
|
||||||
use trizz\AdventOfCode\Solution;
|
use trizz\AdventOfCode\Solution;
|
||||||
|
|
||||||
class Day2 extends Solution
|
final class Day2 extends Solution
|
||||||
{
|
{
|
||||||
public static int|string|null $part1ExampleResult = 150;
|
public static int|string|null $part1ExampleResult = 150;
|
||||||
public static int|string|null $part1Result = 1654760;
|
|
||||||
|
public static int|string|null $part1Result = 1_654_760;
|
||||||
|
|
||||||
public static int|string|null $part2ExampleResult = 900;
|
public static int|string|null $part2ExampleResult = 900;
|
||||||
public static int|string|null $part2Result = 1956047400;
|
|
||||||
|
public static int|string|null $part2Result = 1_956_047_400;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
|
@ -4,10 +4,11 @@ namespace trizz\AdventOfCode\Y21;
|
|||||||
|
|
||||||
use trizz\AdventOfCode\Solution;
|
use trizz\AdventOfCode\Solution;
|
||||||
|
|
||||||
class Day3 extends Solution
|
final class Day3 extends Solution
|
||||||
{
|
{
|
||||||
public static int|string|null $part1ExampleResult = 198;
|
public static int|string|null $part1ExampleResult = 198;
|
||||||
public static int|string|null $part1Result = 3309596;
|
|
||||||
|
public static int|string|null $part1Result = 3_309_596;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
@ -27,9 +28,9 @@ class Day3 extends Solution
|
|||||||
$gammaRate = '';
|
$gammaRate = '';
|
||||||
$epsilonRate = '';
|
$epsilonRate = '';
|
||||||
|
|
||||||
foreach ($bits as $values) {
|
foreach ($bits as $bit) {
|
||||||
$zeros = array_filter($values, static fn ($value) => $value === '0');
|
$zeros = array_filter($bit, static fn ($value) => $value === '0');
|
||||||
$ones = array_filter($values, static fn ($value) => $value === '1');
|
$ones = array_filter($bit, static fn ($value) => $value === '1');
|
||||||
|
|
||||||
$gammaRate .= ($ones > $zeros) ? '1' : '0';
|
$gammaRate .= ($ones > $zeros) ? '1' : '0';
|
||||||
$epsilonRate .= ($ones < $zeros) ? '1' : '0';
|
$epsilonRate .= ($ones < $zeros) ? '1' : '0';
|
||||||
|
@ -4,12 +4,14 @@ namespace trizz\AdventOfCode\Y21;
|
|||||||
|
|
||||||
use trizz\AdventOfCode\Solution;
|
use trizz\AdventOfCode\Solution;
|
||||||
|
|
||||||
class Day4 extends Solution
|
final class Day4 extends Solution
|
||||||
{
|
{
|
||||||
public static int|string|null $part1ExampleResult = 4512;
|
public static int|string|null $part1ExampleResult = 4512;
|
||||||
|
|
||||||
public static int|string|null $part1Result = 60368;
|
public static int|string|null $part1Result = 60368;
|
||||||
|
|
||||||
public static int|string|null $part2ExampleResult = 1924;
|
public static int|string|null $part2ExampleResult = 1924;
|
||||||
|
|
||||||
public static int|string|null $part2Result = 17435;
|
public static int|string|null $part2Result = 17435;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,15 +32,13 @@ class Day4 extends Solution
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int[] $winningCard
|
* @param int[] $winningCard
|
||||||
* @param int $number
|
|
||||||
* @psalm-param array<int, array<array-key, bool|int>|string> $winningCard
|
|
||||||
*
|
*
|
||||||
* @return int
|
* @psalm-param array<int, array<array-key, bool|int>|string> $winningCard
|
||||||
*/
|
*/
|
||||||
protected function calculateScore(array $winningCard, int $number): int
|
private function calculateScore(array $winningCard, int $number): int
|
||||||
{
|
{
|
||||||
$return = [];
|
$return = [];
|
||||||
array_walk_recursive($winningCard, static function (bool $value, int $key) use (&$return) {
|
array_walk_recursive($winningCard, static function (bool $value, int $key) use (&$return): void {
|
||||||
$return[$key] = $value;
|
$return[$key] = $value;
|
||||||
});
|
});
|
||||||
$unusedNumbers = array_keys(array_filter($return, static fn (bool $value) => !$value));
|
$unusedNumbers = array_keys(array_filter($return, static fn (bool $value) => !$value));
|
||||||
@ -47,14 +47,13 @@ class Day4 extends Solution
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $numberList
|
* @param non-empty-string $separator
|
||||||
* @param string $separator
|
|
||||||
*
|
*
|
||||||
* @return int[]
|
* @return int[]
|
||||||
*
|
*
|
||||||
* @psalm-return array<int, int>
|
* @psalm-return array<int, int>
|
||||||
*/
|
*/
|
||||||
protected function explodeNumbers(string $numberList, string $separator): array
|
private function explodeNumbers(string $numberList, string $separator): array
|
||||||
{
|
{
|
||||||
return array_map(
|
return array_map(
|
||||||
static fn ($value) => (int) $value,
|
static fn ($value) => (int) $value,
|
||||||
@ -67,13 +66,10 @@ class Day4 extends Solution
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[] $data
|
* @param string[] $data
|
||||||
* @param bool $firstWins
|
|
||||||
*
|
|
||||||
* @return int|string
|
|
||||||
*/
|
*/
|
||||||
protected function playBingo(array $data, bool $firstWins = true): int|string
|
private function playBingo(array $data, bool $firstWins = true): int|string
|
||||||
{
|
{
|
||||||
$numbers = $this->explodeNumbers(array_shift($data), ',');
|
$numbers = $this->explodeNumbers(array_shift($data) ?? '', ',');
|
||||||
$cards = $this->setupCards($data);
|
$cards = $this->setupCards($data);
|
||||||
$finishedCards = [];
|
$finishedCards = [];
|
||||||
|
|
||||||
@ -129,7 +125,7 @@ class Day4 extends Solution
|
|||||||
*
|
*
|
||||||
* @psalm-return array<int, array<int, array<false|int>|string>>
|
* @psalm-return array<int, array<int, array<false|int>|string>>
|
||||||
*/
|
*/
|
||||||
protected function setupCards(array $data): array
|
private function setupCards(array $data): array
|
||||||
{
|
{
|
||||||
$cards = array_chunk($data, 5);
|
$cards = array_chunk($data, 5);
|
||||||
foreach ($cards as $card => $rows) {
|
foreach ($cards as $card => $rows) {
|
||||||
@ -148,7 +144,7 @@ class Day4 extends Solution
|
|||||||
*
|
*
|
||||||
* @psalm-return list<int>
|
* @psalm-return list<int>
|
||||||
*/
|
*/
|
||||||
protected function checkCards(array $cards, array $finishedCards): array
|
private function checkCards(array $cards, array $finishedCards): array
|
||||||
{
|
{
|
||||||
$winningCards = [];
|
$winningCards = [];
|
||||||
// Check rows
|
// Check rows
|
||||||
@ -191,7 +187,7 @@ class Day4 extends Solution
|
|||||||
return $winningCards;
|
return $winningCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function arrayHasSingleValue(array $array, bool $value): bool
|
private function arrayHasSingleValue(array $array, bool $value): bool
|
||||||
{
|
{
|
||||||
return count(array_unique($array)) === 1 && end($array) === $value;
|
return count(array_unique($array)) === 1 && end($array) === $value;
|
||||||
}
|
}
|
||||||
|
@ -5,20 +5,22 @@ namespace trizz\AdventOfCode\Y21;
|
|||||||
use JetBrains\PhpStorm\Immutable;
|
use JetBrains\PhpStorm\Immutable;
|
||||||
use trizz\AdventOfCode\Solution;
|
use trizz\AdventOfCode\Solution;
|
||||||
|
|
||||||
class Day6 extends Solution
|
final class Day6 extends Solution
|
||||||
{
|
{
|
||||||
public static int|string|null $part1ExampleResult = 5934;
|
public static int|string|null $part1ExampleResult = 5934;
|
||||||
|
|
||||||
public static int|string|null $part1Result = 350917;
|
public static int|string|null $part1Result = 350917;
|
||||||
|
|
||||||
public static int|string|null $part2ExampleResult = 26984457539;
|
public static int|string|null $part2ExampleResult = 26_984_457_539;
|
||||||
public static int|string|null $part2Result = 1592918715629;
|
|
||||||
|
public static int|string|null $part2Result = 1_592_918_715_629;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int[]
|
* @var int[]
|
||||||
|
*
|
||||||
* @psalm-param array{int: int}
|
* @psalm-param array{int: int}
|
||||||
*/
|
*/
|
||||||
#[Immutable]
|
#[Immutable] private array $startState = [
|
||||||
protected array $startState = [
|
|
||||||
8 => 0,
|
8 => 0,
|
||||||
7 => 0,
|
7 => 0,
|
||||||
6 => 0,
|
6 => 0,
|
||||||
@ -48,11 +50,10 @@ class Day6 extends Solution
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int[] $state
|
* @param int[] $state
|
||||||
* @psalm-param array{int: int} $state
|
|
||||||
*
|
*
|
||||||
* @return array
|
* @psalm-param array{int: int} $state
|
||||||
*/
|
*/
|
||||||
protected function processDay(array $state): array
|
private function processDay(array $state): array
|
||||||
{
|
{
|
||||||
$newState = $state;
|
$newState = $state;
|
||||||
|
|
||||||
@ -75,11 +76,11 @@ class Day6 extends Solution
|
|||||||
return $newState;
|
return $newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function processPuzzle(int $numberOfDays, string $data): int
|
private function processPuzzle(int $numberOfDays, string $data): int
|
||||||
{
|
{
|
||||||
$state = $this->startState;
|
$state = $this->startState;
|
||||||
|
|
||||||
array_map(static function (string $stateValue) use (&$state) {
|
array_map(static function (string $stateValue) use (&$state): void {
|
||||||
++$state[(int) $stateValue];
|
++$state[(int) $stateValue];
|
||||||
}, explode(',', $data));
|
}, explode(',', $data));
|
||||||
|
|
||||||
|
@ -4,13 +4,15 @@ namespace trizz\AdventOfCode\Y21;
|
|||||||
|
|
||||||
use trizz\AdventOfCode\Solution;
|
use trizz\AdventOfCode\Solution;
|
||||||
|
|
||||||
class Day7 extends Solution
|
final class Day7 extends Solution
|
||||||
{
|
{
|
||||||
public static int|string|null $part1ExampleResult = 37;
|
public static int|string|null $part1ExampleResult = 37;
|
||||||
|
|
||||||
public static int|string|null $part1Result = 344297;
|
public static int|string|null $part1Result = 344297;
|
||||||
|
|
||||||
public static int|string|null $part2ExampleResult = 168;
|
public static int|string|null $part2ExampleResult = 168;
|
||||||
public static int|string|null $part2Result = 97164301;
|
|
||||||
|
public static int|string|null $part2Result = 97_164_301;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
@ -28,15 +30,10 @@ class Day7 extends Solution
|
|||||||
return $this->calculateFuel($data[0], forPart2: true);
|
return $this->calculateFuel($data[0], forPart2: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function calculateFuel(string $data, bool $forPart2 = false): int
|
||||||
* @param string $data
|
|
||||||
* @param bool $forPart2
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
protected function calculateFuel(string $data, bool $forPart2 = false): int
|
|
||||||
{
|
{
|
||||||
$crabs = array_map(static fn (string $crab) => (int) $crab, explode(',', $data));
|
$crabs = array_map(static fn (string $crab) => (int) $crab, explode(',', $data));
|
||||||
|
|
||||||
/** @psalm-param array{int: int} $fuelPerPosition */
|
/** @psalm-param array{int: int} $fuelPerPosition */
|
||||||
$fuelPerPosition = [];
|
$fuelPerPosition = [];
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use trizz\AdventOfCode\Solution;
|
|||||||
use trizz\AdventOfCode\Utils\Arr;
|
use trizz\AdventOfCode\Utils\Arr;
|
||||||
use trizz\AdventOfCode\Utils\Str;
|
use trizz\AdventOfCode\Utils\Str;
|
||||||
|
|
||||||
class Day8 extends Solution
|
final class Day8 extends Solution
|
||||||
{
|
{
|
||||||
public static int|string|null $part1ExampleResult = 26;
|
public static int|string|null $part1ExampleResult = 26;
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ class Day8 extends Solution
|
|||||||
|
|
||||||
public static int|string|null $part2ExampleResult = 61229;
|
public static int|string|null $part2ExampleResult = 61229;
|
||||||
|
|
||||||
public static int|string|null $part2Result = 1027422;
|
public static int|string|null $part2Result = 1_027_422;
|
||||||
|
|
||||||
private array $digitPatterns;
|
private array $digitPatterns;
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ class Day8 extends Solution
|
|||||||
public function part1(array $data): int
|
public function part1(array $data): int
|
||||||
{
|
{
|
||||||
$values = array_map(
|
$values = array_map(
|
||||||
static fn ($item) => strlen($item),
|
static fn ($item) => strlen((string) $item),
|
||||||
Arr::flatten(
|
Arr::flatten(
|
||||||
array_map(
|
array_map(
|
||||||
static fn ($item) => explode(' ', $item),
|
static fn ($item) => explode(' ', $item),
|
||||||
@ -48,8 +48,8 @@ class Day8 extends Solution
|
|||||||
foreach ($data as $line) {
|
foreach ($data as $line) {
|
||||||
$item = explode(' | ', $line);
|
$item = explode(' | ', $line);
|
||||||
$sequences[] = [
|
$sequences[] = [
|
||||||
'patterns' => array_map([Str::class, 'sort'], explode(' ', $item[0])),
|
'patterns' => array_map(Str::sort(...), explode(' ', $item[0])),
|
||||||
'shown' => array_map([Str::class, 'sort'], explode(' ', $item[1])),
|
'shown' => array_map(Str::sort(...), explode(' ', $item[1])),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,56 +2,84 @@
|
|||||||
|
|
||||||
namespace Tests;
|
namespace Tests;
|
||||||
|
|
||||||
use trizz\AdventOfCode\ExecuteDay;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use trizz\AdventOfCode\Solution;
|
use trizz\AdventOfCode\Solution;
|
||||||
|
|
||||||
class SolutionsTest extends TestCase
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class SolutionsTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @dataProvider loadSolutions
|
* @dataProvider loadSolutions
|
||||||
*/
|
*/
|
||||||
public function testSolutionPart1Example(Solution $class): void
|
public function testSolutionPart1Example(Solution $solution): void
|
||||||
{
|
{
|
||||||
$this->runPart($class, part: 1, testExample: true);
|
$this->runPart($solution, part: 1, testExample: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider loadSolutions
|
* @dataProvider loadSolutions
|
||||||
|
*
|
||||||
* @depends testSolutionPart1Example
|
* @depends testSolutionPart1Example
|
||||||
*/
|
*/
|
||||||
public function testSolutionPart1(Solution $class): void
|
public function testSolutionPart1(Solution $solution): void
|
||||||
{
|
{
|
||||||
$this->runPart($class, part: 1, testExample: false);
|
$this->runPart($solution, part: 1, testExample: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider loadSolutions
|
* @dataProvider loadSolutions
|
||||||
|
*
|
||||||
* @depends testSolutionPart1
|
* @depends testSolutionPart1
|
||||||
*/
|
*/
|
||||||
public function testSolutionPart2Example(Solution $class): void
|
public function testSolutionPart2Example(Solution $solution): void
|
||||||
{
|
{
|
||||||
$this->runPart($class, part: 2, testExample: true);
|
$this->runPart($solution, part: 2, testExample: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider loadSolutions
|
* @dataProvider loadSolutions
|
||||||
|
*
|
||||||
* @depends testSolutionPart2Example
|
* @depends testSolutionPart2Example
|
||||||
*/
|
*/
|
||||||
public function testSolutionPart2(Solution $class): void
|
public function testSolutionPart2(Solution $solution): void
|
||||||
{
|
{
|
||||||
$this->runPart($class, part: 2, testExample: false);
|
$this->runPart($solution, part: 2, testExample: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function runPart(Solution $class, int $part, bool $testExample): void
|
/**
|
||||||
|
* @return array<string, array<int, Solution>>
|
||||||
|
*/
|
||||||
|
public function loadSolutions(): array
|
||||||
|
{
|
||||||
|
$classes = [];
|
||||||
|
for ($year = 15; $year <= date('y'); ++$year) {
|
||||||
|
if (is_dir(__DIR__.'/../src/Y'.$year)) {
|
||||||
|
for ($day = 1; $day < 26; ++$day) {
|
||||||
|
$className = sprintf('trizz\\AdventOfCode\\Y%d\\Day%d', $year, $day);
|
||||||
|
if (class_exists($className)) {
|
||||||
|
/** @var Solution $class */
|
||||||
|
$class = new $className();
|
||||||
|
$class->loadData();
|
||||||
|
$classes["Year '".$year.' / Day '.$day] = [$class];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function runPart(Solution $solution, int $part, bool $testExample): void
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
($testExample && $class->hasExampleData())
|
($testExample && $solution->hasExampleData())
|
||||||
|| (!$testExample && $class->hasData())
|
|| (!$testExample && $solution->hasData())
|
||||||
) {
|
) {
|
||||||
$expectedResult = $class::${'part'.$part.($testExample ? 'Example' : null).'Result'};
|
$expectedResult = $solution::${'part'.$part.($testExample ? 'Example' : null).'Result'};
|
||||||
if ($expectedResult) {
|
if ($expectedResult) {
|
||||||
$result = $class->{'part'.$part.'Data'}(useExampleData: $testExample);
|
$result = $solution->{'part'.$part.'Data'}(useExampleData: $testExample);
|
||||||
self::assertSame($expectedResult, $result);
|
self::assertSame($expectedResult, $result);
|
||||||
} else {
|
} else {
|
||||||
$this->markTestSkipped('No '.($testExample ? 'example' : 'expected').' data for part '.$part.'.');
|
$this->markTestSkipped('No '.($testExample ? 'example' : 'expected').' data for part '.$part.'.');
|
||||||
@ -60,23 +88,4 @@ class SolutionsTest extends TestCase
|
|||||||
$this->markTestSkipped('No example and expected data for part '.$part.'.');
|
$this->markTestSkipped('No example and expected data for part '.$part.'.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadSolutions(): array
|
|
||||||
{
|
|
||||||
$classes = [];
|
|
||||||
for ($year = 15; $year <= date('y'); $year++) {
|
|
||||||
if (is_dir(__DIR__.'/../src/Y'.$year)) {
|
|
||||||
for ($day = 1; $day < 26; $day++) {
|
|
||||||
$className = sprintf("trizz\\AdventOfCode\\Y%d\\Day%d", $year, $day);
|
|
||||||
if (class_exists($className)) {
|
|
||||||
$class = new $className();
|
|
||||||
$class->loadData();
|
|
||||||
$classes['Year \''.$year.' / Day '.$day] = [$class];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $classes;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user