PHP Get Experience by Level - php

I have this piece of code that loops 1 through 99 and is a formula.
function getExperienceByLevel ($maxLevel)
{
$levels = array ();
$current = 0;
for ($i = 1; $i <= $maxLevel; $i++)
{
$levels[$i - 1] = floor ($current / 4);
$current += floor($i+300*pow(2, ($i/9.75)));
}
return $levels;
}
First you initiate it like so $aLevels = getExperienceByLevel(99); then to see how much EXP you need to get to level 6 you do this echo $aLevels[5]; since it's an array.
Now I'm trying to do reverse. Get Level by EXP.
function getLevelByExp($exp)
{
$myLevel = 0;
$aLevels = getExperienceByLevel(99);
for ($i = 1; $i < 100; $i++)
{
if ($exp > $aLevels[$i-1])
{
return $myLevel;
}
}
}
When called upon getLevelByExp(1124); or any number inside, it seems to return a zero. But it seems to work when you put echos inside that statement.
Like instead of return $myLevel do echo "You are up to level $i<br />"; and it will go all the way up to the current level you've gained EXP for.
But still.. doesn't work when I want to simply return a number.

This seems to work better than your function:
function getLevelByExp($exp)
{
$aLevels = getExperienceByLevel(99);
for ($i = 0; $i <= 99; ++$i)
{
//echo "cmp $exp >= aLevels[$i]={$aLevels[$i]}\n";
if ($exp <= $aLevels[$i])
return $i - 1;
}
return -1;
}
It needs improvement for the edge cases, such as when $exp is zero.

Return $i instead because it always '0'
if ($exp > $aLevels[$i-1]) {
return $i;
}

You never change $myLevel, so it will always stay at 0.
Try returning $i instead of $myLevel, as $i is actually changing:
function getLevelByExp($exp) {
$aLevels = getExperienceByLevel(99);
for ($i = 1; $i < 100; $i++) {
if ($exp > $aLevels[$i-1]) {
return $i;
}
}
}

Related

Multiple comparisons inside for loops don't break php code. Why?

Why this piece of code works when it is clearly wrong in the second for loop (for ($i==0; $i<$parts; $i++) {)?
Does php allows for multiple comparisons inside for loops?
function split_integer ($num,$parts) {
$value = 0;
$i = 0;
$result = [];
$modulus = $num%$parts;
if ($modulus == 0) {
for($i = 0; $i < $parts; $i++)
{
$value = $num/$parts;
$result[] = $value;
}
} else {
$valueMod = $parts - ($num % $parts);
$value = $num/$parts;
for ($i==0; $i<$parts; $i++) {
if ($i >= $valueMod) {
$result[] = floor($value+1);
} else {
$result[] = floor($value);
}
}
}
return $result;
}
Code for ($i==0; $i < $parts; $i++) runs because $i==0 has no impact on loop.
In normal for loop first statement just sets $i or any other counter's initial value. As you already set $i to 0 earlier, your loop runs from $i = 0 until second statement $i < $parts is not true.
Going further, you can even omit first statement:
$i = 0;
for (; $i < 3; $i++) {
echo $i;
}
And loop will still run 3 times from 0 to 2.

Gaussian elimination has to give back multiple solutions php

I want to use gaussian elimination to solve the following matrix Matrix and this is the answer I'm expecting. I would like to get back an equation in the form as is displayed in answer but i can't figure out how to do it.
public function gauss($A, $x) {
# Just make a single matrix
for ($i=0; $i < count($A); $i++) {
$A[$i][] = $x[$i];
}
$n = count($A);
for ($i=0; $i < $n; $i++) {
# Search for maximum in this column
$maxEl = abs($A[$i][$i]);
$maxRow = $i;
for ($k=$i+1; $k < $n; $k++) {
if (abs($A[$k][$i]) > $maxEl) {
$maxEl = abs($A[$k][$i]);
$maxRow = $k;
}
}
# Swap maximum row with current row (column by column)
for ($k=$i; $k < $n+1; $k++) {
$tmp = $A[$maxRow][$k];
$A[$maxRow][$k] = $A[$i][$k];
$A[$i][$k] = $tmp;
}
# Make all rows below this one 0 in current column
for ($k=$i+1; $k < $n; $k++) {
$c = -$A[$k][$i]/$A[$i][$i];
for ($j=$i; $j < $n+1; $j++) {
if ($i==$j) {
$A[$k][$j] = 0;
} else {
$A[$k][$j] += $c * $A[$i][$j];
}
}
}
}
# Solve equation Ax=b for an upper triangular matrix $A
$x = array_fill(0, $n, 0);
for ($i=$n-1; $i > -1; $i--) {
$x[$i] = $A[$i][$n]/$A[$i][$i];
for ($k=$i-1; $k > -1; $k--) {
$A[$k][$n] -= $A[$k][$i] * $x[$i];
}
}
return $x;
}
I hope someone can help me to rewrite this code so it gives the solution i've provided or recommend a library which is capable of doing this.
I've searched for possible solutions on Google but haven't been able to find one yet.
Thanks in advance.

Looking for opposite of pow() in PHP

I am working on mathematical problem where the formula is: A[i] * (-2) power of i
where i=0,1,2,3,...
A is an array having values 0 or 1
Input array: [0,1,1,0,0,1,0,1,1,1,0,1,0,1,1]
Output is: 5730
Code
$totalA = 0;
foreach ($A as $i => $a) {
$totalA += $a * pow(-2, $i);
}
This is correct. Now I am looking for its opposite like:
Input is: 5730
Output will be: [0,1,1,0,0,1,0,1,1,1,0,1,0,1,1]
I am not asking for the exact code but looking for some logic from where I should start. I tried to use log() method but that did not return the desired output.
You were not looking for exact code, but I found this problem too interesting. This works:
function sign($n) {
return ($n > 0) - ($n < 0);
}
$target = -2396;
$i = 0;
$currentSum = 0;
// Look for max $i
while (true) {
$val = pow(-2, $i);
$candidate = $currentSum + $val;
if (abs($target) <= abs($candidate)) {
// Found max $i
break;
}
if (abs($target - $candidate) < abs($target - $currentSum)) {
// We are getting closer
$currentSum = $candidate;
}
$i++;
}
$result = [];
for ($j = $i; 0 <= $j; $j--) {
$val = pow(-2, $j);
$border = $val / 4;
if (sign($val) == sign($target) && abs($border) < abs($target)) {
array_unshift($result, 1);
$target -= $val;
} else {
array_unshift($result, 0);
}
}
echo json_encode($result);
First I look for the $i that gets me on or slightly above the $target. When found, I walk down and decide for each bit if it should be in the result.

I need to find all amicable numbers up to a certain number

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!

Get number by loop on if - PHP

I have this piece of code that loops 1 through 99 and is a formula.
function getExperienceByLevel ($maxLevel)
{
$levels = array ();
$current = 0;
for ($i = 1; $i <= $maxLevel; $i++)
{
$levels[$i - 1] = floor ($current / 4);
$current += floor($i+300*pow(2, ($i/9.75)));
}
return $levels;
}
First you initiate it like so $aLevels = getExperienceByLevel(99); then to see how much EXP you need to get to level 6 you do this echo $aLevels[5]; since it's an array.
Now I'm trying to do reverse. Get Level by EXP.
function getLevelByExp($exp)
{
$aLevels = getExperienceByLevel(99);
for ($i = 1; $i < 100; $i++)
{
if ($exp > $aLevels[$i-1])
{
return $i;
}
}
}
So I try to do this:
$aLevels = getExperienceByLevel(99);
echo getLevelByExp(131);
When called upon getLevelByExp(131); or any number inside, it seems to return a 1 even though it should be 2 since Level 3 is 167 EXP and Level 2 is 80 EXP. Here's a reference image: http://i.imgur.com/gEYgu.png
function getLevelByExp($exp) {
$aLevels = getExperienceByLevel(99);
for ($i = 99; $i >= 1; $i--)
{
if ($exp > $aLevels[$i-1])
{
return $i;
}
}
}
You are returning as soon as $exp > $aLevels[$i-1]. On the first runthrough of your original loop, $aLevels[$i-1] = $aLevels[0] = 0, so it will always return right away for any non-negative $exp value.
You are doing two mistakes: You are indexing your levels array wrong. And you're checking it the wrong way. Use this:
http://codepad.viper-7.com/MGpOUu
function getExperienceByLevel($maxLevel) {
$levels = array ();
$current = 0;
for ($i = 1; $i <= $maxLevel; $i++) {
$levels[$i] = floor ($current / 4);
$current += floor($i+300*pow(2, ($i/9.75)));
}
return $levels;
}
function getLevelByExp($exp) {
$levels = getExperienceByLevel(99);
$current = 0;
foreach($levels as $level => $required) {
if($required>$exp)return $current;
$current = $level;
}
return $current;
}
echo getLevelByExp(131);
// returns 2
change
if ($exp > $aLevels[$i-1])
to
if ($exp > $aLevels[$i-1] && $exp < $aLevels[$i])
checked and it is working
working example http://codepad.viper-7.com/BjmHad
You need the opposite conditional, and to compare to the next level, so you can determine that a given exp level does not fit into any higher level. This code works for me:
if ($exp < $aLevels[$i])
{
return $i;
}
Nice and simple. Try it out: http://codepad.viper-7.com/FrjtHT
I think you should do it like
function getLevelByExp($exp)
{
$aLevels = getExperienceByLevel(99);
for ($i = 1; $i < count($aLevels); $i++)
{
if ($exp >= $aLevels[$i-1] && ($exp - $aLevels[$i-1] < $aLevels[$i] - $aLevels[$i-1]))
{
return $i;
}
}
}
Check out http://www.phpfiddle.org/main/code/paw-08f

Categories