Is string a math expression? - php

How can I found if string is a math expression or not?
It is enough to understand basic math expressions +, -, x, /
For Example:
"1+1" => TRUE
"2 / 2" => TRUE
"hello" => FALSE
"1 * 2 - X" => FALSE
"me + u" => FALSE

class MathExpression {
private static $parentheses_open = array('(', '{', '[');
private static $parentheses_close = array(')', '}', ']');
protected static function getParenthesesType( $c ) {
if(in_array($c,MathExpression::$parentheses_open)) {
return array_search($c, MathExpression::$parentheses_open);
} elseif(in_array($c,MathExpression::$parentheses_close)) {
return array_search($c, MathExpression::$parentheses_close);
} else {
return false;
}
}
public static function validate( $expression ) {
$size = strlen( $expression );
$tmp = array();
for ($i=0; $i<$size; $i++) {
if(in_array($expression[$i],MathExpression::$parentheses_open)) {
$tmp[] = $expression[$i];
} elseif(in_array($expression[$i],MathExpression::$parentheses_close)) {
if (count($tmp) == 0 ) {
return false;
}
if(MathExpression::getParenthesesType(array_pop($tmp))
!= MathExpression::getParenthesesType($expression[$i])) {
return false;
}
}
}
if (count($tmp) == 0 ) {
return true;
} else {
return false;
}
}
}
//Mathematical expressions to validate
$tests = array(
'(A1+A2*A3)+A5+(B3^B5)*(C1*((A3/C2)+(B2+C1)))',
'(A1+A2*A3)+A5)*C1+(B3^B5*(C1*((A3/C2)+(B2+C1)))',
'(A1+A2*A3)+A5++(B2+C1)))',
'(A1+A2*A3)+A5+(B3^B5)*(C1*(A3/C2)+(B2+C1))'
);
// running the tests...
foreach($tests as $test) {
$isValid = MathExpression::validate( $test );
echo 'test of: '. $test .'<br>';
var_dump($isValid);
}
you can check and read in detail about the solution here Is there possible to check mathematical expression string?
See also eval. For example, you can do this:
$result = INF;
try {
eval("$result=" + myMathExpression); // Evaluate here
} catch (Exception $e) {
}
if($result != INF) echo("Expression is a valid mathematical expression.");
read more about it there

An extremely simple solution:
Regex number,whitespace,[+,/,*,-,=],whitespace,Substring(recursion here)
will work for any sequence of
1 + 1 + 2 + ... + 1 = 2 + 3 + 4 = 1 * 4 ...
etc.
Obviously would not check if an expression is legit.
As per request, pseudo code:
if Regex(^(([0-9]+)(\s*)([+,/,*,-,=])(\s*)([0-9]+)(\s*)([+,/,*,-,=])(\s*)))
if (recursion())
return True;
else
return False;
else //checking for end point
if Regex(^(([0-9]+)(\s*)([+,/,*,-,=])(\s*)([0-9]+)))
return True;
else
return False;

Maybe a regex with a pattern like this :
^([-+/*]\d+(\.\d+)?)*

Related

preg_match - For sure there is a better way to search for these characters

So, I want to check the users-input, if it contains some of these characters:
" ' < >
I hope someone can show me a better way with less code
Thanks!
I used preg_match, but i just managed it with 4 nested if's.
/*Checks if the given value is valid*/
private function checkValidInput($input)
{
/*If there is no " */
if(preg_match('/"/', $input) == false)
{
/*If there is no ' */
if(preg_match("/'/", $input) == false)
{
/*If there is no <*/
if(preg_match("/</", $input) == false)
{
/*If there is no >*/
if(preg_match("/>/", $input) == false)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
You could create a regex class
preg_match('#["\'<>]#', $input);
Edit:
If you need to check for all characters then use strpos() with for loop
function checkInput($val) {
$contains = true;
$required = "<>a";
for($i = 0, $count = strlen($required); $i < $count ; ++$i) {
$contains = $contains && false !== strpos($val, $required[$i]);
}
return $contains;
}
var_dump(checkInput('abcd<>a')); // true
var_dump(checkInput('abcd>a')); // false, doesn't contain <

Using PHP write an anagram function?

Using PHP write an anagram function? It should be handling different phrases and return boolean result.
Usage:
$pharse1 = 'ball';
$pharse2 = 'lbal';
if(is_anagram($pharse1,$pharse2)){
echo $pharse1 .' & '. $pharse2 . ' are anagram';
}else{
echo $pharse1 .' & '. $pharse2 . ' not anagram';
}
There's simpler way
function is_anagram($a, $b) {
return(count_chars($a, 1) == count_chars($b, 1));
}
example:
$a = 'argentino';
$b = 'ignorante';
echo is_anagram($a,$b); // output: 1
$a = 'batman';
$b = 'barman';
echo is_anagram($a,$b); // output (empty):
function is_anagram($pharse1,$pharse2){
$status = false;
if($pharse1 && $pharse2){
$pharse1=strtolower(str_replace(" ","", $pharse1));
$pharse2=strtolower(str_replace(" ","", $pharse2));
$pharse1 = str_split($pharse1);
$pharse2 = str_split($pharse2);
sort($pharse1);
sort($pharse2);
if($pharse1 === $pharse2){
$status = true;
}
}
return $status;
}
function check_anagram($str1, $str2) {
if (count_chars($str1, 1) == count_chars($str2, 1)) {
return "This '" . $str1 . "', '" . $str2 . "' are Anagram";
}
else {
return "This two strings are not anagram";
}
}
ECHO check_anagram('education', 'ducatione');
I don't see any answers which have addressed the fact that capital letters are different characters than lowercase to count_chars()
if (isAnagram('Polo','pool')) {
print "Is anagram";
} else {
print "This is not an anagram";
}
function isAnagram($string1, $string2)
{
// quick check, eliminate obvious mismatches quickly
if (strlen($string1) != strlen($string2)) {
return false;
}
// Handle uppercase to lowercase comparisons
$array1 = count_chars(strtolower($string1));
$array2 = count_chars(strtolower($string2));
// Check if
if (!empty(array_diff_assoc($array2, $array1))) {
return false;
}
if (!empty(array_diff_assoc($array1, $array2))) {
return false;
}
return true;
}
here is my variant :
public function is_anagram($wrd_1, $wrd_2)
{
$wrd_1 = str_split ( strtolower ( utf8_encode($wrd_1) ) );
$wrd_2 = str_split( strtolower ( utf8_encode($wrd_2) ) );
if ( count($wrd_1)!= count($wrd_2) ) return false;
if ( count( array_diff ( $wrd_1 ,$wrd_2) ) > 0 ) return false;
return true;
}
Heheh little large but work as well :)
public static function areStringsAnagrams($a, $b)
{
//throw new Exception('Waiting to be implemented.');
$a = str_split($a);
$test = array();
$compare = array();
foreach ($a as $key) {
if (!in_array($key, $test)) {
array_push($test, $key);
$compare[$key] = 1;
} else {
$compare[$key] += 1;
}
}
foreach ($compare as $key => $value) {
if ($value !== substr_count($b, $key)) {
return false;
}
}
return true;
}

Own implementation of StringTokenizer returns unexcepted (endless) output

I am implementing my own StringTokenizer class in php, because the strtok function can only handle one opened tokenizer at the same time.
With
Hello;this;is;a;text
it works perfectly.
The output is:
**Hello**
**this**
**is**
**a**
**text**
But with
Hello;this;is;a;text;
it outputs:
**Hello**
**this**
**is**
**a**
**text**
****
****
<endless loop>
But I except the following output:
**Hello**
**this**
**is**
**a**
**text**
****
See my code below and please correct me:
class StringTokenizer
{
private $_str;
private $_chToken;
private $_iPosToken = 0;
private $_bInit;
public function __construct($str, $chToken)
{
if (empty($str) && empty($chToken))
{
throw new Exception('String and the token char variables cannot be empty.');
}
elseif(empty($chToken) && !empty($str))
{
throw new Exception('Missing parameter: Token char cannot be empty.');
}
elseif(!empty($chToken) && empty($str))
{
throw new Exception('Missing parameter: String cannot be empty.');
}
elseif(!empty($chToken) && !empty($str) && is_string($str) && strlen($chToken) >= 0)
{
$this->_str = $str;
$this->_chToken = $chToken;
$this->_bInit = true;
}
else
{
throw new Exception('TypeError: Illegal call to __construct from class StringTokenizer.');
}
}
public function next()
{
if ($this->_iPosToken === false)
{
return false;
}
if ($this->_bInit === true && (strlen($this->_str) - 1) > $this->_iPosToken)
{
$iCh1stPos = strpos($this->_str, $this->_chToken, $this->_iPosToken) + 1;
$this->_iPosToken = $iCh1stPos;
$this->_bInit = false;
return substr($this->_str, 0, $this->_iPosToken - 1);
}
elseif ($this->_bInit === false && (strlen($this->_str) - 1) > $this->_iPosToken)
{
$iCh1stPos = $this->_iPosToken;
$iCh2ndPos = strpos($this->_str, $this->_chToken, $this->_iPosToken);
if ($iCh2ndPos === false)
{
$this->_iPosToken = false;
return substr($this->_str, $iCh1stPos);
}
else
{
$this->_iPosToken = $iCh2ndPos + 1;
return substr($this->_str, $iCh1stPos, $iCh2ndPos - $iCh1stPos);
}
}
}
public function hasNext()
{
return strpos($this->_str, $this->chToken, $this->_iPosToken) === false ? false : true;
}
}
$strText = 'Hello;this;is;a;text';
$tokenizer = new StringTokenizer($strText, ';');
$tok = $tokenizer->Next();
while ($tok !== false)
{
echo '**' . $tok . '**' . PHP_EOL;
$tok = $tokenizer->next();
}
exit(0);
The problem with the third condition in the next() is this. String length is 26 and the last character match is 26 which you represent with the _iPosToken. so the condition in the 3rd if is false and the block never executes for the last semicolon.
A function in php returns NULL not FALSE by default.source
and the while never terminates at the bottom of the code.
So you have two options here. change the condition in the 3rd if to (strlen($this->_str)) >= $this->_iPosToken
OR
add a 4th condtion which returns false, as shown below.
public function next()
{
if ($this->_iPosToken === false)
{
return false;
}
if ($this->_bInit === true && (strlen($this->_str) - 1) > $this->_iPosToken)
{
$iCh1stPos = strpos($this->_str, $this->_chToken, $this->_iPosToken) + 1;
$this->_iPosToken = $iCh1stPos;
$this->_bInit = false;
return substr($this->_str, 0, $this->_iPosToken - 1);
}
elseif ($this->_bInit === false && (strlen($this->_str)-1 ) > $this->_iPosToken)
{
$iCh1stPos = $this->_iPosToken;
echo $this->_iPosToken;
$iCh2ndPos = strpos($this->_str, $this->_chToken, $this->_iPosToken);
if ($iCh2ndPos === FALSE) // You can chuck this if block. I put a echo here and //it never executed.
{
$this->_iPosToken = false;
return substr($this->_str, $iCh1stPos);
}
else
{
$this->_iPosToken = $iCh2ndPos + 1;
return substr($this->_str, $iCh1stPos, $iCh2ndPos - $iCh1stPos);
}
}
else return false;
}
Why do you like reinvent the wheel ?
You can use explode function, and then implements Iterator pattern in this tokenizer, i think it's an good approach.
http://php.net/explode
http://br1.php.net/Iterator
Example
<?php
class StringTokenizer implements Iterator
{
private $tokens = [];
private $position = 0;
public function __construct($string, $separator)
{
$this->tokens = explode($separator, $string);
}
public function rewind()
{
$this->position = 0;
}
public function current()
{
return $this->tokens[$this->position];
}
public function next()
{
++ $this->position;
}
public function key()
{
return $this->position;
}
public function valid()
{
return isset($this->tokens[$this->position]);
}
}
And using it:
$tokenizer = new StringTokenizer('h;e;l;l;o;', ';');
while($tokenizer->valid()) {
printf('**%s**', $tokenizer->current());
$tokenizer->next();
}

Check if all the substring are included in a string using PHP

let's say I have 2 set of string to check.
$string = 12345;
$string2 = 15000;
//string must contain 1,2,3,4,5 to be returned true
if(preg_match('[1-5]',$string) {
return true;
} else {
return false;}
This code works for $string but not for $string2. It returns true too with $string2.
Please help!
If string must contain 1, 2, 3, 4 and 5, then you should use regex pattern
/^(?=.*1)(?=.*2)(?=.*3)(?=.*4)(?=.*5).*/
which can be further optimize... for example:
/^(?=.*1)(?=.*2)(?=.*3)(?=.*4).*5/
If no other characters are allowed, then you should use regex pattern
/^(?=.*1)(?=.*2)(?=.*3)(?=.*4)(?=.*5)[1-5]*$/
You can check this with strpos as well:
<?php
function str_contains_all($string, $searchValues, $caseSensitive = false) {
if (!is_array($searchValues)) {
$searchValues = (string)$searchValues;
$searchValuesNew = array();
for ($i = 0; $i < strlen($searchValues); $i++) {
$searchValuesNew[] = $searchValues[$i];
}
$searchValues = $searchValuesNew;
}
$searchFunction = ($caseSensitive ? 'strpos' : 'stripos');
foreach ($searchValues as $searchValue) {
if ($searchFunction($string, (string)$searchValue) === false) {
return false;
}
}
return true;
}
?>
Use:
<?php
$string = 12345;
$string2 = 15000;
if (str_contains_all($string, 12345)) {
echo 'Y';
if (str_contains_all($string2, 12345)) {
echo 'Y';
} else {
echo 'N';
}
} else {
echo 'N';
}
?>
Which outputs:
YN
DEMO

Preg_match if a string beginns with "00"{number} or "+"{number}

I have to test if a string begins with 00 or with +.
pseudocode:
Say I have the string **0090** or **+41**
if the string begins with **0090** return true,
elseif string begins with **+90** replace the **+** with **00**
else return false
The last two digits can be from 0-9.
How do I do that in php?
You can try:
function check(&$input) { // takes the input by reference.
if(preg_match('#^00\d{2}#',$input)) { // input begins with "00"
return true;
} elseif(preg_match('#^\+\d{2}#',$input)) { // input begins with "+"
$input = preg_replace('#^\+#','00',$input); // replace + with 00.
return true;
}else {
return false;
}
}
if (substr($str, 0, 2) === '00')
{
return true;
}
elseif ($str[0] === '+')
{
$str = '00'.substr($str, 1);
return true;
}
else
{
return false;
}
The middle condition won't do anything though, unless $str is a reference.
if (substr($theString, 0, 4) === '0090') {
return true;
} else if (substr($theString, 0, 3) === '+90') {
$theString = '00' . substr($theString, 1);
return true;
} else
return false;

Categories