-
-
Save dihjital/6c5a7c062cf65d7e761fd09d8318e545 to your computer and use it in GitHub Desktop.
On the margin of a problem solution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Ds\Set; | |
use stdClass; | |
class Zoli | |
{ | |
protected array $range; | |
protected const RANGE_MIN = 0; | |
protected const RANGE_MAX = 5; | |
protected const RANGE_STEP = 0.5; | |
protected $a, $b, $c, $d = null; | |
protected $crossOp, $cellOp; | |
public function __construct(protected Set $set = new Set) { | |
$this->range = range( | |
self::RANGE_MIN, | |
self::RANGE_MAX, | |
self::RANGE_STEP | |
); | |
$this->crossOp = ($this->add(...)); | |
$this->cellOp = ($this->multiply(...)); | |
} | |
protected function resetVariables(): void { | |
$this->a = | |
$this->b = | |
$this->c = | |
$this->d = null; | |
} | |
protected function extractGuess(array $guess): array { | |
return [ | |
$this->a ?? $guess[0], | |
$this->b ?? $guess[1], | |
$this->c ?? $guess[2], | |
$this->d ?? $guess[3], | |
]; | |
} | |
protected function multiply(...$numbers): int|float { | |
return array_reduce($numbers, | |
fn($accumulator, $number) => $accumulator * $number | |
, 1); | |
} | |
protected function subtract(...$numbers): int|float { | |
return array_reduce($numbers, | |
fn($accumulator, $number) => $accumulator - $number | |
, 0); | |
} | |
protected function add(...$numbers): int|float { | |
return array_reduce($numbers, | |
fn($accumulator, $number) => $accumulator + $number | |
, 0); | |
} | |
protected function getSymbols(array $pairs): stdClass { | |
return array_reduce($pairs, function($obj, $sub_array) { | |
foreach ($sub_array as $sub_obj) { | |
foreach ($sub_obj as $key => $value) { | |
if (!property_exists($obj, $key)) { | |
$obj->{$key} = $value; | |
} | |
} | |
} | |
return $obj; | |
}, new stdClass()); | |
} | |
protected function fixVariables(stdClass $symbols):void { | |
foreach($symbols as $symbol => $value) { | |
$this->{$symbol} = $value; | |
} | |
} | |
protected function eq(int $expectedResult, array $pairs): bool { | |
$result = ($this->crossOp)(...array_map(function($cell) { | |
return ($this->cellOp)(...array_map(fn($symbol) => array_values($symbol)[0], $cell)); | |
}, $pairs)); | |
if ($result == $expectedResult) { | |
$this->fixVariables($this->getSymbols($pairs)); | |
return true; | |
} | |
return false; | |
} | |
protected function createPair(array $symbols, array $values): array { | |
return array_map(function ($symbol, $value) { | |
return [$symbol => $value]; | |
}, $symbols, $values); | |
} | |
public function validateSolution(array $guess) { | |
list($a, $b, $c, $d) = $this->extractGuess($guess); | |
yield $this->eq(40, [ | |
$this->createPair(['a', 'a'], [$a, $a]), $this->createPair(['c', 'c'], [$c, $c]), | |
$this->createPair(['c', 'c'], [$c, $c]), $this->createPair(['a', 'a'], [$a, $a]) | |
]); | |
yield $this->eq(26, [ | |
$this->createPair(['a', 'a'], [$a, $a]), $this->createPair(['a', 'a'], [$a, $a]), | |
$this->createPair(['d', 'd'], [$d, $d]), $this->createPair(['d', 'd'], [$d, $d]) | |
]); | |
yield $this->eq(50, [ | |
$this->createPair(['c', 'c'], [$c, $c]), $this->createPair(['c', 'c'], [$c, $c]), | |
$this->createPair(['d', 'd'], [$d, $d]), $this->createPair(['d', 'd'], [$d, $d]) | |
]); | |
yield $this->eq(14, [ | |
$this->createPair(['a', 'a'], [$a, $a]), $this->createPair(['b', 'c'], [$b, $c]), | |
$this->createPair(['a', 'a'], [$a, $a]), $this->createPair(['a', 'b'], [$a, $b]) | |
]); | |
yield $this->eq(24, [ | |
$this->createPair(['b', 'c'], [$b, $c]), $this->createPair(['d', 'b'], [$d, $b]), | |
$this->createPair(['c', 'c'], [$c, $c]), $this->createPair(['b', 'b'], [$b, $b]) | |
]); | |
yield $this->eq(31, [ | |
$this->createPair(['c', 'c'], [$c, $c]), $this->createPair(['d', 'b'], [$d, $b]), | |
$this->createPair(['a', 'a'], [$a, $a]), $this->createPair(['c', 'a'], [$c, $a]) | |
]); | |
yield $this->eq(26, [ | |
$this->createPair(['a', 'a'], [$a, $a]), $this->createPair(['b', 'b'], [$b, $b]), | |
$this->createPair(['d', 'd'], [$d, $d]), $this->createPair(['c', 'd'], [$c, $d]) | |
]); | |
yield $this->eq(31, [ | |
$this->createPair(['a', 'b'], [$a, $b]), $this->createPair(['c', 'a'], [$c, $a]), | |
$this->createPair(['d', 'd'], [$d, $d]), $this->createPair(['c', 'd'], [$c, $d]) | |
]); | |
} | |
public function getRandomElement() { | |
return $this->range[array_rand($this->range)]; | |
} | |
public function generateElements(): array { | |
return array_map(fn() => $this->getRandomElement(), range(1, 4)); | |
} | |
public function checkIfGuessExists($guess): bool { | |
return $this->set->contains($guess); | |
} | |
public function generateGuess(): array { | |
$guess = $this->generateElements(); | |
while ($this->checkIfGuessExists($guess) || count(array_unique($guess)) !== 4) | |
$guess = $this->generateElements(); | |
return $guess; | |
} | |
public function evaluateSolution(array $guess): bool { | |
return array_reduce([...$this->validateSolution($guess)], | |
fn ($validGuess, $eq) => $validGuess && $eq | |
, true); | |
} | |
public function printSolution(array $solution): void { | |
echo sprintf("We have found a solution: a = %.1f, b = %.1f, c = %.1f, d = %.1f", ...$solution); | |
} | |
public function runSequence(int $length = 5000): bool { | |
$this->set->clear(); | |
for ($j = 0; $j < $length; $j++) { | |
$guess = $this->generateGuess(); | |
if ($this->evaluateSolution($guess)) { | |
$this->printSolution($this->extractGuess($guess)); | |
return true; | |
} else { | |
$this->set->add($guess); | |
} | |
} | |
sleep(15); | |
$this->resetVariables(); | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment