I'm new on PHP and I want to find the 0 and replace with the number that is missed, inside the inner array, on a multidimensional array. If the inner array has more than two 0's, it will be ignored and goes to the next.
$list = array("First"=>array(0,1,2,3,0,5,6,7,8,9),
"Second"=>array(0,1,2,3,4,5,6,7,8,9),
"Third"=>array(0,1,2,3,4,5,0,0,8,9),
"Fourth"=>array(0,1,2,3,4,5,6,7,8,0),
"Fifth"=>array(0,1,2,3,4,5,0,7,8,9),
"Sixth"=>array(0,0,0,3,4,5,6,0,0,0),
"Seventh"=>array(0,1,2,3,0,0,6,7,8,9),
"Eighth"=>array(0,1,2,3,4,5,0,7,8,9),
"Ninth"=>array(0,1,2,3,4,0,6,7,8,9),
"Tenth"=>array(0,0,2,3,4,5,6,7,8,9));
$countZero = 0;
foreach($list as $lvl) {
foreach($lvl as $ind => $val) {
if($countZero = array_count_values($lvl[$val] === 0))
$list[$ind][$val] = 45 - array_sum($ind);
echo $count;
}
}
I want all inner arrays, that have two 0's get only one, to have all numbers in sequence i.e.
"First"=>array(0,1,2,3,4,5,6,7,8,9);
Please, help me.
I tried this code below, trying to finde the 0's.
$counts = 0;
$newArr = array();
foreach($list as $lvl) {
if(is_array($lvl)) {
for($i = 0; $i < count($lvl) - 1; $i++) {
if(($lvl[$i] == 0) < 2){
$counts++;
$newArr[$i] = 45 - array_sum($lvl);
}
}
}
}
print_r($newArr);
This is a solution using array_walk:
array_walk($list,
function(&$numbers) {
$zeroIndex = 0;
foreach($numbers as $i => $number) {
if( $number === 0 ) {
if( $zeroIndex > 0 ) {
return;
}
$zeroIndex = $i;
}
}
$numbers[$zeroIndex] = $zeroIndex;
});
You don't need to count all the zeros. You just need to check if there are less than 3 zeros.
I'm saving the index (position) of zero ($zeroIndex = $i).
I'm assuming that the first number is always a zero ($zeroIndex = 0).
The index of the second zero is greater than zero. If I find a zero when the index of the last found zero is greater than zero (if( $zeroIndex > 0 )), this means that there are more than two zeros.
In fact,here is what I've done and worked.
$list = array(array(1,2,3,0,5,6,7,8,9),
array(1,2,3,4,5,6,7,8,9),
array(1,2,3,4,5,0,0,8,9),
array(1,2,3,4,5,6,7,8,0),
array(1,2,3,4,5,0,7,8,9),
array(0,0,3,4,5,6,0,0,0),
array(1,2,3,0,0,6,7,8,9),
array(1,2,3,4,5,0,7,8,9),
array(1,2,3,4,0,6,7,8,9));
for($l = 0; $l < count($list); $l++)
{
$total = 0;
$countZ = 0;
for($i=0; $i < 9; $i++)
{
if($list[$l][$i] == 0)
{
$countZ++;
$indexZero = $i;
}
$total += $list[$l][$i];
if($countZ > 1) {
break;
}
}
$list[$l][$indexZero] = 45 - $total;
}
print_r($list);
TY all.
Related
I need to calculate from a given array the number that is equal or higher and closest to a given number in PHP. Example:
Number to fetch:
6.85505196
Array to calculate:
3.11350000
4.38350000
4.04610000
3.99410000
2.86135817
0.50000000
Only correct combination should be:
3.99410000 + 2.86135817 = 6.85545817
Can somebody help me? It's been 3 hours I'm getting mad!
UPDATE: I finally finished my code as following:
$arr = array(3.1135, 4.3835, 4.0461, 3.9941, 2.86135817, 0.5);
$fetch = 6.85505196;
$bestsum = get_fee($arr, $fetch);
print($bestsum);
function get_fee($arr, $fetch) {
$bestsum = 999999999;
$combo = array();
$result = array();
for ($i = 0; $i<count($arr); $i++) {
combinations($arr, $i+1, $combo);
}
foreach ($combo as $idx => $arr) {
$sum = 0;
foreach ($arr as $value) {
$result[$idx] += $value;
}
if ($result[$idx] >= $fetch && $result[$idx] < $bestsum) $bestsum = $result[$idx];
}
return $bestsum;
}
function combinations($arr, $level, &$combo, $curr = array()) {
for($j = 0; $j < count($arr); $j++) {
$new = array_merge($curr, array($arr[$j]));
if($level == 1) {
sort($new);
if (!in_array($new, $combo)) {
$combo[] = $new;
}
} else {
combinations($arr, $level - 1, $combo, $new);
}
}
}
I hope the following example might help you. Please try this
<?php
$array = array(
"3.11350000",
"4.38350000",
"4.04610000",
"3.99410000",
"2.86135817",
"0.50000000"
);
echo "<pre>";
print_r($array);// it will print your array
for($i=0; $i<count($array); $i++)
{
$j=$i+1;
for($j;$j<count($array); $j++)
{
$sum = $array[$i] + $array[$j];
// echo $array[$i]. " + ".$array[$j]." = ".$sum."<br>"; //this will display all the combination of sum
if($sum >= 6.85505196 && ($sum <= round(6.85505196)) )//change the condition according to your requirement
{
echo "The correct combinations are:<br/><br/>";
echo "<b>". $array[$i]. " + ".$array[$j]." = ".$sum."<b>";
echo "<br/>";
}
}
echo "<br/>";
}
?>
We will get the result as below
Array
(
[0] => 3.11350000
[1] => 4.38350000
[2] => 4.04610000
[3] => 3.99410000
[4] => 2.86135817
[5] => 0.50000000
)
The correct combinations are:
4.04610000 + 2.86135817 = 6.90745817
3.99410000 + 2.86135817 = 6.85545817
You should do it in two steps:
a. Work out (or look up) an algorithm to do the job.
b. Implement it.
You don't say what you've managed in the three hours you worked on this, so here's a "brute force" (read: dumb) algorithm that will do the job:
Use a variable that will keep your best sum so far. It can start out as zero:
$bestsum = 0;
Try all single numbers, then all sums of two numbers, then all sums of three numbers, etc.: Every time you find a number that meets your criteria and is better than the current $bestsum, set $bestsum to it. Also set a second variable, $summands, to an array of the numbers you used to get this result. (Otherwise you won't know how you got the solution). Whenever you find an even better solution, update both variables.
When you've tried every number combination, your two variables contain the best solution. Print them out.
That's all. It's guaranteed to work correctly, since it tries all possibilities. There are all sorts of details to fill in, but you can get to work and ask here for help with specific tasks if you get stuck.
Thank you all for your help!
My code is working pretty cool when is needed to fetch one or two numbers (addition) only. But can't figure out how to add more combinations up to the total count of elements in my given array.
I mean if there are, let's say, 8 numbers in my array I want to try all possible combinations (additions to each other) as well.
My actual code is:
$bestsum = 1000000;
for ($i = 0; $i < count($txinfo["vout"]); $i++) {
if ($txinfo["vout"][$i]["value"] >= $spent && $txinfo["vout"][$i]["value"] < $bestsum) {
$bestsum = $txinfo["vout"][$i]["value"];
}
}
for($i = 0; $i < count($txinfo["vout"]); $i++) {
$j = $i + 1;
for($j; $j < count($txinfo["vout"]); $j++) {
$sum = $txinfo["vout"][$i]["value"] + $txinfo["vout"][$j]["value"];
if($sum >= $spent && $sum < $bestsum) {
$bestsum = $sum;
}
}
}
$fee = bcsub($bestsum, $spent, 8);
print("Fee: ".$fee);
New updated code.
<?php
$x = 6.85505196;
$num = array(3.1135, 4.3835, 4.0461, 3.9941, 2.86135817, 0.5);
asort($num); //sort the array
$low = $num[0]; // lowest value in the array
$maxpossible = $x+$low; // this is the maximum possible answer, as we require the number that is equal or higher and closest to a given number
$num = array_values($num);
$iterations = $x/$num[0]; // possible combinations loop, to equate to the sum of the given number using the lowest number
$sum=$num;
$newsum = $sum;
$k=count($num);
for($j=0; $j<=$iterations; $j++){
$l = count($sum);
for($i=0; $i<$l; $i++){
$genSum = $sum[$j]+$sum[$i];
if($genSum <= $maxpossible){
$newsum[$k] = $genSum;
$k++;
}
}
$newsum = array_unique($newsum);
$newsum = array_values($newsum);
$k = count($newsum);
$sum = $newsum;
}
asort($newsum);
$newsum = array_values($newsum);
for($i=0; $i<count($newsum); $i++){
if($x<=$newsum[$i]){
echo "\nMaximum Possible Number = ".$newsum[$i];
break;
}
}
?>
Here is my code:
$n = 300;
$set = 0;
$set2 = 0;
for($i = 1; $i<$n; $i++)
{
for($j = 1; $j <$i; $j++)
{
$qol = $i % $j;
if($qol == 0)
{
$set += $j;
}
}
for($s=1; $s<$set; $s++)
{
$qol2 = $set % $s;
if($s == 0)
{
$set2 += $s;
}
}
if($set2 == $i)
{
echo "$set and $i are amicable numbers</br>";
}
}
I do not know what the heck the problem is!
FYI: 220 and 284 are an example of amicable numbers. The sum of the proper divisors of one number are equal to other number and vice versa (wiki).
I am having troubles following your logic. In your code how would $set2 == $i ever be true? Seems to me that $i would always be greater.
I would do it the following way:
First make a separate function that finds the sums of the proper divisors:
// Function to output sum of proper divisors of $num
function sumDiv($num) {
// Return 0 if $num is 1 or less
if ($num <= 1) {
return 0;
}
$result = 1; // All nums divide by 1
$sqrt = sqrt($num);
// Add divisors to result
for ($i = 2; $i < $sqrt; $i++) {
if ($num % $i == 0) {
$result += $i + $num / $i;
}
}
// If perfect square add squareroot to result
if (floor($sqrt) == $sqrt) {
$result += $sqrt;
}
return $result;
}
Next check each iteration for a match:
$n = 1500;
for ($i = 1; $i < $n; $i++) {
// Get sum of proper devisors of $i, and sum of div. of result.
$currentDivs = sumDiv($i);
$resultDivs = sumDiv($currentDivs);
// Check for a match with sums not equal to each other.
if ($i == $resultDivs && $currentDivs != $resultDivs) {
echo "$i and $currentDivs are amicable numbers<br>";
}
}
Here a functioning phpfiddle.
Warning: Large numbers will take very long to process!
Why does this not make two arrays one within 7 numbers and one within 2 numbers in it?
It somehow combines the both into one.
When i echo $arvottuLottoRivi and $lottoLisaNumerot in my HTML page the result is:
$arvottuLottoRivi (1,2,3,4,5,6,7,8,9,10) : $lottoLisaNumerot
all the seven numbers.
I have now tried three different styles but same thing happens in all cases
// VARAIBLES
$lottoNumerot = $_POST["lottoNumerot"];
$mahdollisetNumerot = array("1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39");
$i = 0;
$l = 0;
$k = 0;
//ARRAYS
$arvottuLottoRivi = array();
$lottoLisaNumerot = array();
$tenNumbersArray = array();
//FUNCTIONS
$numeroidenRandomointi = array_rand($mahdollisetNumerot, 10);
// COUNTS ARRAY LENGHT
$lottoRivinPituus = count($numeroidenRandomointi);;
// LOOPS
foreach($numeroidenRandomointi as $randomNumero){
while($i <= $lottoRivinPituus){
$i++;
}
$randomToArray = array_push($tenNumbersArray, $randomNumero);
}
// LOOPIT
foreach($tenNumbersArray as $randomToSite){
while($l <= $lottoRivinPituus){
$l++;
}
if($l <= 7){
array_push($arvottuLottoRivi, $randomToSite);
}
}
foreach($tenNumbersArray as $randomToSiteLisanuimerot){
while($k <= $lottoRivinPituus){
$k++;
}
if($k >= 7){
array_push($lottoLisaNumerot, $randomToSiteLisanuimerot);
}
}
$arvottuLottoRivi = implode(' ', $arvottuLottoRivi);
$lottoLisaNumerot = implode(' ', $lottoLisaNumerot);
When you write:
foreach($tenNumbersArray as $randomToSiteLisanuimerot){
while($k <= $lottoRivinPituus){
$k++;
}
if($k >= 7){
array_push($lottoLisaNumerot, $randomToSiteLisanuimerot);
}
}
the while loop is equivalent to:
$k = $lottoRivinPituus + 1;
Since $lottoRivinPituus is 10, $k is always 11. Therefore, if($k >= 7) is always true, so all elements of $randomToSiteLisanuumerot are copied to $lottoLisaNumerot. Similarly, in the previous loop, the test if ($l <= 7) is always false, so nothing is copied to $arvottuLottoRivi.
I think you were trying to test the current position in the loop, not the count of all elements in the array. You can do it like this:
foreach($tenNumbersArray as $l => $randomToSite){
if($l < 7){
array_push($arvottuLottoRivi, $randomToSite);
}
}
foreach($tenNumbersArray as $k => $randomToSiteLisanuimerot){
if($k >= 7){
array_push($lottoLisaNumerot, $randomToSiteLisanuimerot);
}
}
But this wastes time iterating over elements it doesn't care about. A better way would be:
$arvotSize = min(7, $lottoRivinPituus);
for ($l = 0; $l < $arvotSize; $l++) {
array_push($arvottuLottoRivi, $tenNumbersArray[$l]);
}
for ($k = $arvotSize; $k < $lottoRivinPituus; $k++) {
array_push($lottoLisaNumerot, $tenNumbersArray[$k]);
}
I really didn't get your code.
Why don't use rand function?
$randomNumbers1 = array();
$randomNumbers2 = array();
$i = 0;
while ($i < 7) {
$aNumber = rand(1, 39);
if (!in_array($aNumber, $randomNumbers1)) {
$randomNumbers1[] = $aNumber;
$i++;
}
}
$i = 0;
while ($i < 2) {
$aNumber = rand(1, 39);
if (!in_array($aNumber, $randomNumbers2)) {
$randomNumbers2[] = $aNumber;
$i++;
}
}
And if the seconds array cannot contains any number within the first one:
$i = 0;
while ($i < 2) {
$aNumber = rand(1, 39);
if (!in_array($aNumber, $randomNumbers2) && !in_array($aNumber, $randomNumbers1)) {
$randomNumbers2[] = $aNumber;
$i++;
}
}
I am trying to find duplicated values/string in an array using for loop
<?php
$b=array('a','b','c','a','b');
$c=count($b);
$d=array();
for($i=0;$i<=($c-1);$i++)
{
for($j=1;$j<=($c-1);$j++)
{
if($b[$i]!=$b[$j])
{
$flag=1;
}
}
if($flag==1)
{
$d[$i]=$b[$i];
}
}
print_R($d);
?>
where is my mistake? I have used array $d to display non duplicate values.....
NOTE: I need to try this only with for loop - I know how to do it using array functions.
You should reverse your test, because there are almost always values, which are different from the one you're testing. And you must reset your $flag before the inner loop, otherwise it will always be true.
When you want to find unique values, you can just test against $d only. If the value is already in $d, skip it.
$c1 = count($b);
for ($i = 0; $i < $c1; $i++) {
$dup = 0;
$c2 = count($d);
for ($j = 0; $j < $c2; $j++) {
if ($b[$i] == $d[$j])
$dup = 1;
}
if (!$dup)
$d[] = $b[$i];
}
print_r($d);
If you want to find values, which don't have duplicates instead
for ($i = 0; $i < $c; $i++) {
$dup = 0;
for ($j = 0; $j < $c; $j++) {
if ($i != $j && $b[$i] == $b[$j])
$dup = 1;
}
if (!$dup)
$d[] = $b[$i];
}
function has_dupes($array){
$dupe = array();
foreach($array as $val){
if(++$dupe[$val] > 1)
return true;
}
return false;
}
could do something like this.. this would check for dupes, then u can print the uniques
Why are you making a simple task complex .. simply
$b = array('a','b','c','a','b');
var_dump(customCount($b));
Output
array (size=3)
'a' => int 2 //duplicate
'b' => int 2 //duplicate
'c' => int 1
Function Used
function customCount($array) {
$temp = array();
foreach ( $array as $v ) {
isset($temp[$v]) or $temp[$v] = 0;
$temp[$v] ++;
}
return $temp ;
}
I need some help, even though I think I'm checking for the length of the array and I should be breaking out of the loop, I still get warnings on my [else if ($value....] line. So either I'm missing something crucial or I've been staring at this code segment too long and its obvious. Any insight would be appreciated.
$count = count($filter); //Filter is an array
if ($count > 1 ){
//Compare values and generate a range to choose from
$i = 1;
foreach($filter as $value){
//Break the loop if at the end of the array
if ($i >= $count){
//throw new exception($i .' '.$count);
break;
}
//if the value is smaller then the next procceding value, because they are already in order of presidence,
//add it to our range of potentials.
else if($value < $filter[$i]->value){
array_push($range, key($filter));
}
$i++;
}
}else {
return false;
}
I suspect that there are gaps in your array. Try this:
$filter = array_values($filter); // this will remove any gaps in the array
$count = count($filter);
if ($count <= 1)
return false;
for ($i = 0; $i < $count; $i++)
{
if ($i != $count-1 && $filter[$i]->value < $filter[$i+1]->value)
array_push($range, key($filter));
}
Your array might have non-numeric keys. Then try this:
foreach($filter as $key=>$value)
{
// test for $filter[$key];
}
Or your $filter array doesn't hold objects, then you can't use the -> in
$filter[$key]->value
try this code.... no need of checking count..
$range = array();
$i = 1;
foreach($filter as $value)
{
if(isset($filter[$i]) && $value < $filter[$i]->value)
{
array_push($range, key($filter));
$i++;
}
else
{
break;
}
}