Basically I'm trying to achieve this:
// generating a random number
$randomid = rand(261, 270);
//if range is between numbers, assign strings
$verticalaa = if ($randomid >= 261 && $randomid <= 265);
$verticalbb = if ($randomid >= 266 && $randomid <= 270);
//echo the range string name
echo 'random range is in' . $verticalaa . '' . $verticalbb . '';
In the end I want to echo the name of matching range.
If the number is, let's say, 262, it would echo verticalaa.
I hope it's possible to understand what I'm after.
My head is like a balloon now after hours of coding.
Need help.
Probably an easier way to this would be ternary and assign 1 variable.
$randomid = rand(261, 270);
$var = in_array($randomid, range(261, 265)) ? 'between 261 and 265' : 'between 266 and 270';
echo $var;
For readability purpose for long lists you can use switch operator in this way:
switch (true)
{
case $a > 100: $result = 'aaa'; break;
case $a > 90: $result = 'bbb'; break;
case $a > 80: $result = 'ccc'; break;
// ...
case $a > 0: $result = 'zzz'; break;
}
At the same time, your question looks like a classic XY problem and what you ask is not what you need.
Related
I know the following code will remove the numbers are the point.
round($number);
I want to round the numbers as follows
if number is 20.123
I want result 20,
If number is 20.567
I want result 21
Means if value is below .5 , it should remove that value.
If value if .5 or above it should round up.
How ?
Anyone help ?
round($number) will do what you want:
round(20.156); // 20
round(20.651); // 21
Live example
I am sure it's working well.
<?php
$var = 22.443;
$var = number_format($var, 0, '.', '');
echo $var;
?>
function get_decimal_num($number){
$num = explode('.', $number);
return $num[1];
}
$num = 10.5 ; // for example
$val = get_decimal_num($num);
if($val >= 5)
{
$value = (int) $num;
echo $value = $value + 1;
}
if($val < 5)
{
echo $num;
}
Plese check it...
Try this:
use the ceil, floor, explode and substr function to achieve you value.
$num = "20.123";
$arr = explode(".", $num);
if(substr($arr[1], 0, 1) >= 5){
$num = ceil($num);
}else{
$num = floor($num);
}
echo $num;
Result:
20
Also you can use the round function.
round(20.156); // 20
round(20.651); // 21
I want to check value with in range or not suppose if I have range D1 to D40 and if I enter D20 then it returns value with in range.
I check several solution but this are for only integer not for both string and integer.
EDIT
Range will be dynamic like AA20 to AA30 or like AC10D to AC30D
You can write something simpler like this...
$arr = range(1,40); //<--- Creating a range of 1 to 40 elements..
array_walk($arr,function (&$v){ $v = 'D'.$v;}); //<--- Concatenating D to all the elements..
echo in_array('D20',$arr) ? 'Found' : 'Not Found'; //<-- The search part.
Demonstration
First, you should remove the letter D from your string variable, like this:
// This is your first variable:
$rang1="D5";
// This is your second rang variable:
$rang2="D20";
$rang1=str_replace("D","",$rang1);
$rang2=str_replace("D","",$rang2);
$rang=$rang2-$rang1;
echo $rang;
Or if your variable looks like this:
$rang="D5 TO D20";
you can use the following:
$rang="D5 TO D20";
$rang=explode(" TO ",$rang);
$rang1=rang[0];
$rang2=rang[1];
$rang1=str_replace("D","",$rang1);
$rang2=str_replace("D","",$rang2);
$rang=$rang2-$rang1;
echo $rang;
// 1. build up array of valid entries
$prefix = "D";
$rangeArray = array();
for($i = 1; $i <= 40; $i++) {
$rangeArray[] = $prefix . $i;
}
...
// 2. check against that array:
$inRange = in_array($needle, $rangeArray); // boolean
To get the position in the range:
$pos = array_search($needle, $rangeArray); // integer or false if not found
Where $needle would be your input value.
The following code will work with ranges with different letter in the beginning like A10 to B30 (assuming A20 is in that range, but A40 is not):
$min = "A10";
$max = "B30";
$test = "A20";
$min_ascii = chr($min[0]);
$max_ascii = chr($max[0]);
$test_ascii = chr($max[0]);
$min_number = substr($min, 1);
$max_number = substr($max, 1);
$test_number = substr($test, 1);
if ($min_ascii <= $test_ascii and $test_ascii <= $max_ascii
and $min_number <= $test_number and $test_number <= $max_number)
{
echo "$test is in the range from $min to $max";
}
I am writing simple drop formula for player A vs. B fights - level difference determinates drop rate. My issue here is that instead of 0: > 10 ||| 1 vs. 1 = 10% it gives 0: > 10 ||| 1 vs. 1 = 0% - why?
PhpFiddle: http://www.phpfiddle.org/main/code/n1q-dw7
<?php
# lets simulate high level player A attacks low level player B
for ($A = 1; $A <= 100; $A++) {
$B = 1;
calculateMoneyDrop($A,$B);
}
# lets simulate low level player A attacks high level player B
for ($B = 1; $B <= 100; $B++) {
$A = 1;
calculateMoneyDrop($A,$B);
}
function calculateMoneyDrop($A,$B) {
$X = $A - $B;
echo '<strong>', $X, '</strong>: ';
switch ($X) {
case $X > 10:
echo "> 10 ||| ";
$X = 10;
break;
case $X < -90:
echo "< -90 ||| ";
$X = -90;
break;
}
$dropRate = 10 - $X;
echo $A, ' vs. ', $B, ' = ', $dropRate, '%<br>';
}
It's simply how switch-case works. It checks whether $X equals to the value you list in case. Since that value is a boolean (result of a comparison is a boolean!), and PHP has a crazy way to compare different types (in this case int and bool), that block of case will actually be executed.
Use if statements, or use min and max.
If you change your switch to
switch (true) {
the original code runs correctly.
Perhaps someone with better php than me can explain why!
http://www.phpfiddle.org/main/code/6pg-nwc
Well, in your $X > 10 case you set $X = 10 and later calculate $dropRate as 10 - $X, which is 10 - 10, which is 0.
Either the $dropRate should be $X if the desired outcome is 10. It also strikes me funny that the output says $X == 0 first, but then enters the switch case $X > 10... Are you sure that you're showing us all the code?
Also I don't think it's good practice to use the switch case like that. This is a typical candidate for an if block.
Your switch block does the same as:
if(($X > 10)==$X){
echo "> 10 ||| ";
$X = 10;
}
else if(($X < -90)==$X){
echo "< -90 ||| ";
$X = -90;
}
It compares whatever you have at "case" to whatever you have in the switches parentheses.
Switch is used only for "equals" comparisons.
so, to make it work, use:
if($X > 10){
echo "> 10 ||| ";
$X = 10;
}
else if($X < -90){
echo "< -90 ||| ";
$X = -90;
}
Sorry if the title is confusing.
I have several string expressions in an array like these:
var1 <= 6 && var1 > 3
var1 > 2
var1 > 4.5
var2 < 22.5
var2 >= 14.25
var2 < 16
How can I go about evaluating all of the expressions to determine:
var1 min
var1 max
var2 min
var2 max
I understand that with the expressions that are not "or equal to" I won't be able to get an exact value. That is alright.
You're trying to do simple linear programming. SimplexInPHP implements linear programming in PHP, which you could use. See it in action here.
The other option is to implement a solution yourself. Use split() to split each inequality into tokens. For each variable, compute the min/max by starting off with the range [-inf, inf] and update it for each inequality. If the operator begins with < then update max to max(cur_max, value); otherwise update min to min(cur_min, value).
You'll also have to keep track of whether the end-points are inclusive or exclusive. This can be done with booleans is_min_inclusive and is_max_inclusive. A new end-point is inclusive if the operator ends in =, otherwise it's to exclusive. Be sure to handle the case where you have x < 1 and x <= 1 (in both orders), which should result in x < 1.
<?php
$string = "var1 <= 6 && var1 > 0 && var2 >= 4 && var2 < 200";
//creates an array with the key 'name' and 'min OR 'max'
function parseExpression($expression){
$parts = preg_split("|( )+|", $expression,3,PREG_SPLIT_NO_EMPTY);
$result = array('name'=>$parts[0]);
switch ($parts[1]){
case '<':
$parts[2]-=1;
//NO BREAK <x same as <=(x-1)
case '<=':
$result['max'] = $parts[2];
break;
case '>':
$parts[2]+=1;
//NO BREAK >x same as >=(x+1)
case '>=':
$result['min'] = $parts[2];
break;
default:
throw new Exception("format not supported");
}
return $result;
}
$expressions = explode("&&", $string);
$vars = array();
foreach ($expressions as $expression){
$parsed = parseExpression($expression);
$name = array_shift($parsed);
foreach ($parsed as $key => $value){
if (array_key_exists($key,$vars[$name])){
switch ($key){
case 'min':
$vars[$name][$key] = min($vars[$name][$key],$value);
break;
case 'max':
$vars[$name][$key] = max($vars[$name][$key],$value);
break;
default:
}
throw new Exception("format not supported");
}
else{
$vars[$name][$key] = $value;
}
}
}
var_dump($vars);
?>
<?php
$arr = array("var1 <= 6",
"var1 > 2",
"var1 > 4.5",
"var2 < 22.5",
"var2 >= 14.25",
"var2 < 16");
function find_min_max($arr, $variable) {
$min = '-inf';
$max = 'inf';
while (list($i, $v) = each($arr)) {
list($var, $rel, $value) = preg_split('/\s+/', $v);
if ($var != $variable) continue;
if ($rel == "<" || $rel == "<=") {
if ($value < $max)
$max = $value;
}
else if ($rel == ">" || $rel == ">=") {
if ($value > $min)
$min = $value;
}
}
return array($min, $max);
}
list($min, $max) = find_min_max($arr, "var1");
echo "var1 $min - $max \n";
list($min, $max) = find_min_max($arr, "var2");
echo "var3 $min - $max \n";
?>
So in your example, you'd expect the minimum var1 to be >4.5 and the max to be <=6? Have you considered changing your data structure?
If, for example, your data structure looked something like this:
$limits=array('lte'=>array(6), 'lt'=>array(),'gte'=>array(),'gt'=>(2,4.5);
then parsing becomes trivial. The max of the gt and gte arrays would be the minimum value, with > or >= depending on which array it came from. The minimum of lt and lte arrays would be the max value.
I guess...
http://php.net/manual/en/function.max.php
http://php.net/manual/en/function.min.php
In the example they show nummeric string expressions (so not only casted floats or ints)
There's a blog post comment on codinghorror.com by Paul Jungwirth which includes a little programming task:
You have the numbers 123456789, in that order. Between each number, you must insert either nothing, a plus sign, or a multiplication sign, so that the resulting expression equals 2001. Write a program that prints all solutions. (There are two.)
Bored, I thought, I'd have a go, but I'll be damned if I can get a result for 2001. I think the code below is sound and I reckon that there are zero solutions that result in 2001. According to my code, there are two solutions for 2002. Am I right or am I wrong?
/**
* Take the numbers 123456789 and form expressions by inserting one of ''
* (empty string), '+' or '*' between each number.
* Find (2) solutions such that the expression evaluates to the number 2001
*/
$input = array(1,2,3,4,5,6,7,8,9);
// an array of strings representing 8 digit, base 3 numbers
$ops = array();
$numOps = sizeof($input)-1; // always 8
$mask = str_repeat('0', $numOps); // mask of 8 zeros for padding
// generate the ops array
$limit = pow(3, $numOps) -1;
for ($i = 0; $i <= $limit; $i++) {
$s = (string) $i;
$s = base_convert($s, 10, 3);
$ops[] = substr($mask, 0, $numOps - strlen($s)) . $s;
}
// for each element in the ops array, generate an expression by inserting
// '', '*' or '+' between the numbers in $input. e.g. element 11111111 will
// result in 1+2+3+4+5+6+7+8+9
$limit = sizeof($ops);
$stringResult = null;
$numericResult = null;
for ($i = 0; $i < $limit; $i++) {
$l = $numOps;
$stringResult = '';
$numericResult = 0;
for ($j = 0; $j <= $l; $j++) {
$stringResult .= (string) $input[$j];
switch (substr($ops[$i], $j, 1)) {
case '0':
break;
case '1':
$stringResult .= '+';
break;
case '2':
$stringResult .= '*';
break;
default :
}
}
// evaluate the expression
// split the expression into smaller ones to be added together
$temp = explode('+', $stringResult);
$additionElems = array();
foreach ($temp as $subExpressions)
{
// split each of those into ones to be multiplied together
$multplicationElems = explode('*', $subExpressions);
$working = 1;
foreach ($multplicationElems as $operand) {
$working *= $operand;
}
$additionElems[] = $working;
}
$numericResult = 0;
foreach($additionElems as $operand)
{
$numericResult += $operand;
}
if ($numericResult == 2001) {
echo "{$stringResult}\n";
}
}
Further down the same page you linked to.... =)
"Paul Jungwirth wrote:
You have the numbers 123456789, in
that order. Between each number, you
must insert either nothing, a plus
sign, or a multiplication sign, so
that the resulting expression equals
2001. Write a program that prints all solutions. (There are two.)
I think you meant 2002, not 2001. :)
(Just correcting for anyone else like
me who obsessively tries to solve
little "practice" problems like this
one, and then hit Google when their
result doesn't match the stated
answer. ;) Damn, some of those Perl
examples are ugly.)"
The number is 2002.
Recursive solution takes eleven lines of JavaScript (excluding string expression evaluation, which is a standard JavaScript function, however it would probably take another ten or so lines of code to roll your own for this specific scenario):
function combine (digit,exp) {
if (digit > 9) {
if (eval(exp) == 2002) alert(exp+'=2002');
return;
}
combine(digit+1,exp+'+'+digit);
combine(digit+1,exp+'*'+digit);
combine(digit+1,exp+digit);
return;
}
combine(2,'1');