Make abstract day command

This commit is contained in:
Tristan 2023-12-03 14:34:22 +01:00
parent 5ef6984e88
commit 68f6ee867a
Signed by: trizz
SSH Key Fingerprint: SHA256:Xsd2dTN+ZC3OZWfvuKIDMQ/1lWicuINSEPgRQw/CJT8
5 changed files with 90 additions and 34 deletions

4
aoc
View File

@ -4,8 +4,8 @@ require __DIR__.'/vendor/autoload.php';
use NunoMaduro\Collision\Provider as CollisionProvider; use NunoMaduro\Collision\Provider as CollisionProvider;
use Symfony\Component\Console\Application; use Symfony\Component\Console\Application;
use trizz\AdventOfCode\ExecuteDay; use trizz\AdventOfCode\Commands\ExecuteDay;
use trizz\AdventOfCode\Puzzle; use trizz\AdventOfCode\Commands\Puzzle;
(new CollisionProvider())->register(); (new CollisionProvider())->register();

View File

@ -1,28 +1,33 @@
<?php <?php
namespace trizz\AdventOfCode; namespace trizz\AdventOfCode\Commands;
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\Solution;
final class ExecuteDay extends Command abstract class AbstractDayCommand extends Command
{ {
private int $day; protected int $day;
private int $year; protected int $year;
private string $title; protected string $title;
protected bool $skipExamples;
protected int $part;
#[\Override] #[\Override]
protected function configure(): void protected function configure(): void
{ {
$this $this
->setName('day')
->setDescription('Run day')
->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'))
->addOption('one', '1', null, 'Run only part 1')
->addOption('two', '2', null, 'Run only part 2')
->addOption('skip-example', 's', null, 'Skip the example data'); ->addOption('skip-example', 's', null, 'Skip the example data');
} }
@ -33,44 +38,51 @@ final class ExecuteDay extends Command
$this->year = $input->getArgument('year'); $this->year = $input->getArgument('year');
$this->title = sprintf("Advent of Code '%d - Day %d", $this->year, $this->day); $this->title = sprintf("Advent of Code '%d - Day %d", $this->year, $this->day);
$this->skipExamples = $input->getOption('skip-example');
$this->part = $input->getOption('one') ? 1 : ($input->getOption('two') ? 2 : 0);
$output->writeln(''); $output->writeln('');
$output->writeln($this->title); $output->writeln($this->title);
$output->writeln(str_repeat('-', strlen($this->title))); $output->writeln(str_repeat('-', strlen($this->title)));
} }
#[\Override] /**
protected function execute(InputInterface $input, OutputInterface $output): int * @return array<string, int|string>
*/
protected function getSolutions(): array
{ {
$className = sprintf('%s\\Y%d\\Day%d', __NAMESPACE__, $this->year, $this->day); $solution = $this->loadClass();
/** @var Solution $class */
$class = new $className();
$class->loadData();
// Solve the examples if available. // Solve the examples if available.
$resultPart1Example = 'n/a'; $resultPart1Example = 'n/a';
$resultPart2Example = 'n/a'; $resultPart2Example = 'n/a';
if ($class->hasExampleData() && !$input->getOption('skip-example')) { if (!$this->skipExamples && $solution->hasExampleData()) {
['part1' => $resultPart1Example, 'part2' => $resultPart2Example] = $class->results(useExampleData: true); ['part1' => $resultPart1Example, 'part2' => $resultPart2Example] = $solution->results(useExampleData: true, part: $this->part);
} }
// Solve the real puzzle if available. // Solve the real puzzle if available.
$resultPart1 = 'n/a'; $resultPart1 = 'n/a';
$resultPart2 = 'n/a'; $resultPart2 = 'n/a';
if ($class->hasData()) { if ($solution->hasData()) {
['part1' => $resultPart1, 'part2' => $resultPart2] = $class->results(useExampleData: false); ['part1' => $resultPart1, 'part2' => $resultPart2] = $solution->results(useExampleData: false, part: $this->part);
} }
// Output all the results. return [
$output->writeln('<fg=bright-green>Part 1</>'); 'part1' => $resultPart1,
$output->writeln(sprintf('<fg=blue>Example:</> <comment>%s</comment>', $resultPart1Example)); 'part2' => $resultPart2,
$output->writeln(sprintf('<fg=blue>Result: </> <comment>%s</comment>', $resultPart1)); 'part1Example' => $resultPart1Example,
$output->writeln(str_repeat('-', strlen($this->title))); 'part2Example' => $resultPart2Example,
$output->writeln('<fg=bright-green>Part 2</>'); ];
$output->writeln(sprintf('<fg=blue>Example:</> <comment>%s</comment>', $resultPart2Example)); }
$output->writeln(sprintf('<fg=blue>Result: </> <comment>%s</comment>', $resultPart2));
return Command::SUCCESS; protected function loadClass(): Solution
{
$className = sprintf('%s\\Y%d\\Day%d', substr(__NAMESPACE__, 0, -9), $this->year, $this->day);
/** @var Solution $class */
$class = new $className();
$class->loadData();
return $class;
} }
} }

View File

@ -0,0 +1,44 @@
<?php
namespace trizz\AdventOfCode\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
final class ExecuteDay extends AbstractDayCommand
{
#[\Override]
protected function configure(): void
{
parent::configure();
$this
->setName('day')
->setDescription('Run day');
}
#[\Override]
protected function execute(InputInterface $input, OutputInterface $output): int
{
$results = $this->getSolutions();
// Output all the results.
if (in_array($this->part, [0, 1], true)) {
$output->writeln('<fg=bright-green>Part 1</>');
$output->writeln(sprintf(' <fg=blue>Example:</> <comment>%s</comment>', $results['part1Example']));
$output->writeln(sprintf(' <fg=blue>Result: </> <comment>%s</comment>', $results['part1']));
}
if ($this->part === 0) {
$output->writeln(str_repeat('-', strlen($this->title)));
}
if (in_array($this->part, [0, 2], true)) {
$output->writeln('<fg=bright-green>Part 2</>');
$output->writeln(sprintf(' <fg=blue>Example:</> <comment>%s</comment>', $results['part2Example']));
$output->writeln(sprintf(' <fg=blue>Result: </> <comment>%s</comment>', $results['part2']));
}
return Command::SUCCESS;
}
}

View File

@ -1,6 +1,6 @@
<?php <?php
namespace trizz\AdventOfCode; namespace trizz\AdventOfCode\Commands;
use PhpPkg\CliMarkdown\CliMarkdown; use PhpPkg\CliMarkdown\CliMarkdown;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
@ -25,7 +25,7 @@ final class Puzzle extends Command
{ {
$contents = file_get_contents( $contents = file_get_contents(
sprintf( sprintf(
'%s/../data/Y%d/day%s/puzzle.md', '%s/../../data/Y%d/day%s/puzzle.md',
__DIR__, __DIR__,
$input->getArgument('year'), $input->getArgument('year'),
(int) $input->getArgument('day') (int) $input->getArgument('day')

View File

@ -110,11 +110,11 @@ abstract class Solution
* @return array{part1: int|string, part2: int|string} * @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, int $part = 0): array
{ {
return [ return [
'part1' => $this->part1Data($useExampleData), 'part1' => ($part === 1 || $part === 0) ? $this->part1Data($useExampleData) : 'n/a',
'part2' => $this->part2Data($useExampleData), 'part2' => ($part === 2 || $part === 0) ? $this->part2Data($useExampleData) : 'n/a',
]; ];
} }