I have to write the function to check validation of input number from browser:
-> is numeric
-> has 6 letters
-> in form: odd+even+odd+even,... the 1st character can be odd or even.
For example: 123456 => true; 234567 => true
I wrote:
function check_code($code){
if (!is_numeric($code)) return false;
if (strlen($code)<>6) return false;
$c = str_split($code);
if (($c[0]+$c[1])%2==1 && ($c[1]+$c[2])%2==1 && ($c[2]+$c[3])%2==1 && ($c[3]+$c[4])%2==1 && ($c[4]+$c[5])%2==1) return true;
return false;
}
Is there any other solution "shorter and smarter" than above code? Thank you
You could consider rewriting the logic using the modulus operator into a for loop:
function check_code($code)
{
if (!is_numeric($code)) return false;
if (strlen($code)<>6) return false;
$c = str_split($code);
for ($i = 0; $i < count($c); $i++) {
if (isset($c[$i + 1])) {
if (($c[$i] + $c[$i + 1]) % 2 !== 1) {
return false;
}
}
}
return true;
}
Related
I had a job interview test and the question I got was about making a function which would return the number of ways a number could be generated by using numbers from a certain set and any number in the set can be used N times.
It is like if I have the number 10 and I want to find out how many ways 10 can be generated using [2,3,5]
2+2+2+2+2 = 10
5+3+2 = 10
2+2+3+3 = 10
5+5 = 10
to solve it I made this function:
function getNumberOfWays($money, $coins) {
static $level = 0;
if (!$level) {
sort($coins);
}
if ($level && !$money) {
return 1;
} elseif (!$level && !$money) {
return 0;
}
if ($money === 1 && array_search(1, $coins) !== false) {
return 1;
} elseif ($money === 1 && array_search(1, $coins) === false) {
return 0;
}
$r = 0;
$tmpCoins = $coins;
foreach ($coins as $index => $coin) {
if (!$coin || $coin > $money) {
continue;
}
$tmpCoins[$index] = 0;
$tmpMoney = $money;
do {
$tmpMoney -= $coin;
if ($tmpMoney >= 0) {
$level++;
$r += getNumberOfWays($tmpMoney, $tmpCoins);
$level--;
} elseif (!$tmpMoney) {
$r++;
}
} while ($tmpMoney >= 0);
}
return $r;
}
This function works ok and returns the right value.
My question is if there is a better way for it.
Thanks
I have one issue that I can't solve. So I have for loop.
So here is little code:
for ($i=0;$i<3;$i++) {
$int = $i + 1;
if($sms->mobio_check($servID,$request->input("code$int"))) {
continue;
$cart->success($product->id,$product->server->name);
} else {
return redirect()->to(route('mcCheckoutFailed'))->withErrors(['codeError'=>__('messages.invalidCode',['input'=>$int])]);
}
}
I want if three ifs return true to run function $sms->success();.
What is wrong here?
You could rely on the fact that if the loop finished, then it's OK, any failures will cause the return in the loop to exit...
for ($i=0;$i<3;$i++) {
$int = $i + 1;
if( ! $sms->mobio_check($servID,$request->input("code$int"))) {
return redirect()->to(route('mcCheckoutFailed'))->withErrors(['codeError'=>__('messages.invalidCode',['input'=>$int])]);
}
}
$cart->success($product->id,$product->server->name);
You can do it like this:
$success = true;
for ($i=0;$i<3;$i++) {
$int = $i + 1;
if($success = $success || $sms->mobio_check($servID,$request->input("code$int"))) {
continue;
$cart->success($product->id,$product->server->name);
} else {
return redirect()->to(route('mcCheckoutFailed'))->withErrors(['codeError'=>__('messages.invalidCode',['input'=>$int])]);
}
}
if ($success) $sms->success();
you can try this
$count = 0;
for ($i=0;$i<3;$i++) {
$int = $i + 1;
if($sms->mobio_check($servID,$request->input("code$int"))) {
$count++;
} else {
return redirect()->to(route('mcCheckoutFailed'))->withErrors(['codeError'=>__('messages.invalidCode',['input'=>$int])]);
}
}
if($count == 3)
$cart->success($product->id,$product->server->name);
Make a function has_twenty_ones that returns true if at least one of the players in the game has 21, otherwise return false. This function should use the twenty_ones function.
function has_twenty_ones($game){
function twenty_ones($game)
{
$players_with_score_21 = [];
foreach ($game['players'] as $name => $player) {
$distance = 21 - $player['score'];
if ($distance < 0) {
continue;
}
if ($distance == 21) {
$players_with_score_21 = [$name];
}
}
return $players_with_score_21;
}
return isset($players_with_score_21);
}
what's the best way to code it
Just check if return of twenty_ones function is empty, if it return false overthose return twenty_ones value.
function has_twenty_ones($game){
function twenty_ones($game){
$players_with_score_21 = [];
foreach ($game['players'] as $name => $player) {
$distance = 21 - $player['score'];
if ($distance < 0) {
continue;
}
if ($distance == 21) {
$players_with_score_21 = [$name];
}
}
return $players_with_score_21;
}
$playersWithScore = twenty_ones($game);
if (!empty($playersWithScore)) {
return $playersWithScore;
} else {
return false;
}
}
I'm not sure why you need two functions for this.
As was mentioned by #RiggsFolly, you're not actually making a call to twenty_ones() function. Why not have the following code:
function has_twenty_ones($game)
{
foreach($game['players'] as $name => $player)
{
$distance = 21 - $player['score'];
if ($distance < 0) {
continue;
}
// If at least one player has 21, return true.
if($distance == 21) {
return true;
}
}
return false;
}
The above will return true when it encounters a player who has a score of 21, otherwise it'll return false.
function twenty_ones($game)
{
$players_with_score_21 = [];
foreach ($game['players'] as $name => $player) {
$distance = 21 - $player['score'];
if ($distance < 0) {
continue;
}
if ($distance == 21) {
$players_with_score_21 = [$name];
}
}
return $players_with_score_21;
}
function has_twenty_ones($game){
if (count ($this->twenty_ones($game)) > 0 )
return true;
else
return false;
}
I have this PHP code which is supposed to increase a URL shortener mask on each new entry.
My problem is that it dosen't append a new char when it hits the last one (z).
(I know incrementing is a safety issue since you can guess earlier entries, but this is not a problem in this instance)
If i add 00, it can figure out 01 and so on... but is there a simple fix to why it won't do it on its own?
(The param is the last entry)
<?php
class shortener
{
public function ShortURL($str = null)
{
if (!is_null($str))
{
for($i = (strlen($str) - 1);$i >= 0;$i--)
{
if($str[$i] != 'Z')
{
$str[$i] = $this->_increase($str[$i]);
#var_dump($str[$i]);
break;
}
else
{
$str[$i] = '0';
if($i == 0)
{
$str = '0'.$str;
}
}
}
return $str;
}
else {
return '0';
}
}
private function _increase($letter)
{
//Lowercase: 97 - 122
//Uppercase: 65 - 90
// 0 - 9 : 48 - 57
$ord = ord($letter);
if($ord == 122)
{
$ord = 65;
}
elseif ($ord == 57)
{
$ord = 97;
}
else
{
$ord++;
}
return chr($ord);
}
}
?>
Effectively, all you are doing is encoding a number into Base62. So if we take the string, decode it into base 10, increment it, and reencode it into Base62, it will be much easier to know what we are doing, and the length of the string will take care of itself.
class shortener
{
public function ShortURL($str = null)
{
if ($str==null) return 0;
$int_val = $this->toBase10($str);
$int_val++;
return $this->toBase62($int_val);
}
public function toBase62($num, $b=62) {
$base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$r = $num % $b ;
$res = $base[$r];
$q = floor($num/$b);
while ($q) {
$r = $q % $b;
$q =floor($q/$b);
$res = $base[$r].$res;
}
return $res;
}
function toBase10( $num, $b=62) {
$base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$limit = strlen($num);
$res=strpos($base,$num[0]);
for($i=1;$i<$limit;$i++) {
$res = $b * $res + strpos($base,$num[$i]);
}
return $res;
}
}
I have a form in which users can enter floating point values. I post these values to a php script and i compare if the numbers the users entered are between some values. If i post an integer the comparison returns true no matter if the number exceeded the boundaries. If i entere a floating point number the comparison fails no matter if the number is within the boundaries. I am not stupid, i've done floating point comparisons in c++ and i know how to do an if( float1 >= float2) return false...
here is my code:
//loading the helper
$val = Loader::helper('synerciel_form','synerciel_client');
//adding the fields to the inputs array for validation
$val->between('isolation_des_murs_peripheriques', 2.8, null, t($between.'Isolation des murs
pèriphèriques'), true, false);
//helper class
class SynercielFormHelper extends ValidationFormHelper {
const VALID_BETWEEN = 7;
const VALID_FLOAT = 7;
private $min;
private $max;
private $includeLow;
private $includeHigh;
public function between($field, $min, $max, $errorMsg, $includeLow = true, $includeHigh = true) {
$const = SynercielFormHelper::VALID_BETWEEN;
$this->min = $min;
$this->max = $max;
$this->includeLow = $includeLow;
$this->includeHigh = $includeHigh;
$this->addRequired($field, $errorMsg, $const);
}
...
public function test() {
$between = new ValidationNumbersBetweenHelper();
if (!$between->between($this->data[$field], $this->min, $this->max, $this->includeLow, $this->includeHigh)) {
$this->fieldsInvalid[] = $f;
}
}
My validation method (i believe here is the tricky part)
class ValidationNumbersBetweenHelper {
public function between($data, $min = null, $max = null, $includeLow = true, $includeHigh = true) {
if ($min && $includeLow) {
if (!($data >= $min))
return false;
} else if ($min) {
if (!($data > $min))
return false;
}
if ($max && $includeHigh) {
if (!($data <= $max))
return false;
} else if ($max) {
if (!($data < $max))
return false;
}
return true;
}
}
Check the warning message http://php.net/manual/en/language.operators.comparison.php
You can use BC Math Functions http://php.net/manual/en/function.bccomp.php
$status = bccomp($left, $right);
if ($status == 0) {
echo 'equal';
} else if ($status > 0) {
echo 'left bigger than right';
} else {
echo 'right bigger than left';
}
Hope this helps
Try isolating the troublesome code. Put your validation function into a stand-alone PHP file and test it there. Try checking $max and $min for !== null as 0 is also false. You could reverse the logic and remove all the !s. (e.g. change >= to <) so instead of "not greater than or equal to" you can have "less than"