divide samples (numbers) into tests (in the form of intervals) - php

I am trying to divide samples (numbers) into tests (in the form of intervals). But my results are not correct as per the below required result. The code below is working fine till samples of 20 or less than 20. But if more than 20 samples, the results are wired.
The result should come with this case :
If 19 samples - 2 tests: 1-10, 11-19
If 20 samples - 2 tests: 1-10, 11-20
If 21 samples - 3 tests: 1-10, 11-16, 17-21
If 23 samples - 3 tests: 1-10, 11-17, 18-23
If 24 samples - 3 tests: 1-10, 11-17, 18-24
If 31 samples - 4 tests: 1-10, 11-20, 21–26, 27-31.
<?php
$samples = 23;
$tests = 1;
if($samples > 10) {
$tests = ceil($samples/10);
}
echo $tests." tests\n";
$s = 1
for ($x = 0; $x < $tests; $x++) {
if($samples > 20) {
$c = $s.'-'.ceil($samples/$tests);
}
if($x > 0) {
$c = (ceil($samples/$tests)+1).'-'.$samples;
}
echo $c."\n";
}
?>
Result coming which is wrong:
3 tests : 1-8, 9-23, 9-23

Related

how can this algorithm be optimized

I am trying to find the smallest positive number that is evenly divisible by all of the numbers from 1 to 20 and here is the code:
$num = 2520;
$x = 1;
while($x < 21){
if($num % $x == 0){
$x++;
}else{
$num += 20;
$x = 1;
}
}
echo $num;
it gives a proper output in less than 1 minute. Is this execution time bad in the professional world? any way to optimize this?
P.S. I started from 2520 because it is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
Suggestion: find the primes of all integers in [1,20].
Eg, we have the primes {2,3,5,7,11,13,17,19}. So, if the solution is divisible
by all integers in [1,20], then surely it is divisible by each element in this
list of primes. So, at a minimum, our solution is >= 2*3*5*7*11*13*17*19, right?
Now the problem is how clever we can be about constructing candidate solutions
larger than that number. Well, let's first see how much of the solution is done...
Is 2*3*5*7*11*13*17*19 divisible by 4? No. So, let's multiple by 2 to get
2*2*3*5*7*11*13*17*19, which surely is divisible by 2*2...
Is 2*2*3*5*7*11*13*17*19 divisible by 6? Yes.
Is 2*2*3*5*7*11*13*17*19 divisible by 8? ....
You get the picture. While I am not sure, I believe this approach will
result in the right answer -- ie, the smallest integer divisible by each
integer in [1,20].
use modified Sieve of Eratosthenes for massive speed up
http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
but do not use array instead iterate just indexes
something like
1.int ix[20]={1,2,3,4,...20};
2.now write a loop
where you will increment all ix[i]+=i+1; where i=<0;18>
while ix[i]>=ix[19]
if at the end all ix[i] are the same then its contens is the result so stop/return whatever
3.if not then increment also ix[19]+=20;
and continue with the loop on bullet 2
[notes]
can be easily changed for searing for divisible by any numbers not just divisible by 1..20
This sounds like Project Euler's Problem 5.
What we are finding here is the least common multiple of numbers 1 to 20. You can find this with help form the greatest common divisor:
function gcd($a, $b) {
if ($a == 0) return $b;
return gcd($b % $a, $a);
}
function lcm($a, $b) {
return $a * $b / gcd($a, $b);
}
function smallestDiv($n) {
$div = 1;
for ($i = 1; $i <= $n; $i++) {
$div = lcm($div, $i);
}
return $div;
}
echo smallestDiv(20);
Pardon my PHP. It's been a while since I have written any.
Note that we can also find the answer via prime factorization of each of the numbers and looking for the largest exponents as described here and in Kode Charlie's answer:
2 = 2
3 = 3
4 = 2²
5 = 5
6 = 2 × 3
7 = 7
8 = 2³
9 = 3²
10 = 2 × 5
11 = 11
12 = 2² × 3
13 = 13
14 = 2 × 7
15 = 3 × 5
16 = 2⁴
17 = 17
18 = 2 × 3²
19 = 19
20 = 2² × 5
lcm(1,2,…20) = 2⁴ × 3² × 5 × 7 × 11 × 13 × 17 × 19 = 232,792,560

fill 2 dimensional array random in a bingo way

I've got these two functions:
function drawNumber($drawnNumbers){
$unique = true;
while ($unique == true){
$number = mt_rand(10, 69);
if (!in_array($number, $drawnNumbers)){
return $number;
$unique = false;
}
}
}
fillCard(); ?>
It's a bingo game. The card gets filled with random Numbers. But I can't get it like this:
column column column column column column
row 10 13 16 14 16 19
row 24 26 28 29 23 21
row 36 33 39 30 31 35
row 46 48 42 45 43 47
row 59 56 51 52 58 50
row 60 65 68 62 61 67
So I would like to have the first row with numbers from 10 to 19
the second row from 20 to 29 and so on.
I tried like this
<?php drawnNumber(): $number = mt_rand(0,9);
fillArray(): $number = $row . $number; ?>
But that doesn't work, because there are double numbers in the card.
So before that I tried it in a different way,with in_array:
<?php
function fillCard(){
$card = array();
/* fill card with random numbers */
for($i = 0, $min = 10, $max = 19; $i < 6; $i++, $min+=10, $max += 10)
{
for($j = 0; $j < 6; $j++)
{
$number = mt_rand($min,$max) ;
if(!in_array($number, $card){
$card['row' . $i]['column' . $j]['number'] = $number;
$card['row' . $i]['column' . $j]['found'] = 0;
}
}
}
var_dump($card);
return $card;
} ?>
But there are still double random numbers in the card.
I tried a few other thinks in the last two weeks, but I just can't get it to work together.
If one thing succeeds the other thing fails.
I can get the random numbers but not unique random numbers in the card.
I hope someone can help me.
(for extra information: it's a bingo game. So drawnNumber() are the "balls", which get drawn
and stored in the array $drawnNumbers, they also are unique random numbers. fillCard() is the
function that fills the bingo card and checks if $drawNumber is in $card)
I would appreciate some help, if someone can tell me how to get it to work. Maybe in
an algorithm way or else some code?
Thank you in advance.
In general, you draw from some kind of box, right? So do the same, have an array with all available numbers and once you get a random number out of it, remove it, so the next time you search for a number, you will only pick from the remaining ones. Small example:
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
we pick a random number between 0 and 3 inclusive (0 and the length - 1 of a that is). Let's say we picked index 2, then a will look like:
a[0] = 1
a[1] = 2
a[2] = 4
Now if you draw a number between 0 and 2 (note that you take the length - 1 of a!), you won't re-pick the already chosen number in any way thus giving you unique numbers ALL the time.
P.S. this is a simplified version, but now if you can apply that to yourself and, for your example, create several arrays you will pick from.
The simplest way would be to have an additional flat array to keep track, and loop mt_rand
Here's an example of the meat of things:
$drawn = array();
// Loop around until you have a new number in the desired range
do {
$number = mt_rand($min,$max);
} while(in_array($number, $drawn));
// And save it to the $drawn array
$drawn[] = $rand;
To clarify, the above snippet (without the initialization of $drawn) is meant to replace the line
$number = mt_rand($min,$max) ;
in your code.
define('NB_ROWS', 6);
define('NB_COLS', 6);
$rows = range(10, NB_ROWS * 10, 10);
$bingo = array();
foreach($rows as $rowIndex)
{
$availNumbers = range(0, 9);
$line = array();
for($cellIndex = 0; $cellIndex < NB_COLS; $cellIndex++)
{
// pick a random value among remaining ones for current line
$numIndex = rand(0, count($availNumbers)-1);
list($value) = array_splice($availNumbers, $numIndex, 1);
$line[] = $value + $rowIndex;
}
$bingo[] = $line;
}
print_r($bingo);

PHP Counting Negative Numbers and Bold Only Even Numbers

On a form, I used PHP to display every number from 1 to the entered number. For example, if I enter 10 on the form, it displays 1 2 3 4 5 6 7 8 9 10. Now, I want it to be able to handle negative numbers by counting up to 0 (-10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0) and make every even number in the results bold, e.g., 2 4 6 8 10, etc.). I've searched exhaustively for the answers without any luck. How would any of you suggest doing this? My code for the first part is displayed below. Thank you in advance.
<?php
$num = $_POST['num'];
$limit = $_POST['num'];
echo "<pre>";
do {
echo ($counter).'<br>';
$counter++;
} while ($counter <= $limit);
echo "<pre>";
?>
You can do this
<?php
$num = $_POST['num'];
$limit = $_POST['num'];
echo "<pre>";
do {
if( $counter % 2 == 0 )
{
echo "<strong>" . $counter . "</strong><br />";
}
else
{
echo ($counter).'<br>';
}
$counter++;
} while ($counter <= $limit);
echo "<pre>";
?>
Solution 1
Ok, some more information about the %. This is a modulo. It gives you back the remaining number if you divide it by the mod number. For example
0 % 2 = 0
1 % 2 = 1
2 % 2 = 0
3 % 2 = 1 this because 3 / 2 = 1 and a bit,
you can't divide the last 1 completely by 2. So remain 1
4 % 2 = 0
Solution 2
Like crush said, you can use $counter & 1. What does this do?
If you look at a number bitwise. You want to AND it wit 1.
Bitwise number 2 = 0010 AND it with 0001 and your return will be 0000 (zero).
Bitwise number 3 = 0011 AND it with 0001 and your result will be 0001 (one).
If you ceep that going and only check the last bit, you can see if it is a even number. More about bitwise operations.

Project Euler Spoilers, #001 - PHP Sums

I cannot ask for help on their forums, but i've been at this for 3 hours now. Spoilers Below I don't understand what i'm doing wrong. The question is:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
Here's my equation I made.
for($total = 0, $f = 5, $t = 3; $t < 1000; $t+=3){
if($f < 1000)
{
$total += $f + $t;
echo "Five: $f, Three: $t = $total<br />";
$f += 5;
}
else
{
$total += $t;
echo "Five: $f, Three: $t = $total<br />";
}
}
The answer is:233168. Where's my error?
You are counting numbers that are divisible both by 3 and 5 twice.
Suppose S(3) denotes sum of numbers divisible by 3 and S(5) denotes sum of numbers divisible by 5 till a given number n, then sum of numbers divisible by 3 or 5 is given by
S(3 U 5) = S(3) + S(5) - S(3 ∩ 5)
where S(3 ∩ 5) denotes sum of those numbers divisible by both 3 and 5.
In your case, you are calculating S(3 U 5) = S(3) + S(5) and hence getting wrong answer.

Tournament algorithm in php

I need some help. I want to create one tournament. Let's say I have 6 players. 1 2 3 4 5 6
I want to create some.. lets' say stages... Every player will play 5 matches(number of players - 1), in 5 different stages. In one stage, all the players must appear only once.
For example, with 6 players I want to generate these results:
Squad 1:
1-2
3-4
5-6
Squad 2:
1-3
2-5
4-6
Squad 3:
1-4
2-6
3-5
Squad 4:
1-5
2-4
3-6
Squad 5:
1-6
2-3
4-5
So, in every stage, the matches must be unique, and every player must play with every player.
I want one algorithm that will work even if I want 8 players, or 12, or 16, or 28.
Thanks
<?php
$numplayers = 6;
if ($numplayers % 2 != 0) $numplayers++; // Dummy
for ($round = 0;$round < $numplayers - 1;$round++) {
echo 'Squad ' . ($round+1) . ":\n\n1-";
for ($i = 0;$i < $numplayers-1;$i++) {
if ($i % 2 == 0) {
$player = ($numplayers-2) - ($i/2) - $round;
} else {
$player = ((($i-1)/2) - $round);
}
if ($player < 0) $player += $numplayers - 1;
echo ($player+2);
echo ($i % 2 == 0) ? "\n" : '-';
}
echo "\n\n";
}

Categories