using if statement count number of notes given in amount - php

i have a assingment and i am so confuse i dont know how to solve my problem,
Assingment :
Make a system which should have the capability to analyze the total number of possible notes in a given amount using only if statement,
Example
Input:
Input amount: 575
Output
Total number of notes:
500: 1
100: 0
50: 1
20: 1
10: 0
5: 1
2: 0
1: 0
plese tell me how i write code of this,
i need your help i don't know how i make this,

Assuming the keys won't change:
<?php
function getPossibleNotes($input, $keysArray = [500, 100, 50, 20, 10, 5, 2, 1])
{
$responseArray = array_combine($keysArray, array_fill(0, count($keysArray), 0));
foreach($keysArray as $comparison){
if($input >= $comparison){
$input -= $comparison;
$responseArray[$comparison] = 1;
}
if($input <= 0){
break;
}
}
return $responseArray;
}
//When Input = 575
print_r(getPossibleNotes(575));
/*
Array
(
[500] => 1
[100] => 0
[50] => 1
[20] => 1
[10] => 0
[5] => 1
[2] => 0
[1] => 0
)
*/
Edit: if you need the count of the notes (As I see in other answers), do this replacement:
$responseArray[$comparison]++;

Related

Php - get number, not char from string

I'm not very familiar with php and got stuck in how to use substr in this case:
I have to do the parse of a string that has some numbers and symbols,
example:
1[2[3,5],4[7[65,9,11],8]]
And to do this I used a for that will go through and get each char of the string,
something like that:
$count = 0;
for($i = 0; $i <= strlen($string); $i++){
$char = substr($string, $i, 1);
if($char == '['){
$count --;
}
if($char == ']'){
$count ++;
}
if($count == 0){
break;
}
if(is_numeric(substr($string, $i +1, 1)) and $count == -1){
$number = substr($string, $i +1, 1);
$array_aux[] = $number;
}
}
But as I'm getting the char in (substr ($ string, $ i, 1)) it does not work for numbers with more than one digit, such as 65 and 11
And the contents of the array gets something like: (..., 6, 5, 9, 1, 1, ...)
When should be something like: (..., 65, 9, 11, ...)
Any help?
Sorry, I think was not clear enough.
I need the numbers that are inside '[' when count has the value -1
(that's why I'm using substr, and taking every char)
examples: when the string is: 1[2[3,5],4[7[65,9,11],8]], the array must contain 2 and 4
when the string is: 2[3,5],4[7[65,9,11],8]], the array must contain 3 and 5
when the string is: 7[65,9,11],8]], the array must contain 65, 9 and 11. And so on...
Sorry to put these details only now, I was without computer :(
preg_match_all with a simple regular expression can do this for you:
$in = "1[2[3,5],4[7[65,9,11],8]]";
preg_match_all('~\d+~', $in, $out);
print_r($out[0]);
Outputs:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 5
[4] => 4
[5] => 7
[6] => 65
[7] => 9
[8] => 11
[9] => 8
)
You can use preg_split and split by matching one or more times not a digit \D+
$str = "1[2[3,5],4[7[65,9,11],8]]";
print_r(preg_split("/\D+/", $str, -1, PREG_SPLIT_NO_EMPTY));
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 5
[4] => 4
[5] => 7
[6] => 65
[7] => 9
[8] => 11
[9] => 8
)

Merge 2 rows into one filling empty fields

So, I have been searching but I could not find something similair.
What I need is to merge 2 rows what I got from DB (stored in an Array) and fill out empty fields.
We have 2 keys FIXED and WEIGHT and they have different values in columns. If we use FIXED type we do not use values from WEIGHT and those columns are empty, now I have to merge those 2 2rows into one.
There is N rows (but always in pair).
Here is example
id type postal fix_price weight_price our_price your_price product_id group_id
1 fixed 8888 50 - 50 - 1 2
2 weight 8888 - 100 - 100 1 2
3 fixed 7777 20 - 20 - 1 2
4 weight 7777 - 30 - 30 1 2
And I need result like below:
id postal fix_price weight_price our_price your_price product_id group_id
1 8888 50 100 50 100 1 2
2 7777 20 30 20 30 1 2
Thank you for helping!
Try:
$collect=array();
$useType='fixed';
foreach($array as $set){
$check=$set['type'];
unset($set['type']);
if(!isset($collect[$set['postal']])) {
$collect[$set['postal']] = $set;
} else {
foreach($set as $k=>$v){
if($k=='id' && $check!=$useType) {
continue;
}
if(!empty($v)){
$collect[$set['postal']][$k] = $v;
}
}
}
}
$collect=array_values($collect);
var_export($collect);
This produces your expacted result, but i dont thing that is what you really want.
I don't really understand how your question is related with the (very different) data structure you shared in your comment under the #JustOnUnderMillions answer, so here is an answer based on the structure suggested by your initial question.
Taking advantage of your other comment where you say "I have tried with $arra1 + $array2" I guess you're able to first format the source data like this:
$fixed = [
8888 => [50, NULL, 50, NULL, 1, 2],
7777 => [20, NULL, 20, NULL, 1, 2],
];
$weight = [
8888 => [NULL, 100, NULL, 100, 1, 2],
7777 => [NULL, 30, NULL, 30, 1, 2],
];
Then it's pretty easy to use this simple code:
foreach ($fixed AS $postal => $fixed_data) {
$weight_data = $weight[$postal];
foreach ($fixed_data AS $key => $fixed_value) {
$all[$postal][$key] = $fixed_value ? $fixed_value : $weight_data[$key];
}
}
which gives the expected result:
echo '<pre>' . print_r($all, TRUE) . '</pre>';
/*
Array
(
[8888] => Array
(
[0] => 50
[1] => 100
[2] => 50
[3] => 100
[4] => 1
[5] => 2
)
[7777] => Array
(
[0] => 20
[1] => 30
[2] => 20
[3] => 30
[4] => 1
[5] => 2
)
)
*/

Loop through variables, increment by 10 and create new variable

I have $amounts eg. 31; 48; 57; 63; 79; 84 and 95
What I would like to do is loop through each “$amount”, and if they are above 50, create variable that adds 1 for each 10 increment
Eg.
$amount(57) = +1
$amount(63) = +2
$amount(79) = +3
$amount(84) = +4
$amount(95) = +5
UPDATED VERSION:
Apologies for the vague question.
I have
$amount = array(end($percentage));
eg. 47, 63, 79, 95
What I would like to have is another variable to be created eg. $to_add if $amount > 50.
Then for each $amount >= 50 add 1 to the $to_add
Should look like:
$amount(47) = NULL ($to_add = 0)
$amount(50) = $to_add = 1 – *WOULD HAVE BEEN*
$amount(63) = $to_add = 2
$amount(79) = $to_add = 3
$amount(80) = $to_add = 4 – *WOULD HAVE BEEN*
$amount(95) = $to_add = 5
Thanks for the input thus far - I am testing the feedback I have already received - thank you very much!
This should work for you:
(Here I just go through each element with array_map(), then I check if the value is over 50 and if yes I add 1 for every 10)
<?php
$amount = [31, 48, 57, 63, 79, 84, 95];
print_r($amount);
$amount = array_map(function($v){
if($v / 50 >= 1)
return ceil($v + ($v-50)/10);
return $v;
}, $amount);
print_r($amount);
?>
output:
Array ( [0] => 31 [1] => 48 [2] => 57 [3] => 63 [4] => 79 [5] => 84 [6] => 95 )
Array ( [0] => 31 [1] => 48 [2] => 58 [3] => 65 [4] => 82 [5] => 88 [6] => 100 )
Somewhat like this:
$array=array();
$i=0;
foreach($amounts as $amount){
if($amount>50){
$value=floor($amount/10);
$array[$i]=$value;
$i++;
}
}
var_dump($array);
Now $array contains the values you want. You have to adapt the code to your code since I have no idea what $amount is(I assume values of an array)

Adjust function for pyramid-like distribution

In this question I got help to write a PHP function which gives a pyramid-like distribution:
function getRandomStrength($min, $max) {
$ln_low = log($min, M_E);
$ln_high = log($max, M_E);
$scale = $ln_high-$ln_low;
$rand = (mt_rand()/mt_getrandmax())*$scale+$ln_low;
$value = round(pow(M_E, $rand), 1);
return $value;
}
getRandomStrenth(1.1, 9.9);
// output could be: 1.4 or 8.3 or 9.8 or 7.2 or 2.9 or ...
When I run 50,000 iterations and check how often the numbers from 1 to 9 appear, I get the following list:
1 » 26%
2 » 19%
3 » 14%
4 » 10%
5 » 9%
6 » 7%
7 » 6%
8 » 6%
9 » 4%
This is what I wanted to have. But now I would like to adjust this function a bit. The smaller values should appear more often and the big values should appear less often - so that I get a list like this:
1 » 28%
2 » 20%
3 » 15%
4 » 11%
5 » 9%
6 » 6%
7 » 5%
8 » 5%
9 » 2%
As you can see, I just need a slight modification. But what can I change so that my function behaves as expected?
I tried several things (e.g. changing the base of the logarithm) but this did not change anything.
You can use pow on the random number.
$rand = pow( mt_rand()/mt_getrandmax(), 1.2 )*$scale+$ln_low;
By playing with the exponent value, you can get less or more small value.
Reducing the $scale of your function by a small (constant) amount seems to generate results pretty close to what you're looking for. You can achieve more accurate results by making this reduction of $scale a function of the randomly generated number from mt_rand(), which would require saving (mt_rand()/mt_getrandmax()) to a variable and performing some additional math on $scale.
Here are my tests, you can run it yourself: http://codepad.viper-7.com/ssblbQ
function getRandomStrength($min, $max)
{
$ln_low = log($min, M_E);
$ln_high = log($max, M_E);
$scale = $ln_high-$ln_low - .05; // Subtract a small constant, vary between .05 and .08
$rand = (mt_rand()/mt_getrandmax())*$scale+$ln_low;
$value = round(pow(M_E, $rand), 1);
return $value;
}
$values = array_fill(1, 9, 0);
for( $i = 0; $i < 50000; $i++)
{
$values[ intval( getRandomStrength(1.1, 9.9)) ]++;
}
for( $i = 1; $i <= 9; $i++)
{
$values[ $i] /= 500; // / 50000 * 100 to get a percent
}
var_dump( $values);
Output
Run #1 - Constant = 0.5
array(9) {
[1] => float(26.626) // Should be 28
[2] => float(19.464) // Should be 20
[3] => float(13.476) // Should be 15
[4] => float(10.41) // Should be 11
[5] => float(8.616) // Should be 9
[6] => float(7.198) // Should be 6
[7] => float(6.258) // Should be 5
[8] => float(5.52) // Should be 5
[9] => float(2.432) // Should be 2
}
Run #2 - Constant = 0.65
array(9) {
[1] => float(26.75) // Should be 28
[2] => float(19.466) // Should be 20
[3] => float(13.872) // Should be 15
[4] => float(10.562) // Should be 11
[5] => float(8.466) // Should be 9
[6] => float(7.222) // Should be 6
[7] => float(6.454) // Should be 5
[8] => float(5.554) // Should be 5
[9] => float(1.654) // Should be 2
}
Run #3 - Constant = 0.70
array(9) {
[1] => float(26.848) // Should be 28
[2] => float(19.476) // Should be 20
[3] => float(13.808) // Should be 15
[4] => float(10.764) // Should be 11
[5] => float(8.67) // Should be 9
[6] => float(7.148) // Should be 6
[7] => float(6.264) // Should be 5
[8] => float(5.576) // Should be 5
[9] => float(1.446) // Should be 2
}
For n in {0..1}, y=(x^n)-1, y will range from 0 to x-1. That curve is then easily mapped from 0 to some max value by multiplying by the range and dividing by (x-1). If you change the value x to something near one, the curve will be nearly linear, and at large values, the curve becomes more like a hockey-stick, but will still fall in the same range.
My initial sample value of three won't be precisely what you expressed, but you can adjust it to get the distribution curve you're looking for.
function getCustomStrength($min, $max, $x_val, $base) {
$logmax = $base-1;
$range = $max-$min;
return (pow($base,$x_val)-1)*($range/($base-1))+$min;
}
function getRandomStrength($min, $max) {
$rand = mt_rand()/mt_getrandmax();
$base = 3.0;
return getCustomStrength($min, $max, $rand, $base);
}
getRandomStrength(1.1, 9.9);

Evenly distributed integers within a range

Lets say I have a range between 0 and 100 and I want an array returned containing 3 integers which are evenly distributed within that range, what would be the best way to do this?
For example:
Range: 0-100
Wanted: 3
Returned: 25, 50, 75
Pseudo code:
function distributeIntegers(int wanted, int rangeLow, int rangeHigh)
int increment = (rangeHigh - rangeLow) / (wanted + 1)
array r = new array()
for (int i = rangeLow + increment; i < rangeHigh; i += increment)
r.push(i)
return r
PHP:
function distributeIntegers($wanted = 3, $rangeLow = 0, $rangeHigh = 100){
$increment = ($rangeHigh - $rangeLow) / ($wanted + 1);
$r = array();
for ($i = $rangeLow + $increment; $i < $rangeHigh; $i += $increment)
$r []= $i;
return $r;
}
/*
examples:
call:
distributeIntegers();
returns:
[0] => 25
[1] => 50
[2] => 75
call:
distributeIntegers(4);
returns:
[0] => 20
[1] => 40
[2] => 60
[3] => 80
call:
distributeIntegers(5, 50, 200);
returns:
[0] => 75
[1] => 100
[2] => 125
[3] => 150
[4] => 175
*/
you can make use of array_chunk(), eg only
$end=100;
$a = range(0,$end);
$chunk=3;
foreach (array_chunk($a,$end/($chunk+1)) as $s){
print $s[0]."\n";
}
output
$ php test.php
0
25
50
75
100
you can get rid of the start (0) and end(100) points if not needed.
Here's a solution in groovy that gives the answers you want, you should be able to switch it to whatever language you're using:
def distributedValues(min, max, wanted) {
def incrementBy = (max - min)/(wanted + 1)
(1..wanted).collect { count -> min + (count * incrementBy) }
}
assert distributedValues(0, 100, 1) == [50]
assert distributedValues(0, 100, 3) == [25, 50, 75]
assert distributedValues(0, 100, 4) == [20, 40, 60, 80]
assert distributedValues(0, 100, 5) == [16.6666666667, 33.3333333334, 50.0000000001, 66.6666666668, 83.3333333335]
assert distributedValues(100, 200, 3) == [125, 150, 175]
You can use the rand function to get the random value between the specific ranges.
Use this code . This following function would return set of element in a array
function array_elements( $start = 0 , $end = 100 , $element =5 )
{
$myarray = array () ;
for ( $i = 0 ; $i < $element;$i++ )
{
$myarray[$i]= rand ( $start, $end );
}
return $myarray ;
}
print_r ( array_elements() ) ;

Categories