I'm having trouble understanding how the foreach loop works in this code. My understanding is that $Score is assigned the arrays of $Die1 + $Die2, but how does $Score gain the value of 1,2,3,4,5,6,5,4,3,2,1? Shouldn't it be 1,2,3,4,5,6,1,2,3,4,5,6 in a sequence since that's how the values are listed in the $FaceValues array? Is there something that's happening in the foreach statements that I'm missing? Can anyone could elaborate on the double foreach statements here?
$FaceValues = array(1, 2, 3, 4, 5, 6);
$ScoreCount = array();
for($PossibleRolls = 2; $PossibleRolls <= 12; ++$PossibleRolls){
$ScoreCount[$PossibleRolls] = 0;
}
foreach ($FaceValues as $Die1) {
foreach ($FaceValues as $Die2) {
// all possible combinations
++$RollCount;
// increment RollCount
$Score = $Die1 + $Die2;
// 1,2,3,4,5,6
// 6,5,4,3,2,1
++$ScoreCount[$Score];
}
}
foreach ($ScoreCount as $ScoreValue => $ScoreTimes){
echo "<p> A combined value of $ScoreValue occured $ScoreTimes of $RollCount times. </p>";
}
On the first iteration $Die1 is 1 and $Die2 is 2. So it begins at 2 and goes up to 7. Then the inner loop is finished and the outer loop proceeds to set $Die1 to 2. You should then see the number 3 through 8.
You can use echo or var_dump() and exit() to print the values at each step and stop if you're having trouble following-along.
Related
I have a task (or more like a challenge) found on Code-Signal (a site where do you can do some programming-related tasks. This special task was asked by google in an interview:
If you want to try it for yourself: Code-Fight.
After solving an issue, you are allowed to see other solutions.
My task was "find the first dupe in an array". I managed to do this (i'll show the way), but I'm not happy with my result. After investigating the top-solutions, I was confused, since I don't understand whats going on there.
This was (a) given example input array
$a = [2, 1, 3, 5, 3, 2]
My solution:
function firstDuplicate($a) {
$onlyDupesArray= array();
$countedValues = array_count_values($a);
// remove all entries which are only once in the array
foreach($a as $k => $v) {
if($countedValues[$v] > 1) {
$onlyDupesArray[$v] = $v;
}
}
// get rid of dupes
$uniqueDupesArray = array_unique($onlyDupesArray);
$firstEncounter = PHP_INT_MAX;
foreach($uniqueDupesArray as $k => $v) {
if(array_keys($a, $v)[1] < $firstEncounter) {
$firstEncounter = array_keys($a, $v)[1];
}
}
if(is_null($a[$firstEncounter])) {
return -1;
} else {
return $a[$firstEncounter];
}
}
It works in every test-case and I solved the challenge. However, the top-solution was this:
function firstDuplicate($a) {
foreach ($a as $v)
if ($$v++) return $v;
return -1;
}
I know what a variable variable is, but haven't seen this in the wild-life yet until now.
What does the references variable do here? How is this returning a dupe? Does it somehow compare if there is already a value for a key with this typing? Does $$v++ reference a key in an array?
Needlessly to say, I like this approach muche more. It seems way more efficient and better to maintain.
Is this "common practice"?
It is creating numbered variables. $2, $1, $3 etc.
$v in the foreach contains the current number, 2. By doing $test = 2; echo $$test we can see what is in $2 right now. It is normally empty. Now, by doing $$v++, it will return the current value (empty, or actually, variable does not exist), but ++ will put '1' in it. The whole statement itself will return 0, since ++ is not in front of the variable.
Consider this code:
$arr = [2, 1, 3, 5, 3, 2];
foreach($arr as $v)
{
$$v++;
}
$test = 3;
echo $$test;
It will show that the value of $3 equals 2, because we did 2 times ++ on $3.
The only reason this is weird is that normally you can't use variables starting with numbers. Maybe this makes it clearer?:
$arr = [2, 1, 3, 5, 3, 2];
foreach($arr as $v)
{
$v='a'.$v;
$$v++;
}
echo "a3 = $a3\n"; // 2
echo "a2 = $a2\n"; // 2
echo "a1 = $a1\n"; // 1
echo "a5 = $a5\n"; // 1
To answer the question "Is this "common practice"?". No, I would personally not use variable variables, as this can in some cases been considered as a security problem. I personally like the following solution better, which is the same, but uses an array, and does not throw notices:
function firstDuplicate($a) {
$arr = [];
foreach ($a as $v)
if (in_array($v, $arr))
return $v;
else
$arr[] = $v;
return -1;
}
The variable variables solution is a creative one, though!
By specifying your variable with an additional $ (variables variable) PHP creates a "hidden/fake array".
While running each index gets filled with a "0":
After the first run you got something like
$array[2] = 0;
After the next run the index 1 gets filled:
$array[1] = 0;
$array[2] = 0;
Since a "0" is treated as false, your condition becomes valid after the first duplicate (3):
$array[1] = 0;
$array[2] = 0;
$array[3] = 1; // <-- TRUE
$array[5] = 0;
I am trying to change multidimensional array index in running foreach:
$array = array(
array("apple", "orange"),
array("carrot", "potato")
);
$counter = 0;
foreach($array[$counter] as &$item) {
echo $item . " - ";
$counter = 1;
}
I supposed, that output would be apple - carrot - potato -, because in first run it takes value from zero array and then in next runs values from first array.
However, the output is apple - orange -
I tried add "&" before variable $item, but i guess it is not what I am looking for.
Is there any way to do it?
Thank you
// Well, i will try to make it cleaner:
This foreach takes values from $array[0], but in run i want to change index to 1, so in next repeat it will take values from $array[1]
Is that clear enough?
Note: I do not know how many dimensions my array has.
My purpose of this is not to solve this exact case, all I need to know is if is it possible to change source of foreach loop in run:
My foreach
$counter = 0;
foreach($array[$counter] as $item) {
echo $item . " - ";
}
is getting values from $array[0] right now. But inside it, I want to change $counter to 1, so next time it repeats, it will get values from $array[1]
$counter = 0;
foreach($array[$counter] as $item) {
echo $item . " - ";
$counter = 1;
}
I see, it is kind of hard to explain. This is how foreach should work:
Index of $array is $counter
First run
$array[0] -> as $item = apple
echo apple
wait, now counter changes to 1
Second run
$array[1] -> as $item = carrot
echo carrot
Third run
$array[1] -> as $item = potato
echo potato
END
I am really trying to make it clear as much as possible :D
When foreach first starts executing, the internal array pointer is automatically reset to the first element of the array. Now, by changing counter, you are changing the array (the inside one), but it is set to the first array again.
Changing the array in between may result in unexpected behaviour.
Source: Foreach: PHP.net
So finally, I found a time for this, and this is how you can change index of source array in running loop.
Thanks to you, I realized, that i can not do this by foreach, but there are many other loops.
If you were facing the same problem, here is my solution:
$array = array(
array("apple", "orange"),
array("carrot", "potato")
);
$counter = 0;
$x = 0;
while($x < count($array[$counter])) {
echo $array[$counter][$x] . " - ";
$x++;
if($counter == 0) {
$x = 0;
$counter = 1;
}
}
And the output is: apple - carrot - potato - as I wanted to achieve.
i want to calculate two operations with the help of loop. They are already working and providing result i need. But i want them to look more like coding. So if anybody can help them with the help of for in php
for($i=0;i<something;$i++){
$temp_calc = ;
}
here are two statements.
In first statement length of array is 9.
In second statement length of array is 12.
both statements to be solved in different for loop as they are totally different questions.
$temp_calc = 10*$temp_array[0]+9*$temp_array[1]+8*$temp_array[2]+7*$temp_array[3]+6*$temp_array[4]+5*$temp_array[5]+4*$temp_array[6]+3*$temp_array[7]+2*$temp_array[8];
$temp_calc = 1*$temp_array[0]+3*$temp_array[1]+1*$temp_array[2]+3*$temp_array[3]+1*$temp_array[4]+3*$temp_array[5]+1*$temp_array[6]+3*$temp_array[7]+1*$temp_array[8]+3*$temp_array[9]+1*$temp_array[10]+3*$temp_array[11];
Thanks in advance
It will be a little simpler to use a foreach loop rather than a for loop. If you specifically need to use a for loop because it is a requirement of an assignment, you can check the PHP documentation. There are some examples there of using a for loop to loop over an array. This is a common and basic control structure and it will be more valuable for you to really understand how to use it. The more important part is what goes on inside the loop. There are multiple ways to do this, but here are some basic examples.
First one:
// initialize multiplier and result outside the loop
$multiplier = 10;
$result = 0;
// loop over the values
foreach ($temp_array as $value) {
// add the value * multiplier to the result and decrement the multiplier
$result += $value * $multiplier--;
}
Second one
// initialize multiplier and result outside the loop
$multiplier = 1;
$result = 0;
// loop over the values
foreach ($temp_array as $value) {
// add the value * multiplier to the result
$result += $value * $multiplier;
// switch the multiplier to the alternating value
if ($multiplier == 1) {
$multiplier = 3;
} else {
$multiplier = 1;
}
// The switch can be done more simply using a ternary operator like this:
// $multiplier = $multiplier == 1 ? 3 : 1;
}
for both issues:
$temp_array = array(2,2,2,2,2,2,2,2,2);//sample
function calc_1($temp_array){//first
$total=0;
$count = count($temp_array)+1;
foreach($temp_array as $value){
$total += $count*$value;
$count-=1;
}
return $total;
}
function calc_2($temp_array){//second
$total=0;
foreach($temp_array as $k=>$value){
$total += ($k%2==0) ? 1*$value : 3*$value;//when is even or odd
}
return $total;
}
var_dump(calc_1($temp_array));//resp1
var_dump(calc_2($temp_array));//resp2
If your array is called $myArray, then:
/*Since I can't know what the sequence of the values are that you
are multiplying, and because you might need other sequences in the
future, a function was developed that chooses which sequence you
want to multiply.*/
function findSomeValues($arraySize)
{
switch ($arraySize) {
case 9:
{
$someValues = array(10,9,8,7,4,5,4,3,2);
}
break;
case 12:
{
$someValues = array(1,3,1,3,1,3,1,3,1,3,1,3);
}
break;
default:
$someValues = array();
}
return $someValues;
}
/*This following function then finds how big your array is, looks
for a sequence stored in the findSomeValues function. If a sequence
exist for that array size (in this case if you have an array either
9 or 12 elements long), the result will be calculated and echoed. If
the sequence was not found, an error message would be echoed.*/
function multiplyValues($myArray) {
$result = 0;
$arraySize = count($myArray);//obtaining array size
$someValues = findSomeValues($arraySize);//obtaining sequence to multiply with
if (count($someValues)>0)
{
for($i=0;i<$arraySize;$i++){
$result += $myArray[i]*$someValues[i];
}
echo "result = ".$result."<br>";//result message
}
else
{
echo "you are missing some values<br>";//error message
}
}
Let me know if that worked for you.
Alternative:
If you prefer something a bit simpler:
//this array holds the sequences you have saved:
$sequenceArray = array(
9 => array(10,9,8,7,4,5,4,3,2),
12 => array(1,3,1,3,1,3,1,3,1,3,1,3)
);
//this function does the multiplication:
function multiplyValues($myArray)
{
$arraySize = count($myArray);
for($i=0;i<$arraySize;$i++){
$result += $myArray[i]*$sequenceArray[i];
}
echo "result = ".$result."<br>";//result message
}
For your result
$temp_calc = 10*$temp_array[0]+9*$temp_array[1]+8*$temp_array[2]+7*$temp_array[3]+6*$temp_array[4]+5*$temp_array[5]+4*$temp_array[6]+3*$temp_array[7]+2*$temp_array[8];
You should have for loop as following. It will run the loop till 8th index of your temp_array and multiply each index value with $i and sum up in a variable $temp_calc_1.
<?php
$temp_calc_1 = 0;
for($i=0;$i<9;$i++){
$temp_calc_1 = $temp_calc_1 + ( 10-$i)*$temp_array[$i] ;
}
For your second result
$temp_calc = 1*$temp_array[0]+3*$temp_array[1]+1*$temp_array[2]+3*$temp_array[3]+1*$temp_array[4]+3*$temp_array[5]+1*$temp_array[6]+3*$temp_array[7]+1*$temp_array[8]+3*$temp_array[9]+1*$temp_array[10]+3*$temp_array[11];
The above should be converted to the following loop, this will run loop till your 12th index of temparrayand do the calculation. This time it will multiply each index value of temparray by either 1 and 3. So first time it will multiply with 1 and next time with 3 and so on
//
$temp_calc_2 = 0;
for($i=0;$i<12;$i++){
$j = $i%2?3:1;
$temp_calc_2 = $temp_calc_2 + $j*$temp_array[$i] ;
}
?>
I have a php array $numbers = array(1,2,3,4,5,6,7,8,9)
if I am looping over it using a foreach foreach($numbers as $number)
and have an if statement if($number == 4)
what would the line of code be after that that would skip anything after that line and start the loop at 5? break, return, exit?
You are looking for the continue statement. Also useful is break which will exit the loop completely. Both statements work with all variations of loop, ie. for, foreach and while.
$numbers = array( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
foreach( $numbers as $number ) {
if ( $number == 4 ) { continue; }
// ... snip
}
continue;
Continue will tell it to skip the current iteration block, but continue on with the rest of the loop. Works in all scenerios (for, while, etc.)
Break; will stop the loop and make compiler out side the loop. while continue; will just skip current one and go to next cycle.
like:
$i = 0;
while ($i++)
{
if ($i == 3)
{
continue;
}
if ($i == 5)
{
break;
}
echo $i . "\n";
}
Output:
1
2
4
6 <- this won't happen
I suppose you are looking for continue statement. Have a look at http://php.net/manual/en/control-structures.continue.php
dinel
problem Solved..... thanks alot
I want to break the loop and continue loop from the point that the loop stop. E.g., if I have array like this:
$arr = array('1', '2', '3', '4', '5');
I want to stop looping on number '3' and take an action and continue from '4'. I tried this code:
$x = 0;
foreach($arr as $key){
if($x == 3) break; // here I stop loop in number 3
echo $key;
$x++;
// I want to continue loop from 4
}
why stop?
use
$x = 0;
foreach($arr as $key){
if($x == 3)
doSomething();
else
echo $key;
$x++;
}
it will continue with iteration 4, after "doing Something". (Correctly spoken: It will iterate from 1 to n, and only perform an action, when $x==3, otherwhise print the key.)
If you just want to avoid key "3" beeing printed, you can use the continue statement:
$x = 0;
foreach($arr as $key){
if($x++ == 3)
continue; //proceed with next iteration
echo $key;
}
but then you need to use $x++ in your comparrision, otherwhise it will get stuck at $x==3, cause the increment will always be skipped.
Sidenode: If you NEED $x to be the correct line number, use a for() instead of foreach() - use foreach(), if you dont care about the actual line number, but need to process ALL entries within an array.
Sidenode 2: foreach($arr as $key) is wrong. This expression will give you the value for each array entry, not the key. use foreach($arr as $key=>$value) or foreach($arr as $value) to have a correct name on the variable(s).