3v4l.org

run code in 200+ php & hhvm versions
Bugs & Features
<?php define('STOP_CHAR', '.'); /* * GRAMMAR * arrows = simple | simple ('=' | '<=' | '=>' | '<=>') simple * simple = negation | negation ('+' | '*' | '#' | '$' | '^') negation * negation = ('-' | ) paren * paren = '(' simple ')' | variable * variable = '0' | '1' | 'a' | 'b' | ... | 'z' | 'A' | ... | 'Z' */ function read_variable(&$eq, &$vars) { $varname = $eq{0}; if ($varname != '0' && $varname != '1' && !ctype_alpha($eq{0})) return NULL; $eq = substr($eq, 1); if ($varname == '0') return false; if ($varname == '1') return true; if (isset($vars[$varname])) return $vars[$varname]; return $varname . '?'; } function read_paren(&$eq, &$vars) { if ($eq{0} == '(') { $ch = $eq{0}; $eq = substr($eq, 1); $val = read_arrows($eq, $vars); if (is_bool($val)) // Valid result { if ($eq{0} != ')') return NULL; $eq = substr($eq, 1); } return $val; } return read_variable($eq, $vars); } function read_negation(&$eq, &$vars) { $negate = ($eq{0} == '-'); if ($negate) $eq = substr($eq, 1); $val = read_paren($eq, $vars); if ($negate && is_bool($val)) return !$val; return $val; } function read_simple(&$eq, &$vars) { $val1 = read_negation($eq, $vars); $op = $eq{0}; if (!is_bool($val1) || ( $op != '*' && $op != '+' && $op != '$' && $op != '#' && $op != '^')) return $val1; $eq = substr($eq, 1); $val2 = read_simple($eq, $vars); if (!is_bool($val2)) return $val2; switch ($op) { case '*': return $val1 && $val2; case '+': return $val1 || $val2; case '#': return !($val1 || $val2); case '$': return !($val1 && $val2); case '^': return $val1 xor $val2; } } function read_arrows(&$eq, &$vars) { $val1 = read_simple($eq, $vars); $op = $eq{0}; if (!is_bool($val1) || ( $op != '=' && $op != '<' )) return $val1; $eq = substr($eq, 1); while ($eq{0} == '=' || $eq{0} == '>') { $op .= $eq{0}; $eq = substr($eq, 1); } if ($op != '=' && $op != '<=' && $op != '=>' && $op != '<=>') return 'Invalid operator "' . $op . '".'; $val2 = read_simple($eq, $vars); if (!is_bool($val2)) return $val2; switch ($op) { case '=': case '<=>': return $val1 == $val2; case '=>': return (!$val1) || $val2; case '<=': return (!$val2) || $val1; } return 'Internal error.'; } function calculate(&$eq, &$vars) { $eq .= STOP_CHAR; $val = read_arrows($eq, $vars); if (is_bool($val)) { if ($eq{0} != STOP_CHAR) return NULL; } return $val; } function print_table($columns, $unknowns, $latex) { $rowcount = pow(2, count($unknowns)); if ($rowcount <= 0) return; if ($latex) { print("<pre>\\begin{displaymath}\n\\begin{array}{"); for ($i = count($columns); $i; $i--) print('|c'); print("}\n "); } else print('<table cellspacing="0"><tr>'); $repl_search = array('-', '+', '*', '<=>', '=>', '<=', ':'); $repl_replace = $latex ? array('\lnot{}', '\lor{}', '\land{}', '\Leftrightarrow{}', '\Rightarrow{}', '\Leftarrow{}', ': ') : array('&not;', '&or;', '&and;', '&#8660;', '&#8658;', '&#8656;', ': '); $true_count = array(); $false_count = array(); $error_count = array(); $first_col = true; foreach ($columns as $eq) { if ($latex) { if ($first_col) $first_col = false; else print("\n &amp; "); } else print('<th>'); print(str_replace($repl_search, $repl_replace, $eq)); $true_count[] = 0; $false_count[] = 0; $error_count[] = 0; if (!$latex) print('</th>'); } if ($latex) print(" \\\\\n\\hline\n"); else print('</tr>'); for ($bits = 0; $bits < $rowcount; $bits++) { if (!$latex) print('<tr>'); $vars = array(); $x = $bits; for ($i = count($unknowns)-1; $i >= 0; $i--) { $vars[$unknowns[$i]] = (bool) ($x & 0x01); $x >>= 1; } $first_col = true; foreach ($columns as $col_index => $str) { if (strlen($str) > 2 && ctype_alpha($str{0}) && $str{1} == ':') { $assign_to_var = $str{0}; $str = substr($str, 2); } else $assign_to_var = ''; $val = calculate($str, $vars); if ($latex) { if ($first_col) $first_col = false; else print(' &amp; '); } else { print('<td nowrap="nowrap"'); if (($bits & 0x03) == 0x03) print(' class="btmline"'); print('>'); } if (is_bool($val)) { print($val ? '1' : '0'); if ($val) $true_count[$col_index]++; else $false_count[$col_index]++; } else { if (is_null($val)) $val = 'Error at: ' . $str; if ($latex) print(htmlspecialchars('\mathrm{' . str_replace(' ', '\ ', $val) . '}')); else print(htmlspecialchars($val)); $error_count[$col_index]++; } if (!$latex) print('</td>'); if ($assign_to_var) $vars[$assign_to_var] = is_bool($val) ? $val : NULL; } if ($latex) { print(" \\\\\n"); if (($bits & 0x03) == 0x03) print("\\hline\n"); } if (!$latex) print('</tr>'); } if ($latex) print("\\end{array}\n\\end{displaymath}\n"); else print('</table>'); foreach ($columns as $col_index => $eq) { if ($true_count[$col_index] == $rowcount) $str = 'Given the equations above, %s is always true.'; else if ($false_count[$col_index] == $rowcount) $str = 'Given the equations above, %s is always false.'; else if ($error_count[$col_index]) $str = 'Could not evaluate %s. Check the syntax and variable names.'; else continue; if ($latex) printf("\n$str\n", '$' . str_replace($repl_search, $repl_replace, $eq) . '$'); else printf("<p>$str</p>\n", str_replace($repl_search, $repl_replace, $eq)); } if ($latex) print('</pre>'); } function handle_input($input, $latex) { $unknowns = array(); $columns = array(); $str = preg_replace('{//.*?$}m', "", $input); preg_match_all('{[]\-^$#[><=/|&+*()01A-Za-z:]+}', $str, $matches, PREG_SET_ORDER); foreach ($matches as $eq) { $eq = $eq[0]; $columns[] = $eq; if (strlen($eq) == 1) $unknowns[] = $eq; } if (count($columns) == 0) print('<p>No equations or unknowns specified.</p>'); else if (count($unknowns) == 0) print('<p>No unknowns specified.</p>'); else print_table($columns, $unknowns, $latex); }
Output for 5.4.0 - 7.2.0