This question already has answers here:
palindrome condition checking using function arguments [closed]
(5 answers)
Closed 9 years ago.
I can not understand these steps.
function Palindrome($str) {
if ((strlen($str) == 1) || (strlen($str) == 0)) {
echo " THIS IS PALINDROME";
}
else {
if (substr($str,0,1) == substr($str,(strlen($str) - 1),1)) {
return Palindrome(substr($str,1,strlen($str) -2));
}
else { echo " THIS IS NOT A PALINDROME"; }
}
}
Palindrome("456");
if ((strlen($str) == 1) || (strlen($str) == 0)) {
echo " THIS IS PALINDROME";
}
If strlen($str) <= 1 this is obviously a palindrome.
else {
if (substr($str,0,1) == substr($str,(strlen($str) - 1),1)) {
return Palindrome(substr($str,1,strlen($str) -2));
}
If strlen($str) > 1 and if first and last characters of the string are similar, call the same Palindrome function on the inner string (that is the string without its first and last characters).
else { echo " THIS IS NOT A PALINDROME"; }
}
If first and last characters are not equals, this is not a palindrome.
The principle is to test only the outer characters, and to call the same function again and again on smaller parts of the string, until it has tested every pair of characters that have to be equal if we're dealing with a palindrome.
This is called recursion.
This image illustrates what happens better than my poor english can:
image source
Palindrome("456") gets $str == "456". So, looking at branches:
if ((strlen($str) == 1) || (strlen($str) == 0)) -> false
if (substr($str,0,1) == substr($str,(strlen($str) - 1),1)) is the same as if ("4" == "6")), which is false, so we go to the last branch, outputting that "456" is not a palindrome.
Let's see what would happen for Palindrome("454") gets $str == "456". So, looking at branches:
if ((strlen($str) == 1) || (strlen($str) == 0)) -> false
if (substr($str,0,1) == substr($str,(strlen($str) - 1),1)) is the same as if ("4" == "4")), which is true, so we call Palindrome(substr($str,1,strlen($str) -2)), which is the same as `Palindrome("5")
Now, inside that function call, we get new variable $str == "5". Performing the same steps, our first if is true, so we echo that it is a palindrome.
For a recursion, it is crucial to remember that each function call has it's own local variables. In other words, when you call Palindrome(...) and inside that function call Palindrome(...) is called again, there are two $str variables in memory, one belonging to the first (outer) call and one to the second (inner) call. Of course, each sees only its own, but once you exit the inner call, you have unchanged $str in the outer call. That's why we had $str == "454" in the first call and $str == "5" in the second. These are named the same, but are two variables existing in the memory (until you exit the second (inner) call of Palindrome()).
It's recursive...
So it checks the outer and innrer characters. If they match, it continues to the next most outer/inner character, i.e.
NURSESRUN
Will check:
Is the first and last char equal? (N=N?)
Yes. are the second and second from last equal? (U=U?) - by calling itself again. This is recursion.
If it runs into non equal chars it quits and returns 'NOT A PALINDROME'
If it runs out of checks (zero length string for even number of chars, string length 1 for odd numbers) it reaches the 'terminating condition' (no more recursion) and returns 'THIS IS A PALINDROME'
Related
I'm trying on PHP 7.4
<?php
function test(){
do{
$val=(int)readline("Insert a number in the range of 1-5 :");
print_r(($val>5 || $val!==0)."\n");
}while ($val>5 || $val!==0);
}
test();
But it just doesn't work as expected. It just leaves the loop when I insert 0, but not when I insert a number less than or equal to 5.
This condition is incorrect for what you're trying to do.
while ($val>5 || $val!==0)
None of the numbers you want to cause the loop to end are equal to zero, so the $val!==0 part of the condition will always be true unless $val is zero.
If either part of an or expression like $val>5 || $val!==0 is true, then the entire expression is true.
You need this instead:
while ($val > 5 || $val < 1)
This question already has answers here:
Test if number is odd or even
(20 answers)
Closed 7 years ago.
How can I get if a number is even or odd or neither (have decimal, like 1.5) with PHP? I know that there are operators like *, /, but they did not work.
Here's a try (of course it did not) (work that's just to find if it's a even number):
function even($n) {
return (($n/2)*2 == $n);
}
echo even(1); // true (should be false)
echo even(2); // true
How about
function even($n) {
if (!is_int($n)) {return 'n';}
return !($n % 2);
}
even(1); // false;
even(2); // true;
even(1.5); // 'n'
The danger here is that 'n' will evaluate as false if used as a boolean. It might be better to return some specific constants instead of true or false. The OP didn't specify what the return values should be.
It is pretty simple. modulo (%) is the operator you want, it determines if there would be a remainder if x is divided by y... for example (3 % 2 = 1) and (4 % 2 = 0).
This has been asked before too - pretty common question - you really just need to see if your number, $n % 2 is equal to 0.
php test if number is odd or even
Check if given number is integer first. And bitwise & to check if it is even or odd. Here is an example...
if (is_int($n)) {
if ($n & 1) {
echo 'Odd!';
} else {
echo 'Even!';
}
} else {
echo "Not a Integer!";
}
Hope this is helpful.
Use the modulo operator (%) to determine whether the integer is divisible by 2. You also need abs() to handle negative numbers, and is_int() to handle the fact that the modulo operator doesn't correctly handle floating point numbers. An example implementation follows:
function is_even($num) {
return is_int($num) && abs($num % 2) == 0;
}
function is_odd($num) {
return is_int($num) && abs($num % 2) == 1;
}
// this last one seems self-explanatory, but if you want it, here it is
function is_neither_even_nor_odd($num) {
return !is_even($num) && !is_odd($num);
}
// Tests: The following should all output true:
var_dump(
is_even(0),
is_even(2),
is_even(-6),
is_even(51238238),
is_odd(1),
is_odd(-1),
is_odd(57),
is_neither_even_nor_odd(1.5),
is_neither_even_nor_odd(2.5),
is_neither_even_nor_odd(-0.5),
is_neither_even_nor_odd(0.00000001)
);
Here's a demo.
is_numeric returns true if the given variable is a number
is_int returns true if the given variable is an integer
The modulor operator % can be used to determine if an integer is even or odd:
$num % 2 == 0 // returns true if even, false if odd
I'm trying to normalize user input for Canadian postal codes.
The end goal is to get all input as A3A 3A3 - 7 characters, capitalized, with the first group letter number letter, second group as number letter number.
Users will sometimes use o or O for the number 0, or vice versa, so here is my function:
$zip = htmlspecialchars($_REQUEST['zip']);
if (!empty($zip)) {
//if the format is A3A3A3, split it into two groups
if (strlen($zip) == 6) {
$zip = substr($zip, 0, 3) . " " . substr($zip, 3, 3);
}
//now lets make sure there is only a empty space between groups
if (strlen($zip) == 7) {
$zip[3] = " ";
}
//let's put their o's, O's and 0's in the right places
if ($zip[1] == ("O" || "o")) {
$zip[1] = '0';
}
if ($zip[4] == ('O'||'o')) {
$zip[4] = '0';
}
if ($zip[6] == ('O'||'o')) {
$zip[6] = '0';
}
if ($zip[0] == '0') {
$zip[0] = 'O';
}
if ($zip[2] == '0') {
$zip[2] = 'O';
}
if ($zip[5] == '0') {
$zip[5] = 'O';
}
//uppercase all the letters
strtoupper($zip);
}
The first tests I ran were of the sort:
input[0o0 O0o] => output[O0O 0O0]
Everything looks good I said to myself, it's working! But then I tried a normal postal code and keep getting unexpected results:
input[S7K3K1] => output[S0K 0K0]
I can't figure out why the code is deciding that ($zip[1] == ('O' || 'o') is true when $zip[1] == 7.
Any input would be greatly appreciated. Also, if you see a better way of normalizing this input, please share!
//let's put their o's, O's and 0's in the right places
if ($zip[1] == ("O" || "o")) {
$zip[1] = '0';
}
This code does not do what you think – your comparison logic are wrong, because so is your understanding of the || operator.
Use console.log(("O" || "o")) and see what you get in console – ooops, that’s just the letter O. Why? Because the || logical or operator in JS returns the first value that is not false-y.
You need to either write two individual comparisons here, and or-conjoin those – $zip[1] == "O" || $zip[1] == "o", or use an array with possible values and then check whether your variable value is among those (but the latter would be a bit over the top here).
Edit: Or, as bigmandan pointed out, you could also transform your letter to upper- or lower-case first, then you only have to do one comparison: ($zip[1]).toLowerCase() == "o" (Of course this works only in a special case like this – if it was not O or o, but a or b instead, you would still have to do individual comparisons.)
I'm using this function to check if binary is correct, I know it looks sloppy.. I'm not sure how to write the function that well.. but it doesn't seem to work!
If binary = 10001000 it says malformed, even though it's not.. what is wrong in my function?..
function checkbinary($bin) {
$binary = $bin;
if(!strlen($binary) % 8 == 0){
return 1;
}
if (strlen($binary) > 100) {
return 1;
}
if (!preg_match('#^[01]+$#', $binary)){ //Tried without !
return 1;
}
if (!is_numeric($binary)) {
return 1;
}
}
if (checkbinary("10001000") != 1) {
echo "Correct";
} else {
echo "Binary incorrect";
}
Why does this function always say 10001000 is incorrect?
if(!strlen($binary) % 8 == 0){ should be
if( strlen($binary) % 8 !== 0 ){
edit and btw: Since you're already using preg_match() you can simplify/shorten the function to
function checkbinary($binary) {
return 1===preg_match('#^(?:[01]{8}){0,12}$#', $binary);
}
This allows 0 - 12 groups of 8 0/1 characters which includes all the tests you currently have in your function:
strlen()%8 is covered by {8} in the inner group
strlen() > 100 is covered by {0,12} since any string longer than 8*12=96 characters would trigger either the first if or the >100 test
0/1 test is obvious
is_numeric is kinda superfluous
edit2: The name checkbinary might not be a perfect choice for the function. I wouldn't necessarily expect it to check for 8bit/byte alignment and strlen()<=100.
function checkbinary($bin) {
return preg_match('#^[01]+$#', $bin);
}
Some tests: http://www.ideone.com/3D9SQetX and http://www.ideone.com/1HCCtxVV.
I'm not entirely sure what you're attempting to achieve, but you might be able to get there via the following...
if($binaryString == base_convert($binaryString, 2, 2))...
In essence, this is comparing the results of a conversion from binary to binary - hence if the resultant output is identical, the input must be a valid binary string.
This question already has answers here:
startsWith() and endsWith() functions in PHP
(34 answers)
Closed 8 years ago.
Example: I have a $variable = "_foo", and I want to make absolutely sure that $variable does not start with an underscore "_". How can I do that in PHP? Is there some access to the char array behind the string?
$variable[0] != "_"
How does it work?
In PHP you can get particular character of a string with array index notation. $variable[0] is the first character of a string (if $variable is a string).
You might check out the substr function in php and grab the first character that way:
http://php.net/manual/en/function.substr.php
if (substr('_abcdef', 0, 1) === '_') { ... }
Since someone mentioned efficiency, I've benchmarked the functions given so far out of curiosity:
function startsWith1($str, $char) {
return strpos($str, $char) === 0;
}
function startsWith2($str, $char) {
return stripos($str, $char) === 0;
}
function startsWith3($str, $char) {
return substr($str, 0, 1) === $char;
}
function startsWith4($str, $char){
return $str[0] === $char;
}
function startsWith5($str, $char){
return (bool) preg_match('/^' . $char . '/', $str);
}
function startsWith6($str, $char) {
if (is_null($encoding)) $encoding = mb_internal_encoding();
return mb_substr($str, 0, mb_strlen($char, $encoding), $encoding) === $char;
}
Here are the results on my average DualCore machine with 100.000 runs each
// Testing '_string'
startsWith1 took 0.385906934738
startsWith2 took 0.457293987274
startsWith3 took 0.412894964218
startsWith4 took 0.366240024567 <-- fastest
startsWith5 took 0.642996072769
startsWith6 took 1.39859509468
// Tested "string"
startsWith1 took 0.384965896606
startsWith2 took 0.445554971695
startsWith3 took 0.42377281189
startsWith4 took 0.373164176941 <-- fastest
startsWith5 took 0.630424022675
startsWith6 took 1.40699005127
// Tested 1000 char random string [a-z0-9]
startsWith1 took 0.430691003799
startsWith2 took 4.447286129
startsWith3 took 0.413349866867
startsWith4 took 0.368592977524 <-- fastest
startsWith5 took 0.627470016479
startsWith6 took 1.40957403183
// Tested 1000 char random string [a-z0-9] with '_' prefix
startsWith1 took 0.384054899216
startsWith2 took 4.41522812843
startsWith3 took 0.408898115158
startsWith4 took 0.363884925842 <-- fastest
startsWith5 took 0.638479948044
startsWith6 took 1.41304707527
As you can see, treating the haystack as array to find out the char at the first position is always the fastest solution. It is also always performing at equal speed, regardless of string length. Using strpos is faster than substr for short strings but slower for long strings, when the string does not start with the prefix. The difference is irrelevant though. stripos is incredibly slow with long strings. preg_match performs mostly the same regardless of string length, but is only mediocre in speed. The mb_substr solution performs worst, while probably being more reliable though.
Given that these numbers are for 100.000 runs, it should be obvious that we are talking about 0.0000x seconds per call. Picking one over the other for efficiency is a worthless micro-optimization, unless your app is doing startsWith checking for a living.
This is the most simple answer where you are not concerned about performance:
if (strpos($string, '_') === 0) {
# code
}
If strpos returns 0 it means that what you were looking for begins at character 0, the start of the string.
It is documented thoroughly here: http://uk3.php.net/manual/en/function.strpos.php
(PS $string[0] === '_' is the best answer)
function starts_with($s, $prefix){
// returns a bool
return strpos($s, $prefix) === 0;
}
starts_with($variable, "_");
Here’s a better starts with function:
function mb_startsWith($str, $prefix, $encoding=null) {
if (is_null($encoding)) $encoding = mb_internal_encoding();
return mb_substr($str, 0, mb_strlen($prefix, $encoding), $encoding) === $prefix;
}
To build on pinusnegra's answer, and in response to Gumbo's comment on that answer:
function has_leading_underscore($string) {
return $string[0] === '_';
}
Running on PHP 5.3.0, the following works and returns the expected value, even without checking if the string is at least 1 character in length:
echo has_leading_underscore('_somestring').', ';
echo has_leading_underscore('somestring').', ';
echo has_leading_underscore('').', ';
echo has_leading_underscore(null).', ';
echo has_leading_underscore(false).', ';
echo has_leading_underscore(0).', ';
echo has_leading_underscore(array('_foo', 'bar'));
/*
* output: true, false, false, false, false, false, false
*/
I don't know how other versions of PHP will react, but if they all work, then this method is probably more efficient than the substr route.