Hello and welcome to our community! Is this your first visit?
Enjoy an ad free experience by logging in. Not a member yet? Register.

1. ## 1 != 1

I'm stick in an infinate while loop and I don't know why.

The code is quite simple - while \$number is not prime and is > 1 - keep going - but it gets to one, and keeps going and going and going - I even got it to print out: "\$number is not prime and is > 1" and I got "1 is not prime and is > 1"... wtf? I also tried adding 1 to the prime numbers array but still the same result - it works for everything else, just not for this

PHP Code:
``` while(!(in_array(\$number,\$primes)) )      {        if(\$number &#37; \$primes[\$i]==0)        {          \$number=\$number/\$primes[\$i];          \$factors[\$primes[\$i]]++;        }        else        {          \$i++;        }      }  ```
Actually - 1 should never be the answer anyway - if \$number divided by the next prime_number in the list =1 then \$number is = to the next prime number and is therefore prime and should have dropped out of the loop. The number at the start is 139206 and the prime it seems to get stuck on is 23201 - that should pass the test as being prime and drop it out

• If \$number = 1, then your while() condition says `if NOT (in_array && \$number NOT 1)`, which could also be stated `if NOT (TRUE && FALSE)`, which evaulates to TRUE, so it stays in the loop. I think you think the condition says, among other things, while(\$number != 1), but it's not.

• 23201 and 1 are both in the array - I only put the !=1 in as desperation really, it should stop the loop at 23201

• The code has != 1 and your comments refer to > 1. There is a double negative so that solves the mystery about 1 != 1.

I'm a little confused. I'm not sure what the question is after establishing that. It's hard to tell what's going on without being able to run any meaningful test values.

• ok, to make this simple, I've taken out anything to do with the 1 - it still doesn't work both 1 and 23201 are in the primes array but it isn't dropping out.

• This is completely dependent on data so it's hard to duplicate. When I made a small subset, I had to add a conditional to the while loop:

while(!(in_array(\$number,\$primes)) && \$i<count(\$primes) )

That prevented the if-statement from trying to access the array out of bounds. Not sure if that helps but good luck!

• if 23201 wasn't in the array \$primes then \$number would never get to 1. The reason it is 1 is that \$number gets to 23201 then rather than leaving the loop - the loop continues and until it gets to 23201 in the primes array, then it divides \$number by \$primes[\$i] and comes up with 1 (which is also in the primes array and should cause the loop to end)

• this is my primenumber function - I use a limit of 50000

the input number is 139206
PHP Code:
``` function esprime(\$limit)    {        \$sqrtlimit = sqrt(\$limit);        \$range = 0;        while(\$range<\$limit){            \$i .= '11';            \$range+=2;        }        \$n = 2;        while(\$n < \$sqrtlimit){            if (\$i[\$n]){                \$sqn = \$n*\$n;                \$k = \$sqn;                \$i[\$k]=0;                while(\$k<=\$limit){                    \$k += \$n;                    \$i[\$k]=0;                }            }            ++\$n;        }        \$n = 1;        while(\$n<\$limit){            if(\$i[\$n]) \$primes[] = \$n;            \$n+=2;        }        if(\$limit>=2) \$primes[0] = 2;        return \$primes;    }  ```

• Assuming I understand the goal (which is a stretch), it seems to work. My understanding is that it should break out of the while-loop when \$number gets to 23201 since that is a prime number.

PHP Code:
``` \$primes = esprime(50000);\$number = 139206;\$i=0;while(!(in_array(\$number,\$primes)) ){    if(\$number &#37; \$primes[\$i]==0)    {      \$number=\$number/\$primes[\$i];      //\$factors[\$primes[\$i]]++;    }    else    {      \$i++;    }}echo \$number." is in the array so we broke out" ;  ```
This prints out "23201 is in the array so we broke out".

• Originally Posted by arnyinc
Assuming I understand the goal (which is a stretch), it seems to work. My understanding is that it should break out of the while-loop when \$number gets to 23201 since that is a prime number.

PHP Code:
``` \$primes = esprime(50000); \$number = 139206; \$i=0; while(!(in_array(\$number,\$primes)) ) {     if(\$number % \$primes[\$i]==0)     {       \$number=\$number/\$primes[\$i];       //\$factors[\$primes[\$i]]++;     }     else     {       \$i++;     } } echo \$number." is in the array so we broke out" ;  ```
This prints out "23201 is in the array so we broke out".
windows or linux?

• Windows XP and Apache 2.2.

• I assume you want to get all prime factors a number consists of. Here is a script that does that:
PHP Code:
``` /** *  signature *    array sieve( int, &array ) * *  Computes all primes in the range 0..\$size with the Sieve of Erastothenes and returns an associate array with the primes as keys and 0 as values */ function sieve(\$size, &\$flags) {     \$primes = array();     for(\$i = 2; \$i <= \$size; ++\$i)     {         if(\$flags[\$i])         {             \$primes[\$i] = 0;             for(\$j = \$i<<1; \$j <= \$size; \$j += \$i)             {                 \$flags[\$j] = FALSE;             }         }     }     return \$primes; } \$number = \$orgNumber = 139206; // number to decompose, \$number will be modified if(\$number < 1 || (int) (\$number) != \$number) // \$number must be a positive integer {     exit('error'); }  \$flags = array_fill(0, \$number, TRUE); // an array of boolean flags for the 2nd parameter to sieve() \$primeMap = sieve(\$number, \$flags); // create a map of all primes in the range of 0..\$number end(\$primeMap); // start with the last (= highest) prime \$curPrime = key(\$primeMap); // get highest prime if(isset(\$primeMap[\$number])) // if \$number is a prime itself, we don't need to decompose it {     ++\$primeMap[\$number]; } elseif(\$number >= 1) // prevent endless loop for \$number < 1 {     do     {         do         {             \$nTemp = (int) (\$number / \$curPrime);             if(\$nTemp * \$curPrime == \$number) // is \$number divisible by \$curPrime without remainder ?             {                 \$number = \$nTemp;                 ++\$primeMap[\$curPrime]; // increase the factor counter for the prime             }             else             {                 break; // get a smaller prime for next test             }         }         while(\$number >= \$curPrime); // \$number must be at least >= \$curPrime to be divisible         do         {             prev(\$primeMap); // get the next (lower) prime             \$curPrime = key(\$primeMap);         }         while(\$curPrime > \$number); // \$curPrime must be <= \$number for a division     }     while(\$number != 1); // if \$number == 1 we have all factors } // create result string and print it out \$str = (\$number >= 1) ? '1 * ' : \$number.' * '; foreach(\$primeMap as \$prime => \$factorCount) {     if(\$factorCount)     {         \$str .= str_repeat(\$prime.' * ', \$factorCount);     } } echo \$orgNumber,' expressed using prime factors: ',substr(\$str, 0, -3); ?>  ```
dumpfi

• hmm its working now.... of course something else is broken now.
Originally Posted by arnyinc
Assuming I understand the goal
Prime factorisation of course!

Ok, so heres the whole story.

I have a number of different factories.Each factory uses a different amount of hours to produce the subcomponents for a given item.
I'm trying to find, how many of each different type of factory I would need to optimise output.

I've tried to solve this problem by:
1. Finding the number of hours required for all the factories to sync up - ie. they all finish at the same time (regardless of how many components they've manufactured ie. factory 1 might have enough components to make 10 items while factory 2 has only made enough for 5) - I'm doing this by calculating the lowest common multiple (lcm) of all the different times involved. I'm finding the lcm using the prime factorisation method - ie. find the prime factors of each number then for each individual prime number in the set of primes you end up with, find the highest number of each of them and then multiply those all together (each prime is multipled by itself the maximum number of times it appears in any 1 number then each of those numbers are multiplied together) and that gives the lcm.

So the lcm tells me how long it would take for all the factories to sync up, then for each factory, I divide the lcm by its time - which tells me how many runs that factory could complete in that time. Then I divide the lcm/max of all the times then divide that by the number of runs for each factory - and thats supposed to always be a whole number... except at the moment, it isnt....

This is the whole code.

PHP Code:
```     function optimalSetup(\$times)    {      \$start = microtime(true);      foreach(\$times as \$key=>\$val)      {        \$times[\$key]=\$val*60;      }      \$lcm = \$this->lcm(\$times);      echo 'lcm is '.\$lcm.'<br />';      \$max = max(\$times);      \$min = min(\$times);      foreach(\$times as \$id => \$time)      {         \$opt[\$id]=(\$lcm/\$min)/(\$lcm/\$time);       }           return \$opt;     }        function lcm(\$numbers)    {      print_r(\$numbers);      \$start = microtime(true);      foreach(\$numbers as \$number)      {        \$primes = \$this->esprime(50000);        \$primes[]=1;        \$pf[\$number] = \$this->primefactors(\$number,\$primes);        foreach(\$pf[\$number] as \$key => \$val)        {          \$primef[\$key][]=pow(\$key,\$val);        }      }      \$total = 1;      foreach(\$primef as \$key => \$val)      {        \$total = \$total * max(\$val);      }          return \$total;      }        function primefactors(\$number,\$primes)    {      \$start = microtime(true);      \$i=0;      if(!is_numeric(\$number))      {        return array();      }      while(!(in_array(\$number,\$primes)) )      {        if(microtime(true)-\$start>2)        {          break;        }        if(\$number&#37;\$primes[\$i]==0)        {          \$number=\$number/\$primes[\$i];          \$factors[\$primes[\$i]]++;        }        else        {          \$i++;        }      }      \$factors[\$number]++;      return \$factors;    }        function esprime(\$limit)    {        \$sqrtlimit = sqrt(\$limit);        \$range = 0;        while(\$range<\$limit){            \$i .= '11';            \$range+=2;        }        \$n = 2;        while(\$n < \$sqrtlimit){            if (\$i[\$n]){                \$sqn = \$n*\$n;                \$k = \$sqn;                \$i[\$k]=0;                while(\$k<=\$limit){                    \$k += \$n;                    \$i[\$k]=0;                }            }            ++\$n;        }        \$n = 1;        while(\$n<\$limit){            if(\$i[\$n]) \$primes[] = \$n;            \$n+=2;        }        if(\$limit>=2) \$primes[0] = 2;        return \$primes;    }}  ```
This is the current example I'm working on

* 600 minutes @ Forge
* 360 minutes @ Logging Camp (Fir)
* 3000 minutes @ Mine (Iron)
* 720 minutes @ Mine (Sulfur)
* 600 minutes @ Plantation (General)
* 450 minutes @ Powder Mill
* 6000 minutes @ Quarry (Limestone)
* 1080 minutes @ Saltpeter Caves
* 240 minutes @ Tar Distillery
* 60 minutes @ Textile Mill
* 342 minutes @ Weaponsmith

this tells me I need

* 5.7 x Weaponsmith
* 7.5 x Powder Mill
* 6 x Logging Camp (Fir)
* 18 x Saltpeter Caves
* 12 x Mine (Sulfur)
* 10 x Forge
* 100 x Quarry (Limestone)
* 50 x Mine (Iron)
* 1 x Textile Mill
* 10 x Plantation (General)
* 4 x Tar Distillery

but it should always be a whole number and I don't know whether its my logic or my code

• You must compute the lcm for the subcomponents, too. Here's an example:
PHP Code:
``` <?php function gcd(\$a, \$b) // greatest common denominator {     while(\$b)     {         \$t = \$b;         \$b = \$a &#37; \$b;         \$a = \$t;     }     return \$a; } function lcm(\$a, \$b) // least common multiple -> much easier and faster to compute with gcd than with prime factorisation! {     return \$a * \$b / gcd(\$a, \$b); } \$times = array( // our data     'Forge' => 600,     'Logging Camp (Fir)' => 360,     'Mine (Iron)' => 3000,     'Mine (Sulfur)' => 720,     'Plantation (General)' => 600,     'Powder Mill' => 450,     'Quarry (Limestone)' => 6000,     'Saltpeter Caves' => 1080,     'Tar Distillery' => 240,     'Textile Mill' => 60,     'Weaponsmith' => 342);      \$syncTime = array_reduce(\$times, 'lcm', 1); // get the sync time, when all factories have finished producing a sub component \$components = array(); foreach(\$times as \$factory => \$time) // compute for each factory how many sub components it has produced at the sync time {     \$components[\$factory] = \$syncTime / \$time; } \$syncComponents = array_reduce(\$components, 'lcm', 1); // when will all factories have produced the same amount of sub comonents ? foreach(\$components as \$factory => \$parts) // compute the needed number of factories and display it {     echo \$syncComponents / \$parts,' ',\$factory,' needed<br>'; } ?> ```
Output:
Code:
```100 Forge needed
60 Logging Camp (Fir) needed
500 Mine (Iron) needed
120 Mine (Sulfur) needed
100 Plantation (General) needed
75 Powder Mill needed
1000 Quarry (Limestone) needed
180 Saltpeter Caves needed
40 Tar Distillery needed
10 Textile Mill needed
57 Weaponsmith needed```
dumpfi

• I tried that and on one of the recipes I'm looking at, its come up with negtive numbers - now thats impressive.

* 6 hours 12 minutes @ Carpenter
* 42 minutes @ Curing Shed
* 8 hours @ Fishing Lodge
* 49 hours 36 minutes @ Forge
* 42 hours @ Grain Mill
* 2 hours @ Hunting Lodge
* 12 hours 24 minutes @ Logging Camp (Oak)
* 248 hours @ Mine (Iron)
* 844 hours 48 minutes @ Plantation (General)
* 272 hours @ Plantation (Sugar)
* 7 hours @ Provisioner
* 496 hours @ Quarry (Limestone)
* 2 hours @ Rum Distillery
* 6 hours 48 minutes @ Sugar Refinery
* 96 hours @ Vineyard
* 1 hour 48 minutes @ Winery

* -7.51649237213E+013 x Provisioner
* -9.07133250853E+015 x Plantation (General)
* -7.51649237213E+012 x Curing Shed
* -8.59027699671E+013 x Fishing Lodge
* -4.50989542328E+014 x Grain Mill
* -2.14756924918E+013 x Hunting Lodge
* -2.14756924918E+013 x Rum Distillery
* -6.65746467245E+013 x Carpenter
* -5.32597173796E+014 x Forge
* -5.32597173796E+015 x Quarry (Limestone)
* -2.66298586898E+015 x Mine (Iron)
* -1.33149293449E+014 x Logging Camp (Oak)
* -7.30173544721E+013 x Sugar Refinery
* -2.92069417888E+015 x Plantation (Sugar)
* -1.93281232426E+013 x Winery
* -1.03083323961E+015 x Vineyard

•
Page 1 of 2 12 Last

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•