I have the array:
$array = array(1,1,5,2,3,3,3,3);
I need to find a way to count the amount of times a number is repeated at the end of the array. In this case the number 3 is repeated 4 times.
And if...:
$array = array(1,1,5,2,3,3,3,3,4);
In this case, the result would be 1 because the number 4 only appears once.
Thank you for the help.
Try this: (working example)
$array = array(1,1,5,2,3,3,3,3);
$num = end($array); // this will be 3 - the value to compare to
$count = 0; // init count
for($i = sizeof($array)-1; $i>=0;$i--) // loop from the end backwards
if($array[$i]==$num) // if this is the correct num
$count++; // increase count
else
break; // end loop - not side by side anymore - no reason to keep looping
echo $count; // print the result
Related
I want to print an array in spiral order. For arrays with sizes 3x3, 4x4, ...etc. my code works correctly, but for 3x5, 4x6 or 5x8 sizes the output is wrong, returning only the first iteration.
This is my simple code:
private function _spiral($rows, $cols, array $array) {
$offset = 0;
while($offset < ($rows - 1)){
for($col = $offset; $col <= $cols - 1; $col++){
print($array[$offset][$col] . ' ');
}
$offset++;
$cols--;
for($row = $offset; $row < $rows; $row++){
print($array[$row][$cols] . ' ');
}
$rows--;
for($col = $cols - 1; $col >= $offset; $col--){
print($array[$rows][$col] . ' ');
}
for($row = $rows; $row >= $offset; $row--){
print($array[$row][$offset - 1] . ' ');
}
}
}
Example with 3 rows and 4 columns:
$array = array(
array(00,01,02,03),
array(10,11,12,13),
array(20,21,22,23)
)
Expected result for this array is 0 1 2 3 13 23 22 21 20 10 11 12, but the output of my function stops after 10.
For 4 rows and 4 columns:
$array = array(
array(00,01,02,03),
array(10,11,12,13),
array(20,21,22,23),
array(30,31,32,33)
)
...it should return 0 1 2 3 13 23 33 32 31 30 20 10 11 12 22 21, and that is what my code returns.
But I want both cases to work with my code. How can I correct the code to also produce the correct output for the first, and other cases?
There are a few problems with your code:
it does not treat the four directions of traversal in the same way. You have four loops for these four directions, but in some you have <= as loop-end condition in others <, in some the condition is on something minus 1, in others not.
it has no provision for when all elements have been printed by the first or second inner loop, and thus the remaining loops will in some cases print already printed elements.
the outer loop condition does not check whether there are still columns that need traversal. It is not enough to test for such rows only.
Although you could try to fix your code, I think it is better to start from scratch, taking into account that the solution should be symmetric for all four directions. This is an important intuitive reaction to develop: spot symmetries. This will lead to less code and fewer bugs.
You want to traverse a dimension (row or column) in your array until you reach the border of the array or an element you already printed. Then you want to turn 90° to the right and repeat exactly the same logic over and over again. So if your code looks different for these different directions, something is not right.
I will share two implementations. Both will use the concept of the "current" cell, and let it move around in spiral motion.
The first solution treats going back or forward along a row with the same code, and similarly it has one piece of code for traversing a column forward or backward. So this solution has two inner loops, one for traversing along a row, and another for traversing along a column. The direction in which a row or column is traversed is kept in the $direction variable, which flips between 1 and -1 at each execution of the outer loop:
function _spiral(array $array) {
// No need to have the number of rows and columns passed as arguments:
// We can get that information from the array:
$rows = count($array);
$cols = count($array[0]);
// Set "current" cell to be outside array: it moves into it in first inner loop
$row = 0;
$col = -1;
$direction = 1; // Can be 1 for forward and -1 for backward
while ($rows > 0 and $cols > 0) {
// Print cells along one row
for ($step = 0; $step < $cols; $step++) {
$col += $direction;
print $array[$row][$col] . ' ';
}
// As we have printed a row, we have fewer rows left to print from:
$rows--;
// Print cells along one column
for ($step = 0; $step < $rows; $step++) {
$row += $direction;
print $array[$row][$col] . ' ';
}
// As we have printed a column, we have fewer columns left to print from:
$cols--;
// Now flip the direction between forward and backward
$direction = -$direction;
}
}
Note the perfect symmetry between the first inner loop and the second inner loop.
In a second solution, this use of symmetry is taken one step further, in order to replace the two inner loops with only one. For that to happen we must abandon the use of separate variables for rows and columns, and use the concept of a size related to a dimension:
function _spiral(array $array) {
// This version of the function aims to treat rows and columns in the same way,
// They are just another dimension, but all the logic is exactly the same:
// $size[] has the number of rows in $size[0] and number of columns in $size[1]
$size = Array(count($array), count($array[0]));
// $current[] has the current row in $current[0] and current column in $current[1]
$current = Array(0, -1);
// $direction[] has the current row-traversal direction in $direction[0]
// and column-traveral direction in $direction[1]
$direction = Array(1, 1);
$dimension = 0; // Which dimension to traverse along, can be 0 for row, 1 for column
while ($size[$dimension] > 0) {
// Switch dimension (row to column, column to row), to traverse along
$dimension = 1 - $dimension;
// Print one line along that dimension, in its current direction
for ($step = 0; $step < $size[$dimension]; $step++) {
$current[$dimension] += $direction[$dimension];
print $array[$current[0]][$current[1]] . ' ';
}
// As we have printed a line, we have fewer left to print from:
$size[1 - $dimension]--;
// Now flip the direction between forward and backward for this dimension:
$direction[$dimension] = -$direction[$dimension];
}
}
An extended version
Upon request more than one year later: here is a version that allows one to choose the corner to start from, and whether to do it counter-clockwise instead of clockwise. This function will not print the result, but return a 1D array, with the spiral sequence. This way you can decide yourself what to do with the result: print it, or ... whatever.
function spiral(array $array, $startRight = false, $startBottom = false,
$counterClockWise = false) {
// This version allows to select which corner to start from, and in which direction.
// $size[] has the number of rows in $size[0] and number of columns in $size[1]
$size = [count($array), count($array[0])];
// $direction[] has the current row-traversal direction in $direction[0]
// and column-traversal direction in $direction[1]
$direction = [$startBottom ? -1 : 1, $startRight ? -1 : 1];
// Which dimension to traverse along: false means row, true means column.
// Every one of the optional arguments will flip the first dimension to use:
$dimension = ($startBottom xor $startRight xor $counterClockWise);
// $current[] has the current row in $current[0] and current column in $current[1]
$current = [$startBottom * (count($array)-1), $startRight * (count($array[0])-1)];
// Go back one step, outside of the grid
$current[!$dimension] -= $direction[!$dimension];
while ($size[$dimension] > 0) {
// Switch dimension (row to column, column to row), to traverse along
$dimension = !$dimension;
// Print one line along that dimension, in its current direction
for ($step = 0; $step < $size[$dimension]; $step++) {
$current[$dimension] += $direction[$dimension];
$result[] = $array[$current[0]][$current[1]]; // store in new array
}
// As we have printed a line, we have fewer left to print from:
$size[!$dimension]--;
// Now flip the direction between forward and backward for this dimension:
$direction[$dimension] = -$direction[$dimension];
}
return $result; // Return the resulting spiral as a 1D array
}
See it run on eval.in
First of all, I apologize for my lack of English. I hope you do understand what I'm trying to explain here.
So basically I need to build a function that would limit the number of duplicate values inside an array.
The reason I need to do this is that I'm building a system that would divide numbers into groups and every group has to have the same amount of numbers.
EDIT: Random number represents the group number.
I've written a function do this but for some reason, it is not working properly.
function jagaTiimid($max, $liiget, $tArvLength, $tArv){
$tiimid = []; //Starting array
for($z=0;$z<$liiget;$z++){
$numbers = [];
$rn = randomNumber($tArvLength, $tArv, $numbers); //Generate a random number for a group, etc group 1, group 2, group 3
$mitu = countInArray($tiimid, $rn); //Check how many times that number has occured in array
if($mitu == $max){ //If it equals to maximum number of times then...
$rnUus = randomNumber($tArvLength, $tArv, $numbers); //generate a new random number
while($rnUus == $rn){
$numbers = [];
$rnUus = randomNumber($tArvLength, $tArv, $numbers);
} //loop until the new generated number doesn't equal to old rn.
$tiimid[] = $rnUus; //if it doesn't equal to $rn then push into array
}else{
$tiimid[] = $rn;
}
}
return $tiimid;
}
For some reason the number still occures more than it is suppose to.
Basically how it shouldn't end up is.
As you can see, one group(group 2) occurs more times than other group but it should be equal for both groups.
EDIT: CountInArray();
function countInArray($array, $what) {
$count = 0;
for ($i = 0; $i < count($array); $i++) {
if ($array[$i] === $what) {
$count++;
}
}
return $count;
}
When the first random pick hits a number that is already used $liiget times, the inner loop kicks in, but it does not check whether the newly generated random number already occurs $liiget times.
For efficiency I would keep track of the number of times a number has been used. Also, you could benefit from a safety net, in case there really is no number any more that would not exceed the maximum recurrence.
It is not necessary to have a nested loop. The code would look like this:
function jagaTiimid($max, $liiget, $tArvLength, $tArv){
$tiimid = []; //Starting array
$counts = []; // Helper for quick count
$tries = 0; // Counter to avoid infinite looping
while (count($tiimid) < $liiget && $tries++ < 100) {
$numbers = [];
$rn = randomNumber($tArvLength, $tArv, $numbers); //Generate a random number for a group, etc group 1, group 2, group 3
if (!isset($counts[$rn])) $counts[$rn] = 0; // initialise on first occurence
if ($counts[$rn] < $max) {
$tiimid[] = $rn; // add it to the result
$counts[$rn]++; // ... and adjust the count
$tries = 0; // reset the safety
}
}
return $tiimid;
}
replace while($rnUus == $rn) with while(countInArray($tiimid, $rnUus) >= $max)
– Ilya Bursov
I did some research, but didn't found any solution for my question.
What I want to archive:
Generate a random number out of 0's ($min) and 1's ($max), but with a fixed amount ($many) of 1's in the random number. The random number should have a length of 6 as in my while loop (while($xLoop <= 6)).
Here is my current code:
$min = 0;
$max = 1;
$many = 3;
$xLoop = 1;
while($xLoop <= 6) {
$nRand = mt_rand($min,$max);
if($nRand == 1){ //if random number comes out number 1
$many--; // Prevent number 1 more then $many...
//Do something...
}else{ //if random number comes out not number 1
//Do something and still looping until get 6 times
}
echo $nRand.' - '.$many.'</br>'; //For debugin... i want to see how many number 1 comes out.
$xLoop++;
}
It will loop 6 times, so we have a random number of the length 6, but I want a fixed amount of 1's in my random number, which is $many (here 3). And the rest filled with 0's until we reach the length 6.
How can I fix this code? Or is there a simpler way?
This should work for you:
No need for a loop. Just first fill an array with 1's $many times. Then array_merge() the array with the 0's which you fill up until $length elements.
At the end just shuffle() the array and implode() it to print it
<?php
$min = 0;
$max = 1;
$many = 3;
$length = 6;
$arr = array_fill(0, $many, $min);
$arr = array_merge($arr, array_fill($many, $length-$many, $max));
shuffle($arr);
echo implode("", $arr);
?>
possible output:
011010
How do you calculate (sum) + a value in foreach loop?
I am working on a cricket application where i have to count the loop for each 6 times and then count specific value and then echo the total.
I have a code not exact but something like this.
And there are two values:
Balls $balls['1']; array like 1,2,3,4,5 and up to 300-1000 balls
Runs $balls['6']; array like 2,3,1,5 random numbers could be any;
Values comes from mysql table columns balls and runs
foreach( $balls as $ball ){
$countball++;
// here is what i need to know how do i calculate the values of $ball + $ball?
// so i can echo it inside the below if condition?
$runs = $ball['runs'] + $ball['runs']; // not working
if($countball == 6){
echo $runs;
}
$runs+= $ball; // reset the ball counting to continue addition from loop?
// and reset the
}// end foreach
however something like this works fine for the first $countball == 6. but after that it does not show the exact value
You forget to reset the $countball.
You may change the if part as :
if($countball == 6)
{
echo $runs;
$countball = 0;
}
Maybe this is what you need:
$runs = 0;
foreach( $balls as $ball ){
$runs += $ball['runs'];
}
echo $runs;
With help of #Barmar from above i got the desired output as followings
$runs = 0;
$countball=0;
foreach( $balls as $ball ){
$countball++;
$runs += $ball['runs'];
if($countball == 6){
// reset runs from current loop runs for next, if i reset $runs = 0
// for some reason it does not (SUM) + this loops $ball['runs'] with last 5;
$runs = $ball['runs'];
$countball=0;
}// end if $countball == 6
}// end foreach
echo $runs;
This is what my code does:
it gets 4 rows from my table, stores them in an array, repeats them untill they reach 20 inside that array then echo's them whit a foreach loop... problem is i get an empty result at the end of each foreach cycle of the 4 results.
$result = mysql_query("SELECT * FROM ".$table."");
$row_nr = mysql_num_rows($result); // Find out how many rows I have in the table, lets say 4
while($rows = mysql_fetch_assoc($result)){
$arrayrows[] = $rows; // Put my 4 rows in the array
}
// Now I multiply nr. of rows to reach desired number which is 20
$dbRow=0;
for($n=0; $n <= 20; $n++)
{
if($dbRow > $row_nr) $dbRow = 0;
$fullarrayrows[$n] = $arrayrows[$dbRow];
$dbRow++;
}
// after some php pagination code I slice the array:
$arrayslice = array_slice($fullarrayrows, $offset, $rowsperpage);
// Now i display my array
foreach($arrayslice as $slice)
{
echo ''.$slice['name'].'';
echo '<br />';
}
Problem is I get some empty records in the foreach
name1name2name3name4HERE I GET THE EMPTY ENTRYname1name2name3name4AGAIN I GET THE EMPTY ENTRY
... and so on, at the end of each cycle
Thank you very much , please give me an ideea of what's wrong:)
$dbRow indexes start at 0 and end at 3
but $row_nr equals 4
so change this line
if($dbRow > $row_nr) $dbRow = 0;
to
if($dbRow >= $row_nr) $dbRow = 0;