PHP - calculation between two arrays - keys & values - php

Scenario of Web Game. We have two connected buildings. The second one is something like upgrade but not exactly, never mind this is not important.
Every building have experience level and this level its dependеnt of produced materials from the building. When we produce materials we have calculation between levels of the buildings.
Example: we produce 2000 gold, every building produce the gold like:
Building B level - Building A level x Produced Gold
notes:
Always Building B(Upgrade building) have bigger priority so its: level B - level A x Gold
Always the produced gold is the same on both buildings
$building_A = array(4=>2000);
$building_B = array(5=>2000);
Building A Level 4 -> 2000 Gold
Building B Level 5 -> 2000 Gold
Calculation is : 5 - 4 x 2000 gold = 1 x 2000
Variant 0.1:
Its possible Base building to Level UP and second building to be the same level:
Array:
$buildingA = array(4=>1000, 5=>1000);
$buildingB = array(5=>2000);
Building А
Level 4: 1000 gold
Level 5: 1000 gold
Building B:
level 5: 2000 gold
Calculation:
5 - 4 x 1000 = 1 x 1000
5 - 5 x 1000 = 0 x 1000
Variant 0.2:
Its possible and opposite situation:
Array:
$buildingA = array(4=>2000);
$buildingB = array(4=>700,5=>1300);
Building A:
Level 4 : 2000 Gold
Building B:
Level 5 : 700 Gold
Level 6 : 1300 Gold
Calculation:
5-4 x 700 = 1 x 700
6-4 x 1300 = 1 x 1300
Here is the code of variants 0.1 & 0.2
http://sandbox.onlinephpfunctions.com/code/ef0adce304554392266b8193b292051c0d98bae8
//v.01
$buildingA = array(4=>1000, 5=>1000);
$buildingB = array(5=>2000);
//v.02
//$buildingA = array(4=>2000);
//$buildingB = array(4=>700,5=>1300);
if(sizeof($buildingB) == 1)
{
foreach($buildingA as $level_a => $gold)
{
$level_b = array_keys($buildingB);
$level_b = $level_b[0];
$level_diff = $level_b - $level_a;
$tmp['calc'] = $level_b . ' - ' .$level_a.' = '.$level_diff . ' x ' . $gold;
$x[] = $tmp;
}
}
elseif(sizeof($buildingA) == 1)
{
foreach($buildingB as $level_b => $gold)
{
$level_a = array_keys($buildingA);
$level_a = $level_a[0];
$level_diff = $level_b - $level_a;
$tmp['calc'] = $level_b . ' - ' .$level_a.' = '.$level_diff . ' x ' . $gold;
$x[] = $tmp;
}
}
Everything is good to here, but have and turd variant when the both buildings increase his level. I make several code's for this variant but non of them looks and work good.
Can somebody with more clear mind give some suggestion how easy to calculate difference.
v.1
$buildingA = array(4=>500, 5=>1500);
$buildingB = array(4=>1000, 5=>1000);
Calculation: ()
4 - 4 x 500
4 - 5 x 500
5 - 5 x 1000
v.2
$buildingA = array(4=>1500, 5=>500);
$buildingB = array(4=>1000, 5=>1000);
Calculation: (B-A)
4 - 4 x 1000
5 - 4 x 500
5 - 5 x 500
v.3
$buildingA = array(4=>1000, 5=>1000);
$buildingB = array(4=>500, 5=>1500);
Calculation: (B-A)
4 - 4 x 500
5 - 4 x 500
5 - 5 x 1000
V.4
$buildingA = array(4=>1400, 5=>600);
$buildingB = array(5=>700, 6=>1300);
Calculation: (B-A)
5 - 4 x 700
6 - 4 x 700
6 - 5 x 600
V.5
$buildingA = array(1=>300, 2=>700, 3=>1000);
$buildingB = array(5=>500, 6=>1500);
Calculation: (B-A)
5 - 1 x 300
5 - 2 x 200
6 - 2 x 500
6 - 3 x 1500
Lets try explan with v.3:
$buildingA = array(4=>1000, 5=>1000);
$buildingB = array(4=>500, 5=>1500);
Building A will produce 1000 gold in level 4 then level up and the rest is on level 5
Building B will produce 500 gold in level 4 then will level up and the rest is on level 5
So how we calculate:
"B" - 500 gold is given by level 4, we have 4 - 4 x 500, until now we use 500 from 2000 gold
"B" now become level 5
"A" its lv4 and need 500 more
gold to level 5, so we give 5 - 4 x 500 (its 5 because "A" level up
before that), until now we use (500 + 500) from 2000 gold
"A" now its level 5
"B" its level 5 and "A" is level 5, so all other gold its 5 - 5 x 1000, (here is the rest of not used gold: 1000)
Here i make some test script, but the code not look very well and its not work with v.04:
http://sandbox.onlinephpfunctions.com/code/6f12fda4877ad781da52f908f3cba79aa0c69f33
I need to calculate how match gold will produce the buildings together when both level UP.
I not see easy way to calc this. Any suggestions ?
I am out of ideas how to make that. its hard to explain it good, but i hope its writen clear - please do not judge me about that :)

One a genius colleague provided me easy mathematical solution:
function f ($x1, $x2)
{
foreach ($x2 as $k2 => $v2)
{
if ($v2 == 0)
continue;
foreach ($x1 as $k1 => $v1)
{
if ($v2 == 0 || $v1 == 0)
continue;
$m = ($v2 >= $v1) ? $v1 : $v2;
$v2 -= $m;
$v1 -= $m;
$x2[$k2] = $v2;
$x1[$k1] = $v1;
echo '(' . $k2 . ' - ' . $k1 . ') = ' . ($m) . '<br />';
}
}
}
f($buildingA, $buildingB);

Related

PHP - Poker algorithm that creates all possible poker combinations

I am currently trying to make a poker algorithm that creates all possible poker combinations with 2 cards. I know that there are 1,326 combinations of starting hands.
So I created my starting deck like this:
$startingDeck = array();
for($i=1; $i <= 13; $i++)
{
for($x=0; $x <= 3; $x++)
{
array_push($startingDeck, array("Value" => $i ,"Color" => $x, "key"=> $i.$x));
}
}
I want now to loop through all the cards and get all possible combinations with 2 cards for example
: value 1 color 1 and value 1 color 2
: value 1 color 1 and value 1 color 3
... etc
: value 2 color 0 and value 1 color 1
: value 2 color 0 and value 1 color 2
... etc
I want to do this for all the combinations that are possible but how.
You have your starting deck already. The idea is to generate all permutations:
E.g.
CARD NUMBER
1 2 3 4 5 6 7 8 9 10 11 12 13 ... 52
1 o x x x x x x x x x x x x x
2 - o x x x x x x x x x x x x
3 - - o x x x x x x x x x x x
4 - - - o x x x x x x x x x x
5 - - - - o x x x x x x x x x
6
7 ......... and so on .........
8
9
10
11
12
13
...
52
We have 52 cards in the deck (that's what you generated in $startingDeck):
The x denote the combination that we want to generate. Note that we don't have to generate the lower part of the matrix as the order does not matter in poker as you receive both cards at the same time. We also don't generate the axis as you can't have the same card twice (unless you cheat :)).
The idea now is to use two loops, but let the second loop start depending on the first initial $j depends on $i. That way we do not generate e.g. 2-1, 3-2, 3-1, ... again as we already generated 1-2, 1-3, 2-3, ....
So let's start:
for ($i = 0; i < count($startingDeck); $i++) {
// Ignore e.g. 2-1, 3-2, as we already generated 1-2, 2-3, and so on...
for ($j = $i+1; $j < count($startingDeck); $j++) {
$firstCard = $startingDeck[$i];
$secondCard = $startingDeck[$j];
// print my stuff
}
}
This generates the top matrix. The $i+1 makes sure that we don't generate the diagonal.
I hope that helps.

fibonacci numbers start 0, 1, 2, 3, 5 for options 2, but how do i start for option 3 or 4

I am trying to code the codility les 13 ladder.php exercise.
You have to calc using the fibonacci numers the total ways you can climb a ladder when you can do 1 or 2 rungs at the time.
I made a loop creating the first 50 fibonacci numbers like this:
$total = 50;
$fibonacci[0]=0;
$fibonacci[1]=1;
for($i=2;$i<=$total;$i++){
$fibonacci[$i] = $fibonacci[($i-1)] + $fibonacci[($i-2)];
}
This works well if you can do 1 or 2 rungs at the time.
But how do i adjust this loop to give me the first 50 fibonacci numbers if you can take 1, 2 or 3 rungs at the time.
if you can take 1 or 2 rungs you use: Fx = F[(x-1)] + F[(x-2)];
if you can do 1, 2 and 3 you use: Fx = F[(x-1)] + F[(x-2)] + F[(x-3)];
if you can do 1, 2, 3 and 4 you use: Fx = F[(x-1)] + F[(x-2)] + F[(x-3)] + F[(x-4)];
Then you can make as many numbers or calculate as many numbers as you wish.
But you always need the first few numbers to be able to make the calculations.
I hope this table makes clear what i mean:
2 3 4 5 6
1 1 1 1 1 1
2 2 2 2 2 2
3 3 4 4 4 4
4 5 7 8 8 8
5 8 13 15 16 16
6 13 24 29 31 32
The row below 2 is the basic fibonacci
Below 3 I would need number 1 to 3 to be able to calculate #4 and so on
Below 4 I need the first 4 to be able to calc #5 and so on
Can anyone help me create a loop to create the first say 10 numbers for row 4 and 5 and 6?
Thanks
Here you are a function returns a part of fibonacci numbers. You can set a start element (0 - based) and how many elements you need.
function takeFibonacci($start, $length)
{
$fibonacci = array(0, 1);
$result = array();
$position = 0;
do {
if (!isset($fibonacci[$position])) {
$fibonacci[$position] = $fibonacci[$position - 1] + $fibonacci[$position - 2];
}
if ($position >= $start) {
$result[] = $fibonacci[$position];
}
$position++;
} while ($position < $start + $length);
return $result;
}
$fib = takeFibonacci(5, 5);
var_dump($fib);
Code above returns this result
array(5) { [0]=> int(5) [1]=> int(8) [2]=> int(13) [3]=> int(21) [4]=> int(34) }

How to determine next level using a formula?

Thank you for any help you can provide on this.
If we have:
$level = floor((-1 + sqrt(1 + 4 * ($c_xp + 500) / 100 * 2)) / 2) - 1; //GET LEVEL
For instance if:
$c_xp = 1200
Then:
$level = 4
Then I am asking if:
$level = 4
How much xp to get to level 5?
How can I get the amount of xp required to achieve the next level?
The formula to get the minimum XP required to reach a level $level is given by:
$minXP = 12.5 * (pow((2 * $level + 3), 2) - 41);
So you can set $level = 5 and $level = 4 and find the difference between them.
Analyse:
I ran a script to view the XP needed for each level:
$current_level = 0;
for($c_xp = 1;$c_xp < 7000;$c_xp++){
$level = floor((-1 + sqrt(1 + 4 * ($c_xp + 500) / 100 * 2)) / 2) - 1; //GET LEVEL
if($level > $current_level){
$current_level++;
echo "c_xp $c_xp level $level<br>";
}
}
The output is:
c_xp 1 level 1
c_xp 100 level 2
c_xp 500 level 3
c_xp 1000 level 4
c_xp 1600 level 5
c_xp 2300 level 6
c_xp 3100 level 7
c_xp 4000 level 8
c_xp 5000 level 9
c_xp 6100 level 10
We can see that level 1 is an exception, then the difference of XP from level 2 to level 3 is 400, from level 3 to level 4: 500 and level 4 to level 5: 600 and so on...
The pattern is now clear,
Level 1 -> 1 XP
Level 2 -> Start a 100 XP
Level 3 -> Increase by 400 (500 XP)
Level 4 -> Increase by (400 + 100) 1000XP
Level 5 to Level X -> Keep increasing by 100
The code:
With the above analyse, I could come up with a loop in a function:
$c_xp = 1200;
$level = floor((-1 + sqrt(1 + 4 * ($c_xp + 500) / 100 * 2)) / 2) - 1;
echo 'Next level: '.current_level_xp($level+1).'<br>';
echo 'XP needed for next Level: '. (current_level_xp($level+1) - $c_xp);
function current_level_xp($current_level){
if($current_level <= 1){
return(1);
}else{
$increase = 400;
$needed = 100;
for($i=0;$i<$current_level-2;$i++){
$needed += $increase;
$increase += 100;
}
return $needed;
}
}
Output:
Next level: 1600
XP needed for next Level: 400
Use a math / formular plotting tool of your choosing to get an idea of the results of the used equation (which presumably isn't yours):
Now, there's probably even a way to reverse your formula for translating y into x. But I'm unsure if there's a floor reverse.

PHP rating system

I have a table (review) which stores the values (1-5) for ratings. I will use the sum of these ratings for the overall score.
I have 5 stars on the page which will show on or off depending on the overall value.
I have the overall score by counting the total value of all the ratings divided by the number of reviews in the table. This give a value below 5 every time...great.
However I now have a problem where the value could either be 1.5 or 1.75 for instance. If the value is 1.5 I will show 1 and a half stars on and 3 and a half stars off. How should I determine if the value is 1.75 to show only the 1.5 value star.
Hope that makes sense.
That should be a simple math problem, since your resolution is 1/2, multiply by two, round it, then divide by 2:
round(x * 2) / 2
round((1.75) * 2) / 2 = 2
round((1.65) * 2) / 2 = 1.5
<?php
$tests = array(-1, 0, 0.25, 0.5, 1, 1.5, 1.75, 3, 4.22, 6);
foreach($tests as $test)
echo "Initial rate = ".$test.", adjusted rate = ".adjustRate($test)."\n";
function adjustRate($val)
{
if ($val < 0)
return 0;
if ($val > 5)
return 5;
return floor($val * 2) / 2;
}
Gives for example:
Initial rate = 1.75, adjusted rate = 1.5

Finding factor for position

I know question title seems quite 'un-understandable', but I don't know how to write question title for this particular question.
Question:
I want to find factor for position.
Let me clear you with an example.
Value Factor
[Available] [Have to find out]
----------------------------------
1 10
3 10
9 10
10 10
11 10
25 10
50 10
75 10
99 10
100 100
101 100
105 100
111 100
127 100
389 100
692 100
905 100
999 100
1000 1000
1099 1000
1111 1000
4500 1000
6825 1000
7789 1000
9999 1000
10000 10000
10099 10000
51234 10000
98524 10000
99999 10000
100000 100000
and so on.
I hope you understand what I mean to get.
Assuming that the first three values should be 1 (as noted by Asaph), then you just need to use all that logarithm stuff you learned in school:
pow(10, floor(log10($n)))
So, how does this work? The base-10 logarithm of a number x is the y such that 10^y = x (where ^ stands for exponentiation). This gives us the following:
log( 1) 0
log( 10) 1
log(100) 2
...
So the log10 of a number between 1 and 10 will be between 0 and 1, the log10 of a number between 10 and 100 will be between 1 and 2, etc. The floor function will give you the integer part of the logarithm (we're only dealing with non-negative values here so there's no need to worry about which direction floor goes with negative values) so floor(log10()) will be 0 for for anything between 1 and 10, 1 for anything between 10 and 100, etc. Now we have how many factors of ten we need so a simple pow(10, ...) gives us the final result.
References:
log10
floor
pow
I'm still a little unsure of what you're asking, but it seems like you want to map values to other values... In php arrays can be indexed with anything (making them a map). If 999 always means a factor of 100 and 1099 always means a factor of 1000, you can set the value of array[999] to 100 and the value of array[1099] to 1000, etc.
Basically Factor is 10 to the power of number of digits in $value minus 1 (except for the single digit numbers):
if($value < 10) {
$value += 10;
}
$numOfDigits = count(str_split($value,1));
$factor = pow(10,$numDigits-1);
This function should work for you. It seems like the first 3 "factors" in your list don't fit the pattern. If, in your sample data set, those first 3 "factors" should really be 1 instead of 10, then you can safely remove the first 3 lines of the body of the function below.
function getFactor($num) {
if ($num < 10) { // If the first 3 "factors" listed
return 10; // in the question should be 1 instead of 10
} // then remove these 3 lines.
$factor = 1;
while($factor <= $num) {
$factor *= 10;
}
return $factor / 10;
}

Categories