3v4l.org

run code in 300+ PHP versions simultaneously
<?php declare(strict_types=1); # THE RESULT HERE IS KINDA KOOL BUT I'M NOT SURE IF I MADE IT WORSE OR BETTER BY STUFFING AROUND WITHOUT A PLAN ! function most_frequent(array $list_to_search) { // print_r($list_to_search);#DEBUG if (count($list_to_search) === 0) return ['', 0]; $it = new ArrayIterator($list_to_search); $counter = 0; $num = $list_to_search[0]; foreach ($it as $i) { $curr_frequency = 0; foreach (new ArrayIterator($list_to_search) as $j) { if ($j === $i) { $curr_frequency++; } } if ($curr_frequency > $counter) { $counter = $curr_frequency; $num = $i; } } return [$num, $counter]; } interface ReToken extends Countable { public function is_empty(): bool; public function get_head(): string; public function has_head(): bool; public function get_tail(): string; public function has_tail(): bool; public function create_without_head(): ReToken; public function create_without_tail(): ReToken; } /** * A string split by [A-Z]+[] */ class ReSingleToken implements ReToken { private iterable $vals; public function __construct(string $val) { // echo 'ReSingleToken('.$val.')'.PHP_EOL;#DEBUG $regexV1 = '/([A-Z]*[a-z_0-9]*)(?=[A-Z]+)/'; $regexV2 = '~([A-Z]?[^A-Z]+|[A-Z]+(?=[A-Z][^A-Z]|$))~'; $words = preg_split($regexV2,$val,-1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE); // print_r($words);#DEBUG $this->vals = $words; // print_r(['"'.$val.'"', $words]);#DEBUG } public function __toString(): string { return implode('', $this->vals); } public function count(): int { return count($this->vals); } public function is_empty(): bool { return count($this) === 0; } public function get_head(): string { return count($this) > 0 ? $this->vals[0] : ''; } public function has_head(): bool { return true; } public function get_tail(): string { return count($this) > 0 ? $this->vals[array_key_last($this->vals)] : ''; } public function has_tail(): bool { return true; } public function create_without_head(): ReSingleToken { $vals = $this->vals; if ($this->has_head()) { array_shift($vals); } return new ReSingleToken(implode('', $vals)); } public function create_without_tail(): ReSingleToken { $vals = $this->vals; if ($this->has_tail()) { array_pop($vals); } return new ReSingleToken(implode('', $vals)); } } class ReGroup implements ReToken, RecursiveIterator { public function __construct( private iterable $tokens, private $commonBeginning, private $commonEnding, private bool $optional = false ) { // echo 'ReGroup(['.implode(',', $tokens).'], commonBeginning='.$commonBeginning.', commonEnding='.$commonEnding.', optional='.(string)$optional.')'.PHP_EOL;#DEBUG foreach ($tokens as $key => $value) { if ($value->is_empty()) { unset($this->tokens[$key]); $this->optional = true; } } } /** * Sets the tokens that are not empty string and makes the object optional * if any are empty. * * @param iterable $tokens The tokens that represent the alternation group. */ public function setTokens(iterable $tokens) { $this->tokens = []; $this->optional = false; foreach ($tokens as $token) { if ((string)$token === '') $this->optional = true; else $this->tokens[] = $token; } } public function tryToOptimize() { while (true) { // get all token heads $tokenHeads = []; foreach ($this->tokens as $token) { if ($token->has_head()) { $tokenHeads[] = $token->get_head(); } } list($head_most_popular, $head_count) = most_frequent($tokenHeads); // get all token tails $tokenTails = []; foreach ($this->tokens as $token) { if ($token->has_tail()) { $tokenTails[] = $token->get_tail(); } } list($tail_most_popular, $tail_count) = most_frequent($tokenTails); // all tokens have same head if ($head_count > 1 and $head_count === count($this->tokens)) { $tokenGroup = []; // $optional = false; foreach ($this->tokens as $token) { $token = $token->create_without_head(); $tokenGroup[] = $token; // if ((string)$token === '') // $optional = true; } // $this->tokens = [new ReGroup($tokenGroup, $head_most_popular, '', $optional)]; $this->setTokens($tokenGroup); $this->commonBeginning = $head_most_popular; $this->commonEnding = ''; // echo 'grouped by popular head: '.__LINE__.PHP_EOL;#DEBUG continue; } // all tokens have same tail if ($tail_count > 1 and $tail_count === count($this->tokens)) { $tokenGroup = []; // $optional = false; foreach ($this->tokens as $token) { $token = $token->create_without_tail(); $tokenGroup[] = $token; // if ((string)$token === '') // $optional = true; } // $this->tokens = [new ReGroup($tokenGroup, '', $tail_most_popular, $optional)]; $this->setTokens($tokenGroup); $this->commonBeginning = ''; $this->commonEnding = $tail_most_popular; // echo 'grouped by popular tail: '.__LINE__.PHP_EOL;#DEBUG continue; } if ($head_count >= $tail_count) { if ($head_count < 2) { // echo '//############################################################################//';#DEBUG // print_r(get_defined_vars());#DEBUG // echo 'no common groups: '.__LINE__.PHP_EOL;#DEBUG break; } $tokensNoHead = []; $tokensOther = []; $optional = false; foreach ($this->tokens as $token) { if ($token->get_head() === $head_most_popular) { $token = $token->create_without_head(); $tokensNoHead[] = $token; if ((string)$token === '') $optional = true; } else $tokensOther[] = $token; } $newGroup = new ReGroup($tokensNoHead, $head_most_popular, '', $optional); $this->tokens = [$newGroup, ...$tokensOther]; } else { if ($tail_count < 2) { // echo 'no common groups: '.__LINE__.PHP_EOL;#DEBUG break; } $tokensNoTail = []; $tokensOther = []; $optional = false; foreach ($this->tokens as $token) { if ($token->get_tail() === $tail_most_popular) { $token = $token->create_without_tail(); $tokensNoTail[] = $token; if ((string)$token === '') $optional = true; } else $tokensOther[] = $token; } $newGroup = new ReGroup($tokensNoTail, '', $tail_most_popular, $optional); $this->tokens = [$newGroup, ...$tokensOther]; } } // $tokens = []; // foreach ($this->tokens as $token) { // if ($token instanceof ReSingleToken and $token->get_head() === '') { // $tokens[] = $token; // } // } // if (count($tokens) > 0) { // #check if group has '' -> make optional // $this->optional = true; // $tokens = []; // foreach ($this->tokens as $token) { // if (!$token instanceof ReSingleToken or $token->get_head() !== '') { // $tokens[] = $token; // } // } // } foreach ($this->tokens as $group) { if ($group instanceof ReGroup) { $group->tryToOptimize(); } } } public function __toString(): string { $tokens = []; foreach ($this->tokens as $token) { $tokens[] = $token->__toString(); } $ret = $this->commonBeginning.'('.implode('|', $tokens).')'.($this->optional ? '?' : '').$this->commonEnding; // echo $ret.PHP_EOL;#DEBUG return $ret; } public function count(): int { return count($this->tokens); } public function is_empty(): bool { return count($this) === 0; } public function get_head(): string { return (string)$this->commonBeginning; } public function has_head(): bool { return (string)$this->commonBeginning != ''; } public function get_tail(): string { return (string)$this->commonEnding; } public function has_tail(): bool { return (string)$this->commonEnding != ''; } public function create_without_head(): ReGroup { return new ReGroup($this->tokens, '', $this->commonEnding, $this->optional); } public function create_without_tail(): ReGroup { return new ReGroup($this->tokens, $this->commonBeginning, '', $this->optional); } // ~~~>>> Iterator <<<~~~ //\ private int $position = 0; public function current(): mixed { return $this->tokens[$this->position]; } public function key(): mixed { return $this->position; } public function next(): void { $this->position++; } public function rewind(): void { $this->position = 0; } public function valid(): bool { return count($this) > $this->position; } // ~~~>>> RecursiveIterator <<<~~~ // public function getChildren(): ?RecursiveIterator { return $this->tokens; } public function hasChildren(): bool { return (bool)count($this); } } $for_test = [ '(A|B|C|D)', '(A|B|C|DA)', '(A|B|C|AD)', '(Example|ArrayIterator|RecursiveArrayIterator|DirectoryIterator|RecursiveDirectoryIterator)', '(Example|DOMNode|DOMText|DOMElement)' ]; $for_test[] = '('.implode( '|', array_filter( get_declared_classes(), function ($value) { return !(bool)strpos($value, '\\'); } ) ).')'; foreach ($for_test as $init) { // print_r(preg_split('/([A-Z]*[a-z_0-9]*)(?=[A-Z]+)/',substr($init, 1, -1),-1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE)); // continue; echo PHP_EOL.PHP_EOL.'----'.PHP_EOL.PHP_EOL; $inita = substr($init, 1, -1); $tokens = []; $strings = explode('|', $inita); foreach ($strings as $token) { $tokens[] = new ReSingleToken($token); } $r = new ReGroup($tokens, '', '', false); $r->tryToOptimize(); // print_r($r); echo $init.' => '.$r; foreach ($r as $token) { if ($token instanceof ReGroup) $token->tryToOptimize(); } echo PHP_EOL.PHP_EOL.$r.PHP_EOL.PHP_EOL; $tree = new RecursiveTreeIterator($r); foreach ($tree as $key => $value) { echo $value.PHP_EOL; } } /** RANDOM NOTES JUST KEEPING CAUSE I'M TOO TIRED TO GO THROUGH IT NOW * (Sngle|Sngle) * Group = Sngle(Sngle|Sngle)Sngle * * Token can have head/tail * * Sngle split into words: * - starting with upper case character * - all uppercase before a word ^ * head/tail = first/last word * * Group split into Sngle * head/tail = common head/tail * * for a group, * get all heads * if any match * group them with heads removed * rebuild tokens with group and remaining tokens * * Abcdef(Ghijk|Lmnop)?Vwxyz * ^pre ^attrib opt^^post * * prefixToken(tokens)suffixToken * * @todo 🟡 what if the common head and tail counts are equal? */

Abusive script

This script was stopped while abusing our resources

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
8.4.80.0040.01518.54
8.4.70.0140.01918.68
8.4.60.0080.01719.00
8.4.50.0110.02819.39
8.4.40.0000.02020.34
8.4.30.0130.02918.83
8.4.20.0100.02718.21
8.4.10.0100.02723.87
8.3.220.0040.01417.63
8.3.210.0080.03017.09
8.3.200.0070.01316.91
8.3.190.0110.03217.25
8.3.180.0090.01416.71
8.3.170.0070.03418.92
8.3.160.0090.00920.43
8.3.150.0040.01517.21
8.3.140.0030.01618.97
8.3.130.0070.02718.59
8.3.120.0070.03320.75
8.3.110.0070.02818.39
8.3.100.0100.02716.90
8.3.90.0030.01626.77
8.3.80.0030.02018.56
8.3.70.0100.02417.13
8.3.60.0030.03117.13
8.3.50.0030.03718.62
8.3.40.0100.02421.91
8.3.30.0100.02319.21
8.3.20.0070.01124.18
8.3.10.0090.00924.66
8.3.00.0070.01326.16
8.2.280.0120.03120.15
8.2.270.0060.03618.91
8.2.260.0090.01217.30
8.2.250.0040.01518.52
8.2.240.0000.01717.71
8.2.230.0120.02820.94
8.2.220.0070.01124.06
8.2.210.0110.02126.77
8.2.200.0060.01617.00
8.2.190.0130.03217.00
8.2.180.0170.03116.88
8.2.170.0130.02319.50
8.2.160.0140.02722.96
8.2.150.0080.00825.66
8.2.140.0070.01024.66
8.2.130.0030.01326.16
8.2.120.0070.01021.07
8.2.110.0040.01820.70
8.2.100.0070.01520.60
8.2.40.0100.02318.25
8.1.320.0100.02816.73
8.1.310.0060.02918.66
8.1.300.0100.01618.18
8.1.290.0060.01630.84
8.1.280.0100.03025.92
8.1.270.0030.01324.66
8.1.260.0070.01026.35
8.1.250.0030.01428.09
8.1.240.0030.01719.38
8.1.230.0100.01320.41

preferences:
31.96 ms | 403 KiB | 5 Q