Recursion and factorial of a number in PHP [duplicate] - php

This question already has answers here:
What in layman's terms is a Recursive Function using PHP
(17 answers)
Closed 8 years ago.
<?php
function factorial_of_a($n)
{
if($n ==0)
{
return 1;
}
else
{
return $n * factorial_of_a( $n - 1 );
}
}
print_r( factorial_of_a(5) );
?>
My doubt is:
return $n * factorial_of_a( $n - 1 ) ;
In this statement - it gives a result of 20 when $n = 5 and $n - 1 = 4. But how come the answer 120 when I run it? Well, 120 is the right answer... I don't understand how it works. I used for-loop instead and it was working fine.

factorial_of_a(5)
Triggering following calls:
5 * factorial_of_a(5 - 1) ->
5 * 4 * factorial_of_a(4 - 1) ->
5 * 4 * 3 * factorial_of_a(3 - 1) ->
5 * 4 * 3 * 2 * factorial_of_a(2 - 1) ->
5 * 4 * 3 * 2 * 1 * factorial_of_a(1 - 1) ->
5 * 4 * 3 * 2 * 1 * 1
So, the answer is 120.
Consider reading recursive function article on wikipedia.
Also, read this related thread: What is a RECURSIVE Function in PHP?
but how come the answer 120 ?
Well, this function will call itself with $n - 1, while $n - 1 is not equals to 0. When it is, then function actually returns result to the program. So it is not returning result instantly, while argument in larger then 0. It is called a "terminate condition" of the recursion.

It will work in this way..
- factorial_of_a(5);
// now read below dry run code from the bottom for proper understanding
// and then read again from top
- if n = 0 ; false // since [n = 5]
- else n*factorial_of_a(n-1); [return 5 * 24]
// here it will get 24 from the last line since 4*6 = 24 and pass
// it to the value of n i.e. **5** here will make it **120**
- if n = 0 ; false [n = 4]
- else n*factorial_of_a(n-1); [return 4 * 6]
// here it will get 6 from the last line since 3*2 = 6 and pass it
// to the value of n i.e. **4** here will make it **24**
- if n = 0 ; false [n = 3]
- else n*factorial_of_a(n-1); [return 3 * 2]
// here it will get 2 from the last line since 2*1 = 2 and pass it
// to the value of n i.e. **3** here will make it **6**
- if n = 0 ; false [n = 2]
- else n*factorial_of_a(n-1); [return 2 * 1]
// here it will get 1 from the last line since 1*1 = 1 and pass it
// to the value of n i.e. **2** here
- if n = 0 ; false [n = 1]
- else n*factorial_of_a(n-1); [return 1 * 1]
// here it will get 1 from the last line and pass it
// to the value of n i.e. **1** here
- if n = 0 ; true // since [n = 0] now it will return 1
- return 1;

To understand this you need to be clear with the concept of recursion.
Recursion means calling a function again and again.
Every recursive function has a terminating case and a recursive case.
Terminating case tells when will the function stop and recursive case calls the function itself again.
In your code the if condition $n == 0 marks the terminating case, i.e. do not do any calculation if a number is equal to 0 and return 1.
The else part is the recursive case [ $n*factorial_of_a($n-1) ]
Now i will explain how it works for $n = 5 :
Since $n is not equal to 0 then else statement is executed which gives 5 *factorial_of_a(4);
Now factorial_of_a(4) is called which gives 4 * factorial_of_a(3);
Now factorial_of_a(3) is called which gives 3 * factorial_of_a(2);
Now factorial_of_a(2) is called which gives 2 * factorial_of_a(1);
Now factorial_of_a(1) is called which gives 1 * factorial_of_a(0);
Now factorial_of_a(0) is called which gives 1
So basically
factorial_of_a(5) = 5 * 4 * 3 * 2 * 1 = 120
Hence the result!
Hope it helped!!

You have to bear in mind that his is a recursion
when you call factorial_of_a(5) it will execute this as
factorial_of_a(5)
// 5 * 24
5 * factorial_of_a(4)
// 4 * 6
4 * factorial_of_a(3)
// 3 * 2
3 * factorial_of_a(2)
// 2 * 1
2 * factorial_of_a(1)
//will return 1 since it is your base condition
1 * factorial_of_a(0)

Related

How do the non-base cases work in recursion?

I would like to understand recursion fully. I understand the part where it has to meet the base case (n=0) before returning 1, that part I understand completely. When it meets the base case condition, it returns to the instance that called it which is n=1, that I also understand.
How does it now increment and goes back to n=2, how does the mechanism behind it work to make it go back up to n=5? I guess I am missing something here.
<?php
function factorial( $n ) {
// Base case
if ( $n == 0 ) {
echo "Base case: $n = 0. Returning 1...<br>";
return 1;
}
// Recursion
echo "$n = $n: Computing $n * factorial( " . ($n-1) . " )...<br>";
$result = $n * factorial( $n-1 );
echo "Result of $n * factorial( " . ($n-1) . " ) = $result. Returning $result...<br>";
return $result;
}
echo "The factorial of 5 is: " . factorial( 5 );
?>
This is supposed to be the output
5 = 5: Computing 5 * factorial( 4 )...
4 = 4: Computing 4 * factorial( 3 )...
3 = 3: Computing 3 * factorial( 2 )...
2 = 2: Computing 2 * factorial( 1 )...
1 = 1: Computing 1 * factorial( 0 )...
Base case: 0 = 0. Returning 1...
Result of 1 * factorial( 0 ) = 1. Returning 1...
Result of 2 * factorial( 1 ) = 2. Returning 2...
Result of 3 * factorial( 2 ) = 6. Returning 6...
Result of 4 * factorial( 3 ) = 24. Returning 24...
Result of 5 * factorial( 4 ) = 120. Returning 120...
The factorial of 5 is: 120
All the data related to your function or method when it is called is stored on a stack. So let us say you make a call to your function factorial(5) for value 5. Now when you call your function with parameter 5. It is put onto the stack and the program tries to calculate its value, now while calculating it value your program finds out that its value depends on factorial(5-1) that is 5*factorial(4) so overall computation of calculating factorial(5) is stopped it remains in stack and your program will calculate value of factorial(4) by putting it in stack. In order to determine factorial(4) , your program will need value of factorial(3) and therefore i.e will put onto the stack , So the current stack will look somewhat like [[factorial(5) with all its data] , [factorial(4) with all its data] , [factorial(3) with all its data]] Overall state of the whole function is maintained similarly your program will further put factorial(2) and factorial(1) onto the stack. Now if there will be no base condition then your program will crash due to stackoverflow as your program will keep on filling the stack with other function calls like factorial(0) , factorial(-1) and so on. So we need a base case. So when your program finds the condition where n==0 it gets it value directly as and it stops further pushing other function calls to stack and then it starts processing the current stack so once it gets value of factorial(0) it uses it to calculate value of factorial(1) and pops factorial(1) and all its data from the stack after returning the value of facotrial(1) to factorial(2) (as factorial(1) was called from factorial(2) ) now factorial(2) does the same thing. So finally the stack will pop the elements from it as they were pushed and the final value of your function which you called initially will be calculated i.e. factorial(5) .

Bit integer value from numerated list

How would one get the integer value of the n-th value from n?
This is hard to phrase so I'll just use English. If I wanted the 3rd integer value from 1...
1 = 1
2 = 3
3 = 4 <- (looking to get 4 using 3)
4 = 8
5 = 16 <- (or 16 using 5)
...
I could just do a lookup table, but I'm sure there's a better solution.
$bitvalue = 5;
$intvalue = 2 ** ($bitvalue - 1);
// gives 16
echo $intvalue;
The ** operator is the power operator. So I'm using powers of 2.

Elegant solution to reordering a Laravel Collection (or populate it perfectly from the beginning)?

I have a Laravel Collection with items in it. Assuming the items are in the collection in numerical order.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
If for example I have items 1-15 laid out like the following in the View (the number of rows can change but number of columns will always stay the same):
1 4 7 10 13
2 5 8 11 14
3 6 9 12 15
*think of each column as a different type of mammal (cats, dogs, birds, etc.)
Is there a way to easily reorder the items like the following within the Collection?
1 4 7 10 13 2 5 8 11 14 3 6 9 12 15
So in the View it would now look like this:
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
*The View that I talk about is for illustrative purposes only. I only require changes to the Collection in the manner stated above. Populating the collection perfectly from the beginning would be the optimal answer but I can't figure out a way to do so.
I don't think it is perfect but it works.
This code assumes $collection is the collection you want to reorder
$arrayCollection = array();
$numberOfColumns = 5; // adjust this value to change number of columns
$numberOfRows = $collection->count() / $numberOfColumns
foreach($collection as $index => $model){
$column = floor($index / $numberOfRows);
$newIndex = (int)($index % $numberOfRows) * $numberOfColumns + $column;
$arrayCollection[$newIndex] = $model;
}
ksort($arrayCollection); // sort collection by key
$collection = new Collection($arrayCollection); // make new collection with reordered models
Why should you reorder the collection? Sounds to me you want something like this:
#foreach($collection as $item)
<div class="collection-item">{{ $item->value }}</div>
#endforeach
Then apply CSS styles in order to have each of the collection-item divs display inline rather than as block elements.
If you truly want a reordered collection, then specify the order you want when you fill the collection:
Model::all()->orderBy('field', 'desc')->get();
While not discussing whether it makes sense to order the collection or better do it in your SQL query, this is the answer for your generic question (adjust for your specific needs if necessary):
1 compare function:
/**
* Sort the array in groups.
*
* #param mixed $previous
* #param mixed $next
* #param integer $groups
* #return bool
*/
function sortInGroups($previous, $next, $groups = 3)
{
// If equal then return 0
if ($previous == $next) return 0;
// Otherwise check the modulus in order to
// group the items. However if modulus is zero,
// then shift group to the very end of final array.
$prev = ($previous%$groups) ?: $groups;
$nxt = ($next%$groups) ?: $groups;
// If moduli are equal then items are
// in the same group so compare the items.
if ($prev == $nxt)
{
return ($previous < $next) ? -1 : 1;
}
// Otherwise compare the moduli in order to group the items.
return ($prev < $nxt) ? -1 : 1;
}
2 sort the collection by whatever property you want (id for example):
$collection = SomeModel::take(15)->get(); // or Support\Collection
$collection->lists('id'); // [1,2,3,4,... 15]
$collection->sort(function ($prev, $next) {
return sortInGroups($prev->id, $next->id, $cols = 5);
});
$collection->lists('id'); // [1,4,7,10,13,2,5,8,11,14,3,6,9,12,15]
You can manually order by a column.
If these are the id 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Then you can use order by FIELD(id, 1, 4, 7, 10, 13, 2, 5, 8, 11, 14, 3, 6, 9, 12, 15);

Math returns wrong answers [duplicate]

This question already has answers here:
Random Float between 0 and 1 in PHP
(13 answers)
Closed 8 years ago.
I've been trying to get this work for almost an hour now, and it's constantly eluding me.
public static function npcBattleStats($npc) {
$npc = self::findNPC($npc);
$rand = mt_rand(1.2, 3.3);
$npcStats['attack'] = (($npc['level'] * $npc['power']) / $rand);
$npcSpeeda = round($npc['power'] / 2.4);
$npcSpeedb = round(($npc['power'] / 1.1) + 2);
$npcStats['speed'] = mt_rand($npcSpeeda, $npcSpeedb);
return $npcStats;
}
level = 3 | power = 50
$npcStats['attack'] = (($npc['level'] * $npc['power']) / $rand);
Everything else seems to work properly, but the attack is constantly off. It should be between 45 and 115 but only returns the following.
[attack] => 50 | [attack] => 150 | [attack] => 75
I hope I'm not missing something simple here, but help would be greatly appreciated.
It seems that the Funktion mt_rand() only spits aut integers, not floats. Try this instead:
$rand = mt_rand(12, 33) / 10;
First of all as cHao mentioned
PHP manual: "Return value: A random integer value between min (or 0) and max (or mt_getrandmax(), inclusive), or FALSE if max is less than min."
To get it fixed you need something like this
$rand = mt_rand(35, 100) / 10;
//35 is your max
//120 is your low
So when You get:
your max:
(5 * 50) / 3.5 = 42.85.. //so round it
your low:
(5 * 50) / 10 = 15

bad value in calculation output

The following code outputs "3". I was expecting "1".
echo $resultado."\n"; // show 2
$valor = $resultado * ($resultado - 1 / 2);
echo $valor."\n"; // show 3, and should be 1
Why does this happen?
Because the division 1 / 2 takes precedence in the order of operations. So you have really have this expression:
$resultado * ($resaltudo - (1 / 2))
You should add parenthesis to be:
$resultado * (($resaltudo - 1) / 2)
to get the answer you want.
No, you're wrong. The / has priority on - and so your line is like:
$valor = $resultado * ($resultado - (1 / 2));
and that is:
$valor = 2 * (2 - 0.5); // and so $valor = 3
That's because the division operator (/) has a higher precedence than the subtraction operator (-).
Your expression becomes, in order:
1 / 2 = 0.5 // Executed first since it's the highest precedence operation inside ()
$resultado - 0.5 = 1.5 // Still in the ()
$resultado * 1.5 = 3 // Final result
To correct your expression, insert parethesis around the subtraction, like this:
$resultado * (($resultado - 1) / 2);
The / takes precedence over + or -
To get 1 as a result you need to use
$resultado * (($resultado - 1) / 2)
Replacing $resultado in the expression, you get:
$valor = 2 * (2 - 1 / 2);
2 - 1 / 2 = 1.5
2 * 1.5 = 3
My suggestion is review basic math ;)
Change it to:
echo $resultado."\n";
$valor = $resultado * (($resultado - 1) / 2);
echo $valor."\n";
You were effectively doing 2 * (2 - (1 / 2) = 2 * 1.5 = 3
2*(2-1/2)
The dividing operator has higher order operator precedence than the minus sign, so the computer will calculate it like this:
2*(2-(1/2)) = 2 * 1.5 = 3
Use parentheses liberally.

Categories