Simplify PHP Condition - php

I have a loop that creates hexagons 3 in a row, but there is a small bug in the code if 3 are not used per row. To get around this, I have been applying a negative position using conditional code, but it's obviously not going to work on going without adding conditions to each step.
Does anyone know of a way of simplifying the following for future proofing? The condition just checks in increments of 3.
if($i == 3) {
echo ".hex-2 { left: -24.7%;}";
} else if($i == 6) {
echo ".hex-5 { left: -24.7%;}";
} else if($i == 9) {
echo ".hex-8 { left: -24.7%;}";
}
I'd like to do something for this array too, which counts in 2 then 1, then 2 and so on;
if(in_array($i, array(1,3,4,6,7,9,10,12,13,15,16,18,19,21,22,24,25,27,28,30,31))) { echo "</div><div class='hex-wrap'>"; };
Is this possible?

This should do it, though it definitely can be beautified somehow:
$numbers = [];
$n = 1;
$numbers[] = $n;
while ($n < 29) // Or whichever is the allowed maximum number
{
$n += 2;
$numbers[] = $n;
$n += 1;
$numbers[] = $n;
}
And then:
if (in_array($i, numbers)) { echo "</div><div class='hex-wrap'>"; };

Related

I'm new to PHP and I created a For loop and would like to know if anyone knows how to re-write it to a while loop?

This is the code I have. It currently works as is, However I'm experimenting with loops and want to see it can be done with a while loop and how it would be done. With this code I can take 2 input numbers and display them, then point out all odds, add all evens, and add all the squares of the odds.
define ("B","<br/>");
$firstNum = $_POST["firstNum"];
$secondNum = $_POST["secondNum"];
if ($firstNum < $secondNum)
{
$firstNum = true;
}
elseif ($firstNum >= $secondNum)
{
$firstNum = "You didn't listen, dumb dumb!".'<br/>GO BACK';
}
echo "First Number: ".$firstNum."<br/>"."Second Number: ".$secondNum;
echo B;
echo B;
$numbers = array();
$numbers = range($firstNum, $secondNum);
$length = count($numbers);
$odds = array();
$sumSqOdds = 0;
$sumEven = 0;
$j = 0;
for ($x = 0; $x < $length; $x++)
{
if (($numbers[$x] % 2) == 1)
{
$odds[$j] = $numbers[$x];
$sumSqOdds = $sumSqOdds + pow ($numbers[$x], 2);
$j++;
}
else
{
$sumEven = $sumEven + $numbers[$x];
}
}
$x = 0;
$y = 0;
printf("The odd numbers between your integers are: ");
for ($x = 0; $x < $j; $x++)
{
echo $odds[$x];
echo ' ';
$y++;
if (($y % 10) == 0)
{
echo B;
}
}
echo B;
echo B;
printf("The sum of all even numbers between your integers is: ".$sumEven);
echo B;
echo B;
printf("The sum of the square of the odd numbers between your integers is: ".$sumSqOdds);
Here is my while loop but it seems to be infinite...
$numW = array ();
$numW = range ($firstNum, $secondNum);
$lengthW = count ($numW);
$oddsW = array ();
$sumSqOddsW = 0;
$sumEvenW = 0;
$j = 0;
$x = 0;
while ($x < $lengthW)
{
if (($numW[$x] % 2) == 1)
{
$oddsW[$j] = $numW[$x];
$sumSqOddsW = $sumSqOddsW + pow ($numW[$x], 2);
$x++;
$j++;
}
else
{
$sumEvenW = $sumEvenW + $numW[$x];
}
}
$x = 0;
$y = 0;
printf ("The odd numbers between your integers are: ");
while ($x < $j)
{
$x++;
echo $oddsW[$x];
echo "nbsp;";
$y++;
if (($y % 10) == 0)
{
echo B;
}
}
Equivalent loops:
for ($i = 0; $i < 10; $i++) {
echo $i;
}
$i = 0;
while ($i < 10) {
echo $i;
$i++;
}
For a loop to ever finish it has to change one of the two evaluating variables. So either $x, or $lengthW would have to change during iteration. You made an if statment, in the first case you define that X increases by 1, but in the else case you do not change any variable that then has an effect on either $x, or $lengthW
Nor is there any check that sees if the else state has been reached and to catch that by either changing $x or $lengthW in a later iteration.
As such there's an infinite loop as soon as you reach the else case.
The if statement uses the same $x value as the last iteration checking the same position of the $numW, as such nothing has changed since the last iteration and you'll hit the else again, and again, and so on.
while ($x < $lengthW)
{
if (($numW[$x] % 2) == 1)
{
$oddsW[$j] = $numW[$x];
$sumSqOddsW = $sumSqOddsW + pow ($numW[$x], 2);
$x++; //$x is increased by one, and as such, the loop will progress.
// remove this $x++ if you place it outside the if else statement.
$j++;
}
else // reached when ($numW[$x] %2) != 1
{
$sumEvenW = $sumEvenW + $numW[$x];
// No changes to $x or $lengthW as such you'll hit the else again
// this could be solved by either adding $x++; here.
}
// or by adding $x++; here
// (if you do add it here, remove it in the if case above,
// or you risk increasing it by 2 every iteration
}

Solving Algorithm (Josephus permutation) in PHP

Suppose 100 people line up in a circle. Counting from person 1 to person 14, remove person from the circle. Following the count order, counting again and remove the 14th person. Repeat. Who is the last person standing?
I've tried everything to solve this and it seems to not be working with dead loops.
<?php
//init array
$array = array();
for ($i = 0; $i < 100; $i++) { $array[] = $i; }
//start from 0
$pos = 0;
while (count_not_null($array) > 1) {
//reset count
$count = 0;
while (true) {
//ignore NULL for count, that position is already removed
if ($array[$pos] !== NULL) {
$count++;
if($count == 14) { break; }
}
$pos++;
//go back to beginning, we cant go over 0-99, for 100 elements
if ($pos > 99) { $pos = 0; }
}
echo "set index {$pos} to NULL!" ."<br>";
$array[$pos] = NULL;
if (count_not_null($array) === 1) { break; }
}
echo "<pre>";
print_r($array);
echo "</pre>";
//counting not null elements
function count_not_null($array) {
$count = 0;
for ($i = 0; $i < count($array); $i++) {
if ($array[$i] !== NULL) { $count++; }
}
return $count;
}
?>
For solving this with as little code as possible and quickest you could do like this:
function josephus($n,$k){
if($n ==1)
return 1;
else
return (josephus($n-1,$k)+$k-1) % $n+1;
}
echo josephus(100,14);
Here we are using an recursive statement instead, as what you are trying to solve can be defined by this mathematical statement f(n,k) = (f(n-1,k) + k) % n
For reading more about this mathematical formula you can see it here on the wiki page.
The problem is this while loop
while ($count < 14) {
if ($array[$pos] != NULL) {
$count++;
}
$pos++;
if ($pos > 99) { $pos = 0; }
}
Because you increment $pos even if count is 14 you will end with incorrect values and loop forever. Replace it with this:
while (true) {
if ($array[$pos] != NULL) {
$count++;
if($count == 14) {break;}
}
$pos++;
if ($pos > 99) { $pos = 0; }
}
Also comparing 0 to NULL won't give you the expected results as mentioned by #Barmar, so you can either change the NULL comparison, or start counting from 1
NOTE: This would be way faster if you didn't loop through array every time :D consider using a variable to count the remaining items
Anyone who stumbles across this again, here is a slightly quicker one:
function josephus($n){
$toBin = decbin($n); // to binary
$toBack = substr($toBin,1) . "1"; // remove first bit and add to end
return bindec($toBack); // back to value
}
Based on this solution.

Sudoku solving/generating algorithm in PHP

I'm having trouble with a specific part of my algorithm and was hoping someone has an idea what I'm doing wrong.
My program basically works like this:
Create 81 empty cells, fill each cell step per step while checking if it's valid there.
I have 3 valid checks and the horizontal valid check (if numbers are double or more in 1 line) is already giving me trouble.
This is my function:
private function isValidHorizontal($index)
{
for ($i = 0; $i < 81; $i += 9){
$firstIndex = $i * 9;
$lastIndex = 9 * ($i + 1) - 1;
// fisrt loop tracking fowards, 2nd loop tracking backwards
if ($index >= $i && $index <= $lastIndex) {
for ($j = 0; $j <= $lastIndex; $j++) {
if ($this->cell[$index]->getValue() == $j) {
return false;
}
}
for ($k = 0; $k >= $firstIndex; $k--){
if ($this->cell[$index]->getValue() == $j) {
return false;
}
}
}
}
return true;
}
$index is the position of the cell so when $index = 0 that would be the very first cell. Last cell would be $index = 80
$this->cell[$index]->getValue() returns an int number i checked so I'm getting the value correctly.
The problem it somehow never returns true
Any Ideas? obviously this is just part of the code, if you need more to help, write a comment and I'll edit :)
In the second inner loop you are using $j instead of $k:
for ($k = 0; $k >= $firstIndex; $k--){
if ($this->cell[$index]->getValue() == $j) { // Here, change to $k
You already got the right answer from #this.lau_, but If I may offer some advice, you could shorten it up a bit by changing the logic. PHP isn't really the best suited language for this, so it'll still look a bit clunky, but I might be worth taking a look at. :)
private function isValidHorizontal($index) {
$taken = [];
foreach (range($index, 81, 9) as $i) {
$value = $this->cell[$i]->getValue();
if (is_int($value) && in_array($value, $taken)) {
return false;
}
$taken[] = $value;
}
return true;
}

PHP Get Experience by Level

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;
}
}
}

is there a better, simpler way?

in php, i'm doing a loop, something like like
$x = 0;
for ($i = 0; $i < 100; $i++)
{
if ($x == 3) //better way to do this? in this example, determine every 3 times in a loop
{
//"do something"
$x = 0;
}
$x++;
as you can see, i'm doing something in the loop every 3 times it goes around, but the question is, is there a better, simpler way of finding out if it's time for it to "do something" in the loop?
You could use a modulo:
if(($i % 3 == 0) && ($i > 0))
{
...
}
(don't forget to check if it's superior to 0 or it will get in the if at the first iteration.
You can use the modulus operator % to see if $i is divisible by three. That should keep you from managing $x
Instead of using $x, just check if( $i > 0 && $i % 3 == 0). If you want something to happen on the first run as well, just drop the $i > 0 && part.
Fizzbuzz huh? You'll want the Modulo operator - %
if ((6 % 3) == 0) {
echo "is divisable by three";
}
You can avoid the $x variable by using the modulus operator:
if ($i % 3 == 0 && i > 0){
// Do something
}
Basically this implements the same logic; every third iteration, the loop will run your extra code.
Use modulus on $i:
for ($i = 0; $i < 100; $i++)
{
if($i % 3 == 0)
{
// do something
}
}
for ($i = 0; $i < 100; $i++) {
{
if($i%3==0){
//Do Something
}
}
in this code :
for ($i = 0; $i < 100; $i++)
{
if(($i%3==0) && $i>0)
{
//Do Something #first will be after 4 time
}
}
but this one :
for ($i = 1; $i <=100; $i++)
{
if($i%3==0)
{
//Do Something #even first will be after 3 time
}
}

Categories