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;
}
Related
Below is the code i tried, where count is showing improper.
Please help me to get where i am missing the logic.
I am attaching the code which i have tried so far.
PS Note:- I am not intended to use more built in function of php and so I created function for string length.
error_reporting(E_ALL);
$string = "ssddk";
function checkString($addinString, &$stringBK) {
if (empty(count($stringBK))) {
$stringBK[] = $addinString;
return false;
}
foreach ($stringBK as $key => $val) {
if ($addinString == $val) {
return true;
}
}
$stringBK[] = $addinString;
return false;
}
for ($i = 0; $i < checkstrlength($string); $i++) {
$count = 0;
for ($j = 0; $j < checkstrlength($string); $j++) {
if ($string[$i] == $string[$j]) {
if (checkString($string[$i], $stringBK)) {
continue 2;
}
$count++;
echo "Column => " . $string[$j] . " for count" .$count . "<br>";
}
}
}
function checkstrlength($string) {
$count = 0;
for ($i = 0; $string[$i] != ""; $i++) {
$count++;
}
return $count;
}
It gives below output ,
Column => s for count1
Column => d for count1
Column => k for count1
I am expecting it as ,
Column => s for count 2
Column => d for count 2
Column => k for count 1
Ok, there a couple of things to look at here.
The checkstrlength() has the below loop.
for ($i = 0; $string[$i] != ""; $i++) {
Formally speaking, we usually look at \0 terminating character in the string to terminate our loop. But in PHP, everything is a string. So, \0 is now a string to match on rather than a character match. Better, we do an isset check to stop our loop. So, code would look like:
for ($i = 0; isset($string[$i]); $i++) {
Second is your not caching the result which you got from checkstrlength(). Do it. Also, you can start the inner loop from $i itself. There is no need to go from start again. So, for loop would look like:
$length = checkstrlength($string);
for ($i = 0; $i < $length; $i++) {
for ($j = $i; $j < $length; $j++) {
Third is that there is no need of empty and count checks in checkString. This also reduces inbuilt function calls. You can simply loop over and return true if found. If not found, we are adding it anyway. So it would look like:
function checkString($addinString, &$stringBK) {
foreach ($stringBK as $key => $val) {
if ($addinString == $val) {
return true;
}
}
$stringBK[] = $addinString;
return false;
}
Now, in your nested loop, you add it to $stringBK outside of the inner loop, because there is no point in checking with the inner loop when chars match. This is because if some character was visited, why initialize the inner loop at all. Just have a check above and continue the search and count. Also note that you are having echo statements inside the inner loop which doesn't make sense because we haven't finished the count yet. Let's do and print it outside of the inner loop at the end. Snippet as follows:
for ($i = 0; $i < $length; $i++) {
$count = 0;
if (checkString($string[$i], $stringBK)) {
continue;
}
for ($j = $i; $j < $length; $j++) {
if ($string[$i] == $string[$j]) {
$count++;
}
}
echo "Column => " . $string[$i] . " for count : " .$count,PHP_EOL;
}
Final Code Demo: https://3v4l.org/4dpST
The code below basically helps in finding out if a number is a Palindromic Number or not. Although I get my execution done with the output, I just can seem to handle all the "screams" and fatal errors that I get. How do I handle this. Just a beginner and trust you can explain in a way that I may be able to understand..
<?php
for ($num = 1; $num <= 20; ++$num){
$_array1 = str_split($num);
//print_r($_array1);
//echo "<br/>";
$_array2 = array_reverse($_array1);
//print_r($_array2);
//echo "<br/>";
$i = 0;
$j = 0;
while ($i < sizeof($_array1) && $j < sizeof($_array2)){
if ($_array1[$i] == $_array2[$j]){
++$i;
++$j;
}
}
if ($_array1[$i] == $_array2[$j]){
echo "The number $num is a Palindrome Number";
}
}
?>
You get to the size of elements, which is 1. However, if your array has only one element, which is the case for 1-digit numbers, then sizeof($_array) === 1. Which means that the biggest possible index you can use is 0. You need to change your code to something like this:
<?php
for ($num = 1; $num <= 20; ++$num){
$_array1 = str_split($num);
//print_r($_array1);
//echo "<br/>";
$_array2 = array_reverse($_array1);
//print_r($_array2);
//echo "<br/>";
$i = 0;
$j = 0;
$different = false;
while ((!$different) && ($i < sizeof($_array1))){
if ($_array1[$i] == $_array2[$j]){
++$i;
++$j;
} else {
$different = true;
}
}
if (!$different){
echo "The number $num is a Palindrome Number";
}
}
?>
But you are inversing the array without a need to do so and you are looping for unnecessarily long. I propose this function to determine whether an array is a palindrome:
function isPalindrome($input) {
$size = count($input);
for ($index = 0; $index < $size / 2; $index++) {
if ($input[$index] != $input[$size - $index - 1]) {
return false;
}
}
return true;
}
Note, that:
the function assumes that the keys of the array are numbers
the function uses a single array
the size of the array is stored into a local variable to not calculate it repeatedly
the cycle cycles until half of the array, since going beyond that is unnecessary, due to the symmetrical nature of the != operator
the function returns false when the first difference is found, to further optimize the checking
if there were no differences, the function returns true, representing that the input is a palindrome
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.
what I want to do is run this for loop and within there is a foreach searching the positions. what I want to do is once there it returns false I want it to break and save the position of $i in a variable. I'm using simple_html_dom.php but I don't think that matters since this is more of a basic programming problem.
for($i = $0; $i < $20; $i++){
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false){
break;
}
}
//this is not valid, but essentialy this is what I want to do.
$stop = $i;
}
To break multiple levels in a loop you simply specify the levels, eg, break 2 - see the manual on break - http://www.php.net/manual/en/control-structures.break.php.
As such your code might work as
for($i = $0; $i < $20; $i++){
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false){
$stop = $i; // Set variable
break 2; // break both loops
// or alternatively force the outer loop condition to expire
//$i = 21; // Force the outer loop to exit
//break;
}
}
}
I have expanded to question to set $i = 21 to break the outer loop with a single break.
Untested code but syntax checked...
<?php
// Untested code...
// Assume that you WILL break out of the loops...
$currentForIdx = -1; // so we can test that 'for' loop actually ran
$quitLoops = false;
for($i = 0; $i < $20 && !quitLoops; $i++) {
$currentForIdx = $i; // in case we break out of the loops
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false) {
$quitLoops = true;
break;
}
}
}
// test $quitLoops and $currentForIdx to work out what happened...
?>
I havent tested this, but I would try something like this:
for($i = $0; $i < $20; $i++){
$stop = false;
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false){
$stop = $i;
}
}
if ($stop !== false) {break;}
}
I need some help, even though I think I'm checking for the length of the array and I should be breaking out of the loop, I still get warnings on my [else if ($value....] line. So either I'm missing something crucial or I've been staring at this code segment too long and its obvious. Any insight would be appreciated.
$count = count($filter); //Filter is an array
if ($count > 1 ){
//Compare values and generate a range to choose from
$i = 1;
foreach($filter as $value){
//Break the loop if at the end of the array
if ($i >= $count){
//throw new exception($i .' '.$count);
break;
}
//if the value is smaller then the next procceding value, because they are already in order of presidence,
//add it to our range of potentials.
else if($value < $filter[$i]->value){
array_push($range, key($filter));
}
$i++;
}
}else {
return false;
}
I suspect that there are gaps in your array. Try this:
$filter = array_values($filter); // this will remove any gaps in the array
$count = count($filter);
if ($count <= 1)
return false;
for ($i = 0; $i < $count; $i++)
{
if ($i != $count-1 && $filter[$i]->value < $filter[$i+1]->value)
array_push($range, key($filter));
}
Your array might have non-numeric keys. Then try this:
foreach($filter as $key=>$value)
{
// test for $filter[$key];
}
Or your $filter array doesn't hold objects, then you can't use the -> in
$filter[$key]->value
try this code.... no need of checking count..
$range = array();
$i = 1;
foreach($filter as $value)
{
if(isset($filter[$i]) && $value < $filter[$i]->value)
{
array_push($range, key($filter));
$i++;
}
else
{
break;
}
}