Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
97.62% |
41 / 42 |
|
80.00% |
4 / 5 |
CRAP | |
0.00% |
0 / 1 |
Expression | |
97.62% |
41 / 42 |
|
80.00% |
4 / 5 |
18 | |
0.00% |
0 / 1 |
eval | |
94.44% |
17 / 18 |
|
0.00% |
0 / 1 |
6.01 | |||
cleanExpression | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
matchExpressionPattern | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
expression | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
5 | |||
postfixNotationStack | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
5 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Projom\Util\Math; |
6 | |
7 | class Expression |
8 | { |
9 | const OPERATORS = ['+', '-', '*', '/']; |
10 | const PATTERN = '/\d+|\+|\*|-|\/|\(|\)/'; |
11 | |
12 | public static function eval(string $expression): ?int |
13 | { |
14 | if (!$expression = static::cleanExpression($expression)) |
15 | return null; |
16 | |
17 | if (!$list = static::matchExpressionPattern($expression)) |
18 | return null; |
19 | |
20 | $stack = []; |
21 | $postfixNotationStack = static::postfixNotationStack($list); |
22 | foreach ($postfixNotationStack as $item) { |
23 | |
24 | switch (is_numeric($item)) { |
25 | |
26 | case true: |
27 | $stack[] = $item; |
28 | break; |
29 | |
30 | case false: |
31 | $operand_1 = array_shift($stack); |
32 | $operator = $item; |
33 | $operand_2 = array_shift($stack); |
34 | |
35 | $result = static::expression($operand_1, $operator, $operand_2); |
36 | |
37 | $stack[] = $result; |
38 | break; |
39 | } |
40 | } |
41 | |
42 | return array_shift($stack); |
43 | } |
44 | |
45 | public static function cleanExpression(string $expression): string |
46 | { |
47 | $expression = trim($expression); |
48 | $expression = str_replace(' ', '', $expression); |
49 | return $expression; |
50 | } |
51 | |
52 | public static function matchExpressionPattern(string $expression): array |
53 | { |
54 | preg_match_all(static::PATTERN, $expression, $matches); |
55 | $list = $matches[0] ?? []; |
56 | return $list; |
57 | } |
58 | |
59 | public static function expression(string|int|float $operand_1, string|int|float $operator, string|int|float $operand_2): string|int|float |
60 | { |
61 | return match ($operator) { |
62 | '+' => $operand_1 + $operand_2, |
63 | '-' => $operand_1 - $operand_2, |
64 | '*' => $operand_1 * $operand_2, |
65 | '/' => $operand_1 / $operand_2, |
66 | }; |
67 | } |
68 | |
69 | public static function postfixNotationStack(array $list): array |
70 | { |
71 | $stack = []; |
72 | $operator = ''; |
73 | foreach ($list as $item) { |
74 | |
75 | if (is_numeric($item)) { |
76 | |
77 | $stack[] = $item; |
78 | if ($operator !== '') { |
79 | $stack[] = $operator; |
80 | $operator = ''; |
81 | } |
82 | |
83 | continue; |
84 | } |
85 | |
86 | if (in_array($item, static::OPERATORS)) |
87 | $operator = $item; |
88 | } |
89 | |
90 | return $stack; |
91 | } |
92 | } |