optimize the array with for loop - php

I agree to build a function that will calculate "priceinterval". This means that you build an array that you want to assign values for exampel number between 1-3 to assign "1-3" example $array [2] => "1-3" and 4-10 $array[5] => "4-10"
I've built a function that works but want optimize function, someone who is good at for-loops;)
public function CalcPris() {
$Prisinterval = array();
for ($i = 0; $i <= 3; $i++) {
array_push($Prisintervall, "1-3");
}
if ($i = 4) {
for ($i = 4; $i <= 10; $i++) {
array_push($Prisintervall, "4-10");
}
}
if ($i = 11) {
for ($i = 11; $i <= 50; $i++) {
array_push($Prisintervall, "11-50");
}
}
if ($i = 51) {
for ($i = 51; $i <= 100; $i++) {
array_push($Prisintervall, "51-100");
}
}
var_dump($Prisinterval);
}
the reason for this feature is that you should get a price floor.
in my next step is to check what the number "2" is worth, therefore, Please I build an array that has already been completed as has the value 1-100

your approach is totally off...
you want something like this:
function printerval($int){
if($int >= 1 && $int <= 3){
return "1-3";
}elseif($int >= 4 && $int <= 10){
return "4-10";
}elseif($int >= 11 && $int <= 50){
return "11-50";
}elseif($int >= 51 && $int <= 100){
return "51-100";
}
return "error";
}
calling printerval(2); will return the string "1-3"
well here is the stupid thing that seems to be requested:
function printerval(){
$arr= array();
for($i=1;$i<=100;$i++){
if($i >= 1 && $i <= 3){
$arr[$i]= "1-3";
}elseif($i >= 4 && $i <= 10){
$arr[$i]= "4-10";
}elseif($i >= 11 && $i <= 50){
$arr[$i]= "11-50";
}elseif($i >= 51 && $i <= 100){
$arr[$i]= "51-100";
}
}
return $arr;
}
although that is the wrong approach it should now answer the question..

Ok, to optimize this function, you should do the following:
Go to the nearest technical bookstore, or register at oreilly.com.
Buy a copy of Learning PHP5.
Read the book and understand the difference between if ($x = 4) and if ($x == 4).
Read the book and learn about for-loops and arrays.

Related

PHP - check if number is prime

I'm trying to create a function which checks whether the number is prime or not. BUT I want this function to echo to the user 'prime' or 'NOT prime' - and that's where my problem starts.
Let me show you my code:
class IsPrime
{
function check($num)
{
for ($i = 2; $i < $num; $i++)
{
if ($num % $i == 0)
{
echo 'NOT prime';
break;
}
}
echo 'Prime';
}
}
$x = new IsPrime();
$x->check(4);
The problem is that when I put any prime number - it works correctly, but when I put any not prime number - it also echos second echo, sth like this: 'NOT prime prime'.
How can I make it echo only the right answer ?
in 54 59 bytes:
function is_prime($n){for($i=$n;--$i&&$n%$i;);return$i==1;}
loops $i down from $n-1 until it finds a divisor of $n; $n is prime if that divisor is 1.
add 10 bytes for much better performance:
function is_prime($n){for($i=$n**.5|1;$i&&$n%$i--;);return!$i&&$n>1;}
loops $i from (approx.) sqrt($n) to 1 looking for a divisor with a post-decrement on $i.
If the divisor is 1, $i will be 0 at the end, and !$i gives true.
This solition uses a trick: For $n=2 or 3, $i will be initialized to 1 → loop exits in first iteration. For larger even square roots ($n**.5|0), |1 serves as +1. For odd square roots, +1 is not needed because: if $n is divisible by root+1, it is also divisible by 2. Unfortunately, this can cost a lot of iterations; so you better
add another 7 bytes for even better performance:
function is_prime($n){for($i=~-$n**.5|0;$i&&$n%$i--;);return!$i&$n>2|$n==2;}
$n=2 needs a special case here: inital $i=2 divides $n=2 → final $i=1 → returns false.
Adding 1 to $n instead of the square root is enough to avoid failures; but:
I did not count the iterations but only tested time consumption; and that only in TiO instead of a controlled environment. The difference between the last two versions was smaller than the deviation between several runs.
Significant test results may be added later.
This could be a long procedure if the number is really a prime number. There is a shorter procedure as well.
We need not run the for loop upto the number itself. Instead, we can run it upto the Highest Integer less than or equal to the square root of the number.
class IsPrime
{
function check($num)
{
$bCheck = True;
$highestIntegralSquareRoot = floor(sqrt($num));
for ($i = 2; $i <= $highestIntegralSquareRoot; $i++)
{
if ($num % $i == 0)
{
$bCheck = False;
break;
}
}
if $bCheck
echo 'Prime';
else
echo 'NOT prime';
}
}
$x = new IsPrime();
$x->check(97);
Now, in the above, if we check check whether 97 is prime or not (actually, it is), then the loop need not run from 2 to 97, but only from 2 to 9. (Square root of 97 is 9.8488578018, and highest integer less than or equal to that is 9. Similarly, we can check for number 121 (this is not a prime number, as it is divisible by 11). The limit will be increased from 2 to 11 in a similar matter. And so on.
Actually, we need to check the divisibility of the number by the smaller prime numbers in the vicinity, but that would be more complex.
Hope this helps.
As many answer pointed out, your logic code has a problem: when you get i such that num % i == 0, you print "NOT prime" and quit the loop, after that, you still print "Prime". Some guys moved echo "Prime" in if-else, it is still wrong. One way to approach, for example,
class IsPrime
{
function check($num)
{
$bCheck = True;
for ($i = 2; $i < $num; $i++)
{
if ($num % $i == 0)
{
$bCheck = False;
break;
}
}
if $bCheck
echo 'Prime';
else
echo 'NOT prime';
}
}
$x = new IsPrime();
$x->check(4);
<?php
function primeCheck($num)
{
if ($num == 1)
return false;
for ($i = 2; $i <= $num/2; $i++)
{
if ($num % $i == 0)
{
return false;
}
}
return true;
}
$primeNumber = primeCheck(17);
if ($primeNumber == true)
{
echo "Is Prime";
}
else
{
echo "Is Not Prime";
}
?>
The break is only breaking the for loop,
use return; instead. it will exit the function
Just use return:
class IsPrime
{
function check($num)
{
for ($i = 2; $i < $num; $i++)
{
if ($num % $i == 0)
{
echo 'NOT prime';
return; // that you need
}
}
echo 'Prime';
}
}
$x = new IsPrime();
$x->check(4);
if/else notation
return notation
You can find prime numbers and non prime numbers from 1 to your limit and its count.
public function prime_checker($count){
$counter=0;
$no_prime=0;
for($i=2 ; $i<=$count; $i++ ){
for($j=2 ; $j<$i ; $j++ ){
if($i % $j == 0){
echo $i.'is not prime<br/>';
$no_prime=$i;
break;
}
}
if($i != $no_prime){
$prime_numbers[$counter]=$i;
$counter=$counter+1;
}
}
echo '<br/>'.$counter.'prime numbers<br/><br/>';
for($i=0 ; $i<$counter ; $i++ ){
echo $prime_numbers[$i].' is prime<br/>';
}
}
You can check number is prime or not & without using loop with this function:
function is_prime($p) {
$r1 = $p%2;
$r2 = $p%3;
$r3 = $p%5;
return ($p > 1) && (($r1 >= 1) && ($r2 >= 1) && ($r3 >= 1)) || in_array($p, [2,3,5]);
}
Please Check this
class IsPrime
{
function check($num)
{
for ($i = 2; $i < $num; $i++)
{
if ($num % $i == 0)
{
return 'NOT prime';
}
}
return 'Prime';
}
}
$x = new IsPrime();
$result = $x->check(4);
echo $result;
try this
class IsPrime
{
function check($num)
{
for ($i = 2; $i < $num; $i++)
{
if ($num % $i == 0)
{
echo 'NOT prime';
break;
}
else
{
echo 'Prime';
}
}
//echo 'Prime';
}
}
$x = new IsPrime();
$x->check(3);
Put else part otherwise it will always return Prime
for ($i = 2; $i < $num; $i++)
{
if ($num % $i == 0)
{
echo 'NOT prime';
break;
}
echo 'Prime';
}
You can print "Prime" as a return to the function to ensure nothing is printed during the function except for the condition for "NOT prime".
class IsPrime
{
function check($num)
{
for ($i = 2; $i < $num; $i++)
{
if ($num % $i == 0)
{
echo 'NOT prime';
break;
}
}
return "Prime";
}
}
$x = new IsPrime();
echo $x->check(4);
$num = ceil(sqrt($num));
$is_prime = true;
for($j=3; $j<=$num; $j=$j+2){
if($i%$j == 0){
$is_prime = false;
break;
}
}
if($is_prime){
echo "No is Prime";
}
Note: Start loop from 2 as it is the only even prime no. Increment with 2 as no even no is a prime no.
=> Code for finding all prime no in range (2-100)
$limit = 100; $arr = array(2);
for($i=3; $i<=$limit; $i=$i+2){
$num = ceil(sqrt($i));
$is_prime = true;
for($j=3; $j<=$num; $j=$j+2){
if($i%$j == 0){
$is_prime = false;
break;
}
}
if($is_prime){
$arr[] = $i;
}
}
I made a similar one where a user types in a number and PHP checks if the number is prime or not.
HTML
<p>See if your number is a prime number</p>
<form>
<input type='number' name='number'>
<input type='submit' value='Check!'>
</form>
PHP
if ($_GET) {
$i = 2;
$isPrime = true;
while ($i < $_GET['number']) {
if ($_GET['number'] % $i == 0){
// Number is NOT prime
$isPrime = false;
}
$i++;
}
if ($isPrime){
echo '<p>'.$i.' is a prime number!';
} else {
echo '<p>'.$i.' is NOT a prime number';
}
}
Hopefully this works for you.
First, don't make a mistake here:
for ($i = 2; $i < $num; $i++)
and then:
if ($num % $i == 0) return false;
2 % 2 equals 0 and then 2 will result as NOT prime.
Next, you don't have to check even numbers, so after you check if $num == 2, better performance is:
for ($i = 3; $i < $num/2; $i += 2)
Notice $num/2 - you don't have to check beyond that point.
And even better is:
for ($i = 3; $i*$i <= $num; $i += 2)
This is because when you check for division with 2 and 3 all other NON prime numbers are product of two (or more) prime numbers (e.g. 49 = 7*7 or 55 = 5*11). In the worst case scenario your $i pointer would reach a square root of $num (like in 49 = 7*7). That's why you check until $i*$i <= $num.
PHP 4
You can do enough random checks ($i=20) to bring the false positive probability very low.
/*
The Rabin/Miller Algorithm.
*/
function is_prime($n, $i = 10)
{
if (($n == 1) == ($n & 1)) return $n == 2;
if ($n < 51529) // will not be repeated 7 times (deletable condition)
return ($n & 1) & (($n < 6) * 42 + 0x208A2882) >> $n % 30 && ($n < 49 || ($n % 7 && $n % 11 && $n % 13 && $n % 17 && $n % 19 && $n % 23 && $n % 29 && $n % 31 && $n % 37 && ($n < 1369 || ($n % 41 && $n % 43 && $n % 47 && $n % 53 && $n % 59 && $n % 61 && $n % 67 && $n % 71 && $n % 73 && ( $n < 6241 || ($n % 79 && $n % 83 && $n % 89 && $n % 97 && $n % 101 && $n % 103 && $n % 107 && $n % 109 && $n % 113 && ( $n < 16129 || ($n % 127 && $n % 131 && $n % 137 && $n % 139 && $n % 149 && $n % 151 && $n % 157 && $n % 163 && $n % 167 && ( $n < 29929 || ($n % 173 && $n % 179 && $n % 181 && $n % 191 && $n % 193 && $n % 197 && $n % 199 && $n % 211 && $n % 223))))))))));
for ($a = $c = $n - 1, $d = $c - 1, $b = 0; !($a & 1); $a >>= 1, ++$b) ;
for (; $i--;) {
do for ($e = $f = mt_rand(1, $d), $g = $n; ($e %= $g) && ($g %= $e);) ;
while ($e > 1 && $g > 1);
for ($e = $g = 1; $g <= $a; $g <<= 1) ;
for (; $g >>= 1; $e = ($e * $e) % $n, $g & $a && ($e = ($f * $e) % $n)) ;
if ($e == 1) continue;
for ($r = $b; $r-- ; $e = ($e * $e) % $n)
if ($e == $c) continue 2;
return 0;
}
return 1;
}
echo is_prime(2147483647); // 1
echo is_prime(PHP_MAJOR_VERSION); // You Know
This PHP4 variant of the Fermat test has a polynomial runtime in log($n).
Just use it for small numbers, when $n < 2147483647, otherwise it's gmp_prob_prime.
Thank You.
function is_prime($number)
{
return (bool) !preg_match('/^1?$|^(11+?)\1+$/x', str_repeat('1', $number));
}
Entire program is correct . But only you should do replace break with exit function .because break only used to exit loop which are enclosed with curly braces {} and exit are used to stop the execution of an entire script.
class IsPrime
{
function check($num)
{
for ($i = 2; $i < $num; $i++)
{
if ($num % $i == 0)
{
echo 'NOT prime';
break;
}
}
echo 'Prime';
}
}
$x = new IsPrime();
$x->check(4);
That is my solution. If you put the condition in the loop and break after it, it's never going to finish with the check.
$num = rand ( 1, 1000 );
$notPri = null;
for($check = 2; $check < $num; $check ++) {
if ($num % $check == 0) {
$notPri ++;
}
}
if ($neEpri == 0) {
echo $num . "<br>Prime!";
} else {
echo $num . "<br>Not a prime!";
}

PHP Loop Per Tens

How to make loop per tens like this one,
<?php
for ($i=0; $i < 30; $i++) {
if ($i == 1 || $ == 2 ... $i == 10) {
# code...
} elseif ($i == 11 || $ == 12 ... $i == 20) {
# code...
} else {
# code...
}
}
I need 1 2 3 4 5 is different from 11 12 13 14 15 and 21 22 23 24 25
There are several ways you could approach this :
1. Separate them
Since clearly, you're doing different code to the ranges 1-10, 11-20, a,d 21-30, then it would do you good to separate them into several for loops.
for ($i=1; $i <= 10; $i++) {
//code for $i 1-10
}
for ($i=11; $i <= 20; $i++) {
//code for $i 11-20
}
for ($i=21; $i <= 30; $i++) {
//code for $i 21-30
}
2. Put the conditionals inside one for loop, but use <= instead of ==
for ($i=1; $i <= 30; $i++) {
if($i <= 10){
//code for $i 1-10
}
else if($i <= 20){
// code for $i 11-20
}
else{
// code for $i 21-30
}
}
Alternatively, you could use $i > 0 && $i <= 10 for the if conditions if you prefer or for readability, but the above code does exactly the same with less.
Personally, for your specific example, I would prefer using the first option, as it is much more readable (for me).
How about this:
for($i = 0; $i < 30; $i++) {
switch (floor($i / 10)) {
case 0:
break;
case 1:
break;
default:
break;
}
}

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!

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

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