The user can only enter a number between 1 and 5 - if they enter 0, leave the field blank or enter a number greater than 5 it will be default reset to 5. 1,2,3,4 are accepted otherwise.
$max=mysql_real_escape_string($_POST["max"]);
if ($max=="0" || $max==""){
$max_r="5";
} elseif ($max > "5"){
$max_r="5";
} else {
$max_r=$max;
}
However it always spits out 5.
Well, you're comparing strings and not integers. Try $max = (int) $_POST['max'] and don't wrap the values in quotes. Then, you can always escape $max before writing it to the DB.
$max = (int) $_POST['max'];
if ( ! $max || $max > 5){
$max_r = 5;
} else {
$max_r = $max;
}
Or, you could go one-liner FTW:
$max_r = ( ! $max || $max > 5) ? 5 : $max;
$max = intval($_POST['max']);
if($max < 0 || $max > 5){
$max = 5;
}
Related
I try to recreate what we see when we printing page on office or adobe.
For example, when you want to print page 1 to 5 you write : 1-5 and if you want to print a page outside you write : 1-5,8
At the moment I explode string by ',' :
1-5 / 8
Then explode each result by '-' and if I've got result I loop from first page to last and create variable with comma :
1,2,3,4,5,8
Finally I explode by ',' and use array unique to erase double value.
It take some times to achieve this especially when there's a lot of '-'.
Maybe someone got a easier solution to so this ?
Thank
Edit :
$pages = "1-4,6-8,14,16,18-20";
$pages_explode = explode(',',$pages);
foreach($pages_explode as $page){
$page_explode = explode('-',$page);
if(!empty($page_explode[1])){
for ($i=$page_explode[0]; $i<=$page_explode[1] ; $i++) {
$page_final .= $i.',';
}
}else{
$page_final .= $page_explode[0].',';
}
}
$page_final = explode(',',$page_final);
$page_final = array_unique ($page_final);
foreach($page_final as $value){
echo $value.'<br>';
}
Is it a code golf challenge?
Well a basic approach seems fine to me :
$input = '1-5,6-12,8';
$patterns = explode(',', $input);
$pages = [];
foreach ($patterns as $pattern) {
if (2 == count($range = explode('-', $pattern))) {
$pages = array_merge($pages, range($range[0], $range[1]));
} else {
$pages[] = (int)$pattern;
}
}
$uniquePages = array_unique($pages);
var_dump($uniquePages);
Outputs :
array (size=12)
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5
5 => int 6
6 => int 7
7 => int 8
8 => int 9
9 => int 10
10 => int 11
11 => int 12
Having to remove duplicates suggests that you have overlapping ranges in your strings.
Eg: 1-5,2-9,7-15,8,10
You seems to process all these without considering the overlapping areas and finally attempt to remove duplicates by the expensive array_unique function.
Your code should instead remember the minimum and maximum of the resulting range and not process anything that overlaps this range.
Following is a sample code which demonstrates the idea. But its certainly faster than the code you have suggested in your question. You should add parts there to process additional types of delimiters, if any, in your requirement.
<?php
$ranges = "1-5,3-7,6-10,8,11";
$min = 10000;
$max = -1;
$numbers = array(); //Your numbers go here
//Just a utility function to generate numbers from any range and update margins
function generateNumbers($minVal, $maxVal) {
global $min, $max, $numbers;
for ($i = $minVal; $i <= $maxVal; $i++) {
array_push($numbers, $i);
if ($i < $min)
$min = $i;
if ($i > $max)
$max = $i;
}
}
//Seperate ranges
$sets = explode(",", $ranges);
//Go through each range
foreach($sets as $aSet) {
//Extract the range or get individual numbers
$range = explode("-", $aSet);
if (count($range) == 1) { //its an individual number. So check margins and insert
$aSet = intval($aSet);
if ($aSet < $min){
array_push($numbers, $aSet);
$min = $aSet;
}
if ($aSet > $max){
array_push($numbers, $aSet);
$max = $aSet;
}
continue; // <----- For single numbers it ends here
}
//Its a range
$rangeLow = intval($range[0]);
$rangeHigh = intval($range[1]);
//Adjusting numbers to omit cases when ranges fall right on the margins
if ($rangeLow == $min){
$rangeLow++;
}
else
if ($rangeLow == $max) {
$rangeLow--;
}
if ($rangeHigh == $min){
$rangeHigh++;
}
else
if ($rangeHigh == $max) {
$rangeHigh--;
}
//Check if below or above the generated range
if (($rangeLow < $min && $rangeHigh < $min) || ($rangeLow > $max && $rangeHigh > $max)) {
generateNumbers($rangeLow, $rangeHigh);
};
//Check if across the lower edge of the generated range
if ($rangeLow < $min && $rangeHigh > $min && $rangeHigh < $max) {
generateNumbers($rangeLow, $min - 1);
};
//Check if across the upper edge of the generated range
if ($rangeLow > $min && $rangeLow < $max && $rangeHigh > $max) {
generateNumbers($max + 1, $rangeHigh);
};
}
//Now just sort the array
print_r($numbers);
?>
I'm trying to find the number of units between 2 numbers that are under zero between 0 and a limit and over that limit. Here is my function. It works fine until I have to work with some huge numbers which takes a lot of time to process. I am trying to find a way to execute this code without using a loop.
public function getBetween($num1, $num2) {
$limit = 500000;
$array = array(0,0,0);
if ($num1 >= $num2) {
$low = $num2;
$high = $num1;
} else {
$low = $num1;
$high = $num2;
}
for($i=$low; $i < $high; $i++) {
if ($i < 0) {
$array[0]++;
} elseif ($i >= 0 && $i < $limit) {
$array[1]++;
} else {
$array[2]++;
}
}
return $array;
}
I have started to split my loop into elseif statements but this is getting messy really quick and I will also have to eventually be able to set more than one limit which will become impossible to use.
if ($low < 0 && $high < 0) {
} elseif ($low < 0 && $high >= 0 && $high < $limit) {
} elseif ($low < 0 && $high >= $limit) {
} elseif ($low >= 0 && $low < $limit && $high < 0) {
} elseif ($low >= 0 && $low < $limit && $high >= 0 && $high < $limit) {
} elseif ($low >= 0 && $low < $limit && $high >= $limit) {
} elseif ($low >= $limit && $high < 0) {
} elseif ($low >= $limit && $high >= 0 && $high < $limit) {
} elseif ($low >= $limit && $high >= $limit) {
}
I am trying to find a clean way to do it. Any ideas?
EDIT
Here is an example of the array I'm trying to get.
If my limit was 500, $num1 = -100 and $num2 = 700 i would get the array
$array[0] = 100
$array[1] = 500
$array[2] = 200
I didn't test it (didn't run a PHP script but I tried it "manually" with a few examples).
You still have loops, but only one iteration per limit (instead of one per unit).
// Example datas
$limits = array(0, 500, 800);
$low = -100;
$high = 1000;
$splittedResults = array();
// Get total of units
$totalUnits = abs($high - $low);
$totalCounted = 0;
foreach($limits as $limit) {
if ($low > $limit) {
// Nothing under the limit
$nbUnderLimit = 0;
} elseif($high < $limit) {
// Both values under the limit
$nbUnderLimit = $totalUnits;
} else {
// $low under the limit and $high over it
$nbUnderLimit = abs($limit - $low);
}
// Here we know how much units are under current limit in total.
// We want to know how much are between previous limit and current limit.
// Assuming that limits are sorted ascending, we have to remove already counted units.
$nbBetweenLimits = $nbUnderLimit - $totalCounted;
$splittedResults[] = $nbBetweenLimits;
$totalCounted += $nbBetweenLimits;
}
// Finally, number of units that are over the last limit (the rest)
$splittedResults[] = $totalUnits - $totalCounted;
You could create an array of the numbers with range() and use array_filter
$count = sizeof(array_filter (range(0,800), function($value){ return ($value > 500); }));
And one for < as well etc.
You only need to define range array once, separately.
How can I optimize this if-statement?
if ($min && $max && $value && ($min <= $max) && ($min <= $value) && ($value <= $max)) {
// do anything
}
What it should do:
I got three values (min, max and value). First of all, all values should be != 0. Second, min <= value <= max.
Valid:
min = 1; max = 3; value = 2;
min = 2; max = 2; value = 2;
this:
if ( 0 < $min && $min <= $value && $value <= $max ){
echo 'good';
}
The answer is:
if(isset($min , $max , $value ) && ($min <= $value) && ($value <= $max)){
//Insert your code here
}
I think this prevents any value from being a 0 and makes sure value is inside the min and max range.
if ( ( $min > 0 && $max >= $min ) && ( $value >= $min && $value <= $max ) ) {
echo "Good";
} else {
echo "Bad";
}
Here is the problem, when it encounters fractions like: 300/10 instead of giving a result of "30"
the following code gives me: 1/0
$tokens = explode('/', $value);
while ($tokens[0] % 10 == 0) {
$tokens[0] = $tokens[0] / 10;
$tokens[1] = $tokens[1] / 10;
}
if ($tokens[1] == 1) {
return $tokens[0].' s';
} else {
return '1/'.floor(1/($tokens[0]/$tokens[1])).' s';
// return $tokens[0].'/'.$tokens[1].' s';
}
thanks
You should change the line while($tokens[0] % 10 === 0 && $tokens[1] % 10 === 0) { to while($tokens[0] % 10 === 0 && $tokens[1] % 10 === 0) {.
And the line return '1/'.floor(1/($tokens[0]/$tokens[1])).' s'; is not reliable.
If you want to reduce fractions, try this function:
function reduceFraction($fraction) {
sscanf($fraction, '%d/%d %s', $numerator, $denominator, $junk);
// TODO: validation
if( $denominator === null ) {
return (string)$numerator;
}
if( $numerator === $denominator ) {
return 1;
}
$max = max(array($numerator, $denominator));
for($i = 1; $i < $max; ++$i) {
if( $denominator % $i === 0 && $numerator % $i === 0) {
$common = $i;
}
}
if( $denominator === $common ) {
return (string)($numerator / $common);
}
return ($numerator / $common) . '/' . ($denominator / $common);
}
You could use it like this:
reduceFraction('300/10') . ' s';
It's also possible to generalize more the function for chained fractions (eg: '300/100/10'). I can send an implementation of it if you wish.
tell me why the "while ($tokens[0] % 10 == 0 && $tokens[1] % 10 ==0)"
would be better to use than just "while ($tokens[0] % 100 == 0)" since
both methods seem to work ok
If you try to use the string "3000/10" as an argument for each implementation, the one with while ($tokens[0] % 10 == 0 && $tokens[1] % 10 ==0) will return 300 s, and the other with while ($tokens[0] % 100 == 0) will return 1/0 s.
If you use the while ($tokens[0] % 100 == 0) method, the loop iterations are:
$tokens[0] = 3000 / 10 = 300;
$tokens[1] = 10 / 10 = 10;
$tokens[0] = 30 / 10 = 30;
$tokens[1] = 10 / 1 = .1;
Stopped because 30 % 100 != 0.
Since the $token[1] is not 1, it does not return "30 s".
1/30 is less than zero (0.0333...), thus floor(1/30) = 0. That's why it returns "1/0 s".
If you use the while ($tokens[0] % 10 == 0 && $tokens[1] % 10 == 0) method, the loop iterations are:
$tokens[0] = 3000 / 10 = 300;
$tokens[1] = 10 / 10 = 1;
Stopped because 1 % 10 != 0.
Since the $token[1] is not 1, it returns "30 s".
It is better because it will work with more inputs.
But I recommend you to use the "reduceFraction" function that I implemented.
It uses the maximum common denominator technique to reduce functions.
echo reduceFraction('3000/10'); outputs "300".
echo reduceFraction('300/10'); outputs "30".
echo reduceFraction('30/10'); outputs "3".
echo reduceFraction('3/10'); outputs "3/10".
echo reduceFraction('3/3'); outputs "1".
echo reduceFraction('222/444'); outputs "1/2".
echo reduceFraction('444/222'); outputs "2".
How can I determine using PHP code that, for example, I have a variable that has a value
between 1 and 10, or
between 20 and 40?
if (($value > 1 && $value < 10) || ($value > 20 && $value < 40))
Do you mean like:
$val1 = rand( 1, 10 ); // gives one integer between 1 and 10
$val2 = rand( 20, 40 ) ; // gives one integer between 20 and 40
or perhaps:
$range = range( 1, 10 ); // gives array( 1, 2, ..., 10 );
$range2 = range( 20, 40 ); // gives array( 20, 21, ..., 40 );
or maybe:
$truth1 = $val >= 1 && $val <= 10; // true if 1 <= x <= 10
$truth2 = $val >= 20 && $val <= 40; // true if 20 <= x <= 40
suppose you wanted:
$in_range = ( $val > 1 && $val < 10 ) || ( $val > 20 && $val < 40 ); // true if 1 < x < 10 OR 20 < x < 40
You can do this:
if(in_array($value, range(1, 10)) || in_array($value, range(20, 40))) {
# enter code here
}
if (($value >= 1 && $value <= 10) || ($value >= 20 && $value <= 40)) {
// A value between 1 to 10, or 20 to 40.
}
Sorry for the late answer, but this function allow you to do that.
function int_between($value, $start, $end) {
return in_array($value, range($start, $end));
}
// Example
$value1 = 20;
$value2 = 40;
echo int_between(20, $value1, $value2) ? "true" : "false";
Guessing from the tag 'operand' you want to check a value?
$myValue = 5;
$minValue = 1;
$maxValue = 10;
if ($myValue >= $minValue && $myValue <= $maxValue) {
//do something
}
If you just want to check the value is in Range, use this:
MIN_VALUE = 1;
MAX_VALUE = 100;
$customValue = min(MAX_VALUE,max(MIN_VALUE,$customValue)));
Try This
if (($val >= 1 && $val <= 10) || ($val >= 20 && $val <= 40))
This will return the value between 1 to 10 & 20 to 40.