Round up number to highest nearest 9 in laravel - php

I want to round up a number to highest nearest 9, Here is an example
(12,24,37,75,80)
if i gave this inputs want to get output like below given
(19,29,39,79,89)
I am using PHP(laravel), Please Help Me.

$input = [12,24,37,75,80];
$output = array_map(function($num) {
return (int)($num / 10) * 10 + 9;
}, $input);

I like the simplicity of #HTMHell's answer. And it works perfectly for integers. However, I found, that when using real numbers as input, something like 19.999 will be "rounded up" to 19.
I therefore suggest the following, modified version:
echo json_encode(array_map(function($v){
return ceil(($v+1)/10)*10-1;
},[12,18.99,19.01,24,37,75,80,90]));
// [19,19,29,29,39,79,89,99]
And, to answer #nice_dev's question, 90 should be rounded up to 99.

<?php
$items = array(12,24,37,75,80);
$endDigit = 9; //this should be between 0-9
$newItems = array();
foreach($items as $item){
$final = (int)($item / 10) * 10 + $endDigit;
array_push($newItems,$final);
}
print_r($newItems);
Output
Array ( [0] => 19 [1] => 29 [2] => 39 [3] => 79 [4] => 89 )

Related

PHP program to accept user input and terminate when entered zero

I came across this program on http://www.programmr.com . And the question is
Complete the program to print the sum of negative numbers, positive even numbers, positive odd numbers from a list of numbers entered by the user. The list terminates when the number entered is zero . And my code is,
$nums = array();
while(trim(fgets(STDIN)) != 0){
array_push($nums,trim(fgets(STDIN)));
}
I know the code is incomplete but what im trying to do is to push the inputs to the array and then calculate the sum. When I print_r($nums) the array it gives me this,
Array
(
[0] => 34
[1] => 32
[2] => 45
[3] => 0
)
And my input is,
12
34
12
32
12
45
12
0
0
It pushes the alternative elements i dont know whats happening with this. Please help me , thanks in advance.
You are calling fgets(STDIN) twice in your code, i have adjusted it a bit so the array part is working. The rest of the assignment i let you figure that part out ;) Hint: Use modulus operator.
$nums = array();
do {
$number = (int) trim(fgets(STDIN));
array_push($nums,$number);
} while ($number !== 0);
print_r($nums);
Also if you are using PHP5.6 or higher you can use short array syntax like so:
$nums = [];
And
$nums[] = $number;

Reverting a bitwise/binary number to an array of values?

I have a a list of data that has a value attached to it that constantly gets doubled as it goes up:
0 = value 0
1 = value 1
2 = value 2
4 = value 3
8 = value 4
16 = value 5
32 = value 6
64 = value 7
128 = value 8
256 = value 9
512 = value 10
I have also been given the number x
say x = 76.
Visually, I can see that value 7 (64), value 4 (8), and value 3 (4) all sum up to 76.
What I need to be able to do, is take x, run it through a function, and return an array of the values.
I've tried looping through all the numbers in reverse and taking off what value has been used, but i got confused with lots of if statements.
Is there a built in PHP function to do this? Or am I looking at it the wrong way?
Thanks
May be you are looking for this-
function getArray($x){
$ar = array();
for($i = 0 ; $i < 16; $i++){
if( ($x&(1<<$i)) != 0 ){
array_push($ar, (1<<$i));
// if you need positions; you should use it instead of above line
//array_push($ar, ($i+1));
}
}
return $ar;
}
print_r( getArray(76) );
Output:
Array (
[0] => 4
[1] => 8
[2] => 64
)
The alternate output will be (if you use array_push($ar, ($i+1));)-
Array
(
[0] => 3
[1] => 4
[2] => 7
)
Explanation:
In binary 76 presents 00000000 01001100 in 16 bit. I ran a loop from Least Significant Bit (LSB) to Most Significant Bit (MSB) (0-16). In each loop, I'm generating a new number which contains only i'th bit as 1 and rest of the bits are 0. To generate it I used shifting operator (1 << i) which is actually 2^i. Now I did a bit wise AND operation between x and the new number. If this operation returns any nonzero number that means i'th bit of x is 1 and I'm pushing that position/value inside the array. Finally I'm returning that arry.

Math & php: FAST sort of an array [1..N] in a special way

$array = array(1, 2, 3, 4, 5, ..., N);
Also there is a number D = 10%. What is the fastest way to sort the array in such way that:
$sorted_array = {a[i]}
contains exactly the elements of $array in a mixed order, but also:
abs(a[i + 1] - a[i]) >= N * 10%
for any [i] and look randomized as much as possible.
For example,
// assume D = 25%
$array = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// so the difference between any neighbors is >= 4 = 10 * 25%.
$sorted_array = array(4, 8, 3, 7, 1, 5, 9, 2, 6, 10);
Of course if D is large, it is impossible to sort the array I want. I don't need the 100% perfect result, but I want the numbers to look "randomized" and most of them to be different at least for 10%.
I have a strange task but it has a practical area to use. I want to extract randomized lines from the image and they should be different as much as possible. Of course, the neighbor lines on the digital images (photos etc) look very similar.
Did I explain it properly?
I know it's not a good idea just to provide code, but I was intrigued by this question. Here's how I would do it:
$d = 0.3;
$random = array();
// Populate the original array
for ($n=1; $n <= 10; $n++) {
$arr[] = $n;
}
$count = count($arr);
// Loop through array
foreach (array_keys($arr) as $key) {
if (!isset($prev_key)) {
$prev_key = array_rand($arr);
}
$possibles = array(); // This stores the possible values
echo "Trying: $prev_key";
echo ":\n";
// Loop through the array again and populate $possibles with all possible
// values based on the previous values
foreach (array_keys($arr) as $n) {
if ($arr[$n] < $prev_key - $count * $d || $arr[$n] > $prev_key + $count * $d) {
$possibles[] = $n;
echo $arr[$n]." is valid\n";
}
else {
echo $arr[$n];
echo " outside range\n";
}
}
// If there is nothing outside that range, just return the remaining values
if (count($possibles) == 0) {
$possibles = array_keys($arr);
echo "Nothing within range so just returning whole array\n";
}
echo "\n";
// Choose random value from the possible values array
$rand_key = $possibles[array_rand($possibles)];
$random[] = $arr[$rand_key];
$prev_key = $arr[$rand_key];
// Unset this value from the original array since we can only use the
// values once
unset($arr[$rand_key]);
}
print_r($random);
This will produce output like this:
Trying: 8:
1 is valid
2 is valid
3 is valid
4 is valid
5 outside range
6 outside range
7 outside range
8 outside range
9 outside range
10 outside range
Trying: 2:
1 outside range
3 outside range
4 outside range
5 outside range
6 is valid
7 is valid
8 is valid
9 is valid
10 is valid
Trying: 9:
1 is valid
3 is valid
4 is valid
5 is valid
6 outside range
7 outside range
8 outside range
10 outside range
Trying: 5:
1 is valid
3 outside range
4 outside range
6 outside range
7 outside range
8 outside range
10 is valid
Trying: 10:
1 is valid
3 is valid
4 is valid
6 is valid
7 outside range
8 outside range
Trying: 4:
1 outside range
3 outside range
6 outside range
7 outside range
8 is valid
Trying: 8:
1 is valid
3 is valid
6 outside range
7 outside range
Trying: 3:
1 outside range
6 outside range
7 is valid
Trying: 7:
1 is valid
6 outside range
Trying: 1:
6 is valid
Array
(
[0] => 2
[1] => 9
[2] => 5
[3] => 10
[4] => 4
[5] => 8
[6] => 3
[7] => 7
[8] => 1
[9] => 6
)
The only drawback is that since it randomly gets rows, there is a chance that the values near the end may not be outside the defined range. By my tests, this happens to about 4% using the above $d = 0.25 and 1000 values. One way to get around this is just to insert these values back in at random places instead of appending them like I have done.
Also note, this method is not that efficient. It has to loop through the array count($arr) ^ 2 times. So for 1000 values, you're looking at 1,000,000 iterations. Fortunately the array gets progressively smaller.

How to convert byte array to integer in php?

I have seen a code that converts integer into byte array. Below is the code on How to convert integer to byte array in php 3 (How to convert integer to byte array in php):
<?php
$i = 123456;
$ar = unpack("C*", pack("L", $i));
print_r($ar);
?>
The above code will output:
//output:
Array
(
[1] => 64
[2] => 226
[3] => 1
[4] => 0
)
But my problem right now is how to reverse this process. Meaning converting from byte array into integer. In the case above, the output will be 123456
Can anybody help me with this. I would be a great help. Thanks ahead.
Why not treat it like the math problem it is?
$i = ($ar[3]<<24) + ($ar[2]<<16) + ($ar[1]<<8) + $ar[0];
Since L is four bytes long, you know the number of elements of the array. Therefore you can simply perform the operation is reverse:
$ar = [64,226,1,0];
$i = unpack("L",pack("C*",$ar[3],$ar[2],$ar[1],$ar[0]));
In order to get a signed 4-byte value in PHP you need to do this:
$temp = ($ar[0]<<24) + ($ar[1]<<16) + ($ar[2]<<8) + $ar[3];
if($temp >= 2147483648)
$temp -= 4294967296;

PHP: find two or more numbers from a list of numbers that add up towards a given amount

I am trying to create a little php script that can make my life a bit easier.
Basically, I am going to have 21 text fields on a page where I am going to input 20 different numbers. In the last field I will enter a number let's call it the TOTAL AMOUNT. All I want the script to do is to point out which numbers from the 20 fields added up will come up to TOTAL AMOUNT.
Example:
field1 = 25.23
field2 = 34.45
field3 = 56.67
field4 = 63.54
field5 = 87.54
....
field20 = 4.2
Total Amount = 81.90
Output: field1 + fields3 = 81.90
Some of the fields might have 0 as value because sometimes I only need to enter 5-15 fields and the maximum will be 20.
If someone can help me out with the php code for this, will be greatly appreciated.
If you look at oezis algorithm one drawback is immediately clear: It spends very much time summing up numbers which are already known not to work. (For example if 1 + 2 is already too big, it doesn't make any sense to try 1 + 2 + 3, 1 + 2 + 3 + 4, 1 + 2 + 3 + 4 + 5, ..., too.)
Thus I have written an improved version. It does not use bit magic, it makes everything manual. A drawback is, that it requires the input values to be sorted (use rsort). But that shouldn't be a big problem ;)
function array_sum_parts($vals, $sum){
$solutions = array();
$pos = array(0 => count($vals) - 1);
$lastPosIndex = 0;
$currentPos = $pos[0];
$currentSum = 0;
while (true) {
$currentSum += $vals[$currentPos];
if ($currentSum < $sum && $currentPos != 0) {
$pos[++$lastPosIndex] = --$currentPos;
} else {
if ($currentSum == $sum) {
$solutions[] = array_slice($pos, 0, $lastPosIndex + 1);
}
if ($lastPosIndex == 0) {
break;
}
$currentSum -= $vals[$currentPos] + $vals[1 + $currentPos = --$pos[--$lastPosIndex]];
}
}
return $solutions;
}
A modified version of oezis testing program (see end) outputs:
possibilities: 540
took: 3.0897309780121
So it took only 3.1 seconds to execute, whereas oezis code executed 65 seconds on my machine (yes, my machine is very slow). That's more than 20 times faster!
Furthermore you may notice, that my code found 540 instead of 338 possibilities. This is because I adjusted the testing program to use integers instead of floats. Direct floating point comparison is rarely the right thing to do, this is a great example why: You sometimes get 59.959999999999 instead of 59.96 and thus the match will not be counted. So, if I run oezis code with integers it finds 540 possibilities, too ;)
Testing program:
// Inputs
$n = array();
$n[0] = 6.56;
$n[1] = 8.99;
$n[2] = 1.45;
$n[3] = 4.83;
$n[4] = 8.16;
$n[5] = 2.53;
$n[6] = 0.28;
$n[7] = 9.37;
$n[8] = 0.34;
$n[9] = 5.82;
$n[10] = 8.24;
$n[11] = 4.35;
$n[12] = 9.67;
$n[13] = 1.69;
$n[14] = 5.64;
$n[15] = 0.27;
$n[16] = 2.73;
$n[17] = 1.63;
$n[18] = 4.07;
$n[19] = 9.04;
$n[20] = 6.32;
// Convert to Integers
foreach ($n as &$num) {
$num *= 100;
}
$sum = 57.96 * 100;
// Sort from High to Low
rsort($n);
// Measure time
$start = microtime(true);
echo 'possibilities: ', count($result = array_sum_parts($n, $sum)), '<br />';
echo 'took: ', microtime(true) - $start;
// Check that the result is correct
foreach ($result as $element) {
$s = 0;
foreach ($element as $i) {
$s += $n[$i];
}
if ($s != $sum) echo '<br />FAIL!';
}
var_dump($result);
sorry for adding a new answer, but this is a complete new solution to solve all problems of life, universe and everything...:
function array_sum_parts($n,$t,$all=false){
$count_n = count($n); // how much fields are in that array?
$count = pow(2,$count_n); // we need to do 2^fields calculations to test all possibilities
# now i want to look at every number from 1 to $count, where the number is representing
# the array and add up all array-elements which are at positions where my actual number
# has a 1-bit
# EXAMPLE:
# $i = 1 in binary mode 1 = 01 i'll use ony the first array-element
# $i = 10 in binary mode 10 = 1010 ill use the secont and the fourth array-element
# and so on... the number of 1-bits is the amount of numbers used in that try
for($i=1;$i<=$count;$i++){ // start calculating all possibilities
$total=0; // sum of this try
$anzahl=0; // counter for 1-bits in this try
$k = $i; // store $i to another variable which can be changed during the loop
for($j=0;$j<$count_n;$j++){ // loop trough array-elemnts
$total+=($k%2)*$n[$j]; // add up if the corresponding bit of $i is 1
$anzahl+=($k%2); // add up the number of 1-bits
$k=$k>>1; //bit-shift to the left for looking at the next bit in the next loop
}
if($total==$t){
$loesung[$i] = $anzahl; // if sum of this try is the sum we are looking for, save this to an array (whith the number of 1-bits for sorting)
if(!$all){
break; // if we're not looking for all solutions, make a break because the first one was found
}
}
}
asort($loesung); // sort all solutions by the amount of numbers used
// formating the solutions to getting back the original array-keys (which shoud be the return-value)
foreach($loesung as $val=>$anzahl){
$bit = strrev(decbin($val));
$total=0;
$ret_this = array();
for($j=0;$j<=strlen($bit);$j++){
if($bit[$j]=='1'){
$ret_this[] = $j;
}
}
$ret[]=$ret_this;
}
return $ret;
}
// Inputs
$n[0]=6.56;
$n[1]=8.99;
$n[2]=1.45;
$n[3]=4.83;
$n[4]=8.16;
$n[5]=2.53;
$n[6]=0.28;
$n[7]=9.37;
$n[8]=0.34;
$n[9]=5.82;
$n[10]=8.24;
$n[11]=4.35;
$n[12]=9.67;
$n[13]=1.69;
$n[14]=5.64;
$n[15]=0.27;
$n[16]=2.73;
$n[17]=1.63;
$n[18]=4.07;
$n[19]=9.04;
$n[20]=6.32;
// Output
$t=57.96;
var_dump(array_sum_parts($n,$t)); //returns one possible solution (fuc*** fast)
var_dump(array_sum_parts($n,$t,true)); // returns all possible solution (relatively fast when you think of all the needet calculations)
if you don't use the third parameter, it returns the best (whith the least amount numbers used) solution as array (whith keys of the input-array) - if you set the third parameter to true, ALL solutions are returned (for testing, i used the same numbers as zaf in his post - there are 338 solutions in this case, found in ~10sec on my machine).
EDIT:
if you get all, you get the results ordered by which is "best" - whithout this, you only get the first found solution (which isn't necessarily the best).
EDIT2:
to forfil the desire of some explanation, i commented the essential parts of the code . if anyone needs more explanation, please ask
1. Check and eliminate fields values more than 21st field
2. Check highest of the remaining, Add smallest,
3. if its greater than 21st eliminate highest (iterate this process)
4. If lower: Highest + second Lowest, if equal show result.
5. if higher go to step 7
6. if lower go to step 4
7. if its lower than add second lowest, go to step 3.
8. if its equal show result
This is efficient and will take less execution time.
Following method will give you an answer... almost all of the time. Increase the iterations variable to your taste.
<?php
// Inputs
$n[1]=8.99;
$n[2]=1.45;
$n[3]=4.83;
$n[4]=8.16;
$n[5]=2.53;
$n[6]=0.28;
$n[7]=9.37;
$n[8]=0.34;
$n[9]=5.82;
$n[10]=8.24;
$n[11]=4.35;
$n[12]=9.67;
$n[13]=1.69;
$n[14]=5.64;
$n[15]=0.27;
$n[16]=2.73;
$n[17]=1.63;
$n[18]=4.07;
$n[19]=9.04;
$n[20]=6.32;
// Output
$t=57.96;
// Let's try to do this a million times randomly
// Relax, thats less than a blink
$iterations=1000000;
while($iterations-->0){
$z=array_rand($n, mt_rand(2,20));
$total=0;
foreach($z as $x) $total+=$n[$x];
if($total==$t)break;
}
// If we did less than a million times we have an answer
if($iterations>0){
$total=0;
foreach($z as $x){
$total+=$n[$x];
print("[$x] + ". $n[$x] . " = $total<br/>");
}
}
?>
One solution:
[1] + 8.99 = 8.99
[4] + 8.16 = 17.15
[5] + 2.53 = 19.68
[6] + 0.28 = 19.96
[8] + 0.34 = 20.3
[10] + 8.24 = 28.54
[11] + 4.35 = 32.89
[13] + 1.69 = 34.58
[14] + 5.64 = 40.22
[15] + 0.27 = 40.49
[16] + 2.73 = 43.22
[17] + 1.63 = 44.85
[18] + 4.07 = 48.92
[19] + 9.04 = 57.96
A probably inefficient but simple solution with backtracking
function subset_sums($a, $val, $i = 0) {
$r = array();
while($i < count($a)) {
$v = $a[$i];
if($v == $val)
$r[] = $v;
if($v < $val)
foreach(subset_sums($a, $val - $v, $i + 1) as $s)
$r[] = "$v $s";
$i++;
}
return $r;
}
example
$ns = array(1, 2, 6, 7, 11, 5, 8, 9, 3);
print_r(subset_sums($ns, 11));
result
Array
(
[0] => 1 2 5 3
[1] => 1 2 8
[2] => 1 7 3
[3] => 2 6 3
[4] => 2 9
[5] => 6 5
[6] => 11
[7] => 8 3
)
i don't think the answer isn't as easy as nik mentioned. let's ay you have the following numbers:
1 2 3 6 8
looking for an amount of 10
niks solution would do this (if i understand it right):
1*8 = 9 = too low
adding next lowest (2) = 11 = too high
now he would delete the high number and start again taking the new highest
1*6 = 7 = too low
adding next lowest (2) = 9 = too low
adding next lowest (3) = 12 = too high
... and so on, where the perfect answer would simply
be 8+2 = 10... i think the only solution is trying every possible combination of
numbers and stop if the amaunt you are looking for is found (or realy calculate all, if there are different solutions and save which one has used least numbers).
EDIT: realy calculating all possible combiations of 21 numbers will end up in realy, realy, realy much calculations - so there must be any "intelligent" solution for adding numbers in a special order (lik that one in niks post - with some improvements, maybe that will bring us to a reliable solution)
Without knowing if this is a homework assignment or not, I can give you some pseudo code as a hint for a possible solution, note the solution is not very efficient, more of a demonstration.
Hint:
Compare each field value to all field value and at each iteration check if their sum is equal to TOTAL_AMOUNT.
Pseudo code:
for i through field 1-20
for j through field 1-20
if value of i + value of j == total_amount
return i and j
Update:
What you seem to be having is the Subset sum problem, given within the Wiki link is pseudo code for the algorithm which might help point you in the right direction.

Categories