Complicated Star Pattern? - php

Okay, so I have a unique problem that I ran into when trying to code a 5x3 star pattern. I can do the for loops to get the 5x3, that's easy. However I need something different than a square.
We can have a maximum of 15 stars. So printing out a full block would look like this:
* * *
* * *
* * *
* * *
* * *
But we can pass in a parameter for the number of stars that we want. So let's pass in 11 instead of 15. We should get:
* * *
* * *
* * *
* *
However, with 11 as my parameter the output is like this:
*
* *
* *
*
It prints out the correct number of rows with the incorrect number of stars. I know why this is, and it's because of the modulus in my code. I also tried a different approach, which printed out one less row than needed. I am stuck and not sure where to go from here.
Here is my code:
<?php
$num = 11;
$rows = ceil($num/3);
$count - 0;
for($j = 0; $j < $rows; $j++){
echo '<div class="row-fluid"><ul class="thumbnails">';
for($i = $num%3; $i < 3; $i++){
echo '*';
$count++;
}
$num-=$count;
echo '</ul></div>';
}
?>

With some simple PHP-Fu:
$stars = 11;
$row_length = 3;
$array = array_fill(0, $stars, '*');
$array = array_chunk($array, $row_length);
$table = '<table border="0">';
foreach($array as $row){
$table .= '<tr><td>'. implode('</td><td>', $row) .'</td></tr>';
}
$table .= '</table>';
echo $table;
Online demo.

The idea should be as simple as: keep drawing until you reach the target number.
So you could do this:
$num = 11;
for( $i=0; $i<$num; $i+=3) {
echo "<div class=\"row-fluid\"><ul class=\"thumbnails\">";
for( $j=0; $j<3 && $i+$j<$num; $j++) {
echo "*";
}
for( ; $j<3; $j++) { // finish the current row (optional, remove if not needed)
echo " ";
}
echo "</ul></div>";
}

Ooh a puzzle!
I don't know if using for was a requirement for your assignment, I prefer while.
$num_of_stars = 15;
$stars_per_row = 3;
while($num_of_stars > 0){
echo "*";
if($stars_per_row == 1){
$stars_per_row = 3;
echo "<br />";
}else{
$stars_per_row --;
}
$num_of_stars --;
}

I don't see why you would have to use two for-loops.
I would do something like this: (I noticed you don't have any <li>'s in your code) Of course you would have to set the class="thumbnails" to include list-style-type:none;
<?php
$num = 11;
$cols = 3;
echo '<div class="row-fluid"><ul class="thumbnails">';
$count = 0;
for($j = 0; $j < $num; $j++){
$count++;
echo '<li style="float:left;">*</li>';
if ($count>=$cols) {
$count = 0;
echo '<li style="clear:both;"></li>';
}
}
echo '</ul></div>';
?>

For this to work, this is what you need.
$num = 11;
$cols = 3;
$rows = ceil($num/$cols);
for($j=0;$j<$rows;$j++)
echo "<div class='row'>";
for($i=0;$i<$cols;$i++){
echo "*";
}
echo "</div>";
}
To show where you went wrong in your code. First, your definition of $count should be = not -. Next, your inner for loop is odd.
First loop through, $num is equal to 11. In your inner loop you set $i = $num%3 which is $i = 2. So the inner loop runs through once while $i++ < 3, echo's one star and increments count once. inner loop exits, you subtract $count from $num making $num=10 and row is completed, next outer loop iteration.
Next time the inner loop runs, $num is 10 so $i = $num%3 becomes $i=1. Inner loop runs 2 times while $i++ < 3, echo'ing 2 more stars and incrementing $count both times making it now 3. after the inner loop you subtract 3 more from $num making it 7 and row ends, outer loop continues.
Next inner loop, $num is 7 so $i = $num%3 becomes $i=1. Inner loop runs 2 times while $i++ < 3, echo'ing 2 more stars and incrementing $count both times making it now 5. after the inner loop you subtract 5 from $num making it now 2, row ends, outer loop continues.
Last iteration of the outer loop (row limit hit), $num is 2 so $i = $num%3 becomes $i=1. Inner loop runs once, echo's one star and inrement count once making it now 8. Inner loop finishes, you subtract 8 from $num making it now -6, row ends, outer loop ends.

Related

Reflective pattern of numbers in rows and columns of html table using loops

I'm stuck trying to use nested loops to make a reflective pattern from numbers.
I've already tried, but the output looks like this:
|0|1|2|
|0|1|2|
|0|1|2|
This is my code:
<?php
echo "<table border =\"1\" style='border-collapse: collapse'>";
for ($row=1; $row <= 3; $row++) {
echo "<tr> \n";
for ($col=1; $col <= 3; $col++) {
$p = $col-1;
echo "<td>$p</td> \n";
}
echo "</tr>";
}
echo "</table>";
?>
I expected this result:
|0|1|0|
|1|2|1|
|0|1|0|
Each columns' and rows' cell values must increment to a given amount then decrement to form a mirror / palindromic sequence.
First declare the square root of the of the table cell count. In other words, if you want a 5-by-5 celled table (25 cells), declare $size = 5
Since your numbers are starting from zero, the highest integer displayed should be $size - 1 -- I'll call that $max.
I support your nested loop design and variables are appropriately named $row and $col.
Inside of those loops, you merely need to make the distinction between your "counters" as being higher or lower than half of the $max value. If it is higher than $max / 2, you subtract the "counter" (e.g. $row or $col) from $max.
By summing the two potentially adjusted "counters" and printing them within your inner loop, you generate the desired pattern (or at least the pattern I think you desire). This solution will work for $size values from 0 and higher -- have a play with my demo link.
Code: (Demo)
$size = 5;
$max = $size - 1;
echo "<table>\n";
for ($row = 0; $row < $size; ++$row) {
echo "\t<tr>";
for ($col = 0; $col < $size; ++$col) {
echo "<td>" . (($row >= $max / 2 ? $max - $row : $row) + ($col >= $max / 2 ? $max - $col : $col)) . "</td>";
}
echo "</tr>\n";
}
echo "</table>";
Output:
<table>
<tr><td>0</td><td>1</td><td>2</td><td>1</td><td>0</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>2</td><td>1</td></tr>
<tr><td>2</td><td>3</td><td>4</td><td>3</td><td>2</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>2</td><td>1</td></tr>
<tr><td>0</td><td>1</td><td>2</td><td>1</td><td>0</td></tr>
</table>
There are a lot of ways to achive that.
An easy way to do that is;
<?php
$baseNumber = 0;
echo "<table border='1' style='border-collapse: collapse'>";
for ($row = 0; $row < 3; $row++) {
echo "<tr>";
if ($row % 2 !== 0) {
$baseNumber++;
} else {
$baseNumber = 0;
}
for ($col = 0; $col < 3; $col++) {
echo "<td>" . ($col % 2 === 0 ? $baseNumber : $baseNumber + 1) . "</td>";
}
echo "</tr>";
}
echo "</table>";
this code will do what you want just call the patternGenerator function with the number of distinct numbers you want for your example these numbers are 3 (0,1,2).
the idea in this code is to use two for loops one that starts from the minimum number to the maximum one and the other one that starts after the maximum number decreasing to the minimum.
for example:
if min = 0 and max = 5
the first loop will print 0,1,2,3,4,5
and the second will print 4,3,2,1,0
and that's it.
at first, I created a function that creates just on row called rowGenerator it takes $min and $max as parameters and prints one row
so if we want to print a row like this: |0|1|0| then we will call this function with min = 0 and max = 1 and
if we want to print a row like this: |1|2|1| then we will call it with min = 1 and max = 2.
function rowGenerator($min, $max)
{
echo '<tr>';
for($i = $min; $i<=$max;$i++)
echo '<td>'.$i.'</td>';
for($i = $max-1; $i>=$min;$i--)
echo '<td>'.$i.'</td>';
echo '</tr>';
}
for now, we can print each row independently. now we want to print whole the table if we look at the calls we do for the rowGenerator function it will looks as follow:
(min = 0, max = 1),
(min = 1, max = 2) and
(min = 0, max = 1).
minimums are (0,1,0).
yes, it's the same pattern again. then we need two loops again one to start from 0 and increase the number until reach 1 and the other one to loop from 0 to 0.
and that's what happened in the patternGenerator function. when you call it with the number of distinct numbers the function just get the min that will always be 0 in your case and the max.
function patternGenerator($numberOfDistinct )
{
echo "<table border =\"1\" style='border-collapse: collapse'>";
$min = 0;
$max = $numberOfDistinct - 2;
for($i = $min;$i<=$max; $i++)
{
rowGenerator($i,$i+1);
}
for($i = $max-1;$i>=$min;$i--)
{
rowGenerator($i,$i+1);
}
echo '</table>';
}
this is the output of calling patternGenerator(3):
the output of calling patternGenerator(5):

Finding the averege in a loop counting to 100

I need to find the averege after using a loop counting ever 3rd to a 100. The loop part is easy enough, but I need to sum every value then divide the sum on the total of values.
for ($x = 3; $x < 100; $x+=3) {
echo $x.", ";
}
This is the loop I need to use. How to I sum the values this produces and how do I find how many values this loop produces?
I believe the intention here is to learn about loops, otherwise this stuff can be done without looping too.
For learning purpose, you can simply introduce two variables count and sum and compute them inside the loop. For count, you just increment it on each iteration. For sum, you add the current value of x into sum. After the loop you print both variables.
$count = 0;
$sum = 0;
for ($x = 3; $x < 100; $x+=3) {
echo $x.", ";
$count++;
$sum+=$x;
}
echo $sum;
echo $count;
add your elements into an array and then use array_sum to sum the array elements , then divide the sum by the count of your array
$arr = [];
for ($x = 3; $x < 100; $x+=3) {
// echo $x.", \n";
$arr[] = $x;
}
print_r(array_sum($arr) / count($arr));
// Output : 51
$i=0;
$tempx=0;
for ($x = 3; $x < 100; $x+=3) {
//total sum
$tempx = $tempx + $x;
//count of how many times the loop ran in this case 33 times
$i++;
}
//first $i was 0 so we add 1
$i=$i + 1;
//getting the average
$average=$tempx / $i;
echo $average;
//output
For the last answer i think we should not do:
//first $i was 0 so we add 1 $i=$i + 1;
Regards

PHP Dubble For Loop

I need to make a loop in php that says 1*9 = 9 2*9 = 18 and 1*8 = 8 and 1*7 = 7 etc in loop so the result will be this:
1*7 = 7
2*7 = 14
3*7 = 21
1*8 = 8
2*8 = 16
3*8 = 24
1*9 = 9
2*9 = 18
3*9 = 27
And I need to use a nested loop for that i tried some things out but i cant get it to work here is what is did. But for the most part i don't really understand what nested loops do and what there used for. hope you can help me thanks!
for ($tafel7 = 0; $tafel7 <= 9; $tafel7++) {
for($tafel7 = 0; $tafel7 <= 9; $tafel7++){
for($tafel7 = 0; $tafel7 <= 9; $tafel7++){
$antwoord9 = $tafel7 * 9;
echo "$tafel7 x 8 = $antwoord9 <br>";
$antwoord8 = $tafel7 * 8;
echo "$tafel7 x 8 = $antwoord8 <br>";
$antwoord7 = $tafel7 * 7;
echo "$tafel7 x 7 = $antwoord7 <br>";
};
};
};
Your question is not as clear but if you just want the exact result, here's the code:
for($i = 7; $i <= 9; $i++){
for($j = 1; $j <= 3; $j++){
$result = $i * $j;
echo $j." * ".$i." = ".$result."<br>";
}
}
If you need to print complete tables, then try this:
for($i = 1; $i <= 9; $i++){
for($j = 1; $j <= 10; $j++){
$result = $i * $j;
echo $i." * ".$j." = ".$result."<br>";
}
}
As far as the explanation is concerned, then listen:
A normal loop works by executing a block of statement(s) again and again until a condition is met.
So, nested loops are basically loops in another loop. This means that the block of code will be executed 'n' number of times by the inner loop, and then the inner loop will again be executed by the outer loop, again 'n' number of times.
'n' means whatever the number of times the conditions are met for the respective for loops.
Hope you got my explanation!
You need to loop over your two variables, (1) the left operand and (2) the right operand
for ($right = 7; $right <= 9; $right++) {
for ($left = 1; $left <= 3; $left++) {
$product = $left * $right;
echo "{$left} x {$right} = {$product} <br>";
}
}
In this example, I have to loops one with the times table you want eg 7, 8 and 9 "tafel" and the other one with how many times you want it to run for each times table "$hoeveel". This can easily be altered to more times tables or how many times you want to run, you also only need to export the values once as it cycles through the loops anyways. Hope it helps.
for ($tafel = 7; $tafel <= 9; $tafel++) {
for ($hoeveel = 1; $hoeveel <= 3; $hoeveel++) {
$antwoord = $tafel * $hoeveel;
echo "$tafel x $hoeveel = $antwoord <br>";
}
}

Finding the difference between 2 dates and iterating an image based on the difference

Ive managed to loop through a table and get the difference in days between 2 dates adjacent to each other in the table.
Multiple entries have the same date, i have it now that when that date changes, it displays an image however i want it to display the image as many times as the difference in date
$sql = mysql_query("SELECT * FROM Films_Info")
or die(mysql_error());
$last_value = null;
while ($row = mysql_fetch_assoc($sql)) {
if (!is_null($last_value)) {
$a = new DateTime($row['FilmRelease']);
echo "<p>".$row['FilmName']."</p>";
$interval = $a->diff(new DateTime($last_value));
//echo $interval->format('%d days');
$i = 0;
}
$howManydays = $interval->days;
for ( $i; $howManydays; $i++) {
echo "<img src=\"day.jpg\" />";
$howManydays = 0;
}
$last_value = $row['FilmRelease'];
}
for ( $i = 0; $i < $howManydays; $i++) The second is a conditional statement telling when the loop should stop.
The first section in the for loop where it says $i = 0 initialized the variable $i to 0 and then tests the condition $i < $howManydays.
Let's say $howManydays equals 1. That means 0 < 1, so the loop will perform.
At the end of the loop, the third section is called ($i++), so $i is incremented and now equals 1. The second section is called again to test conditions $i < $howManydays which is asking if 1<1 which it's not, so the loop will exit.
So if $howManydays is greater than 0, the loop should happen the integer amount that is in $howManydays.
You will want to remove $howManydays = 0; within the for loop, if you don't want it to only fire once.
The for loop
for ( $i = 0; $i < $howManydays; $i++){
// ...
}
is somewhat equivalent to the while loop:
$i = 0;
while ( $i < $howManydays ){
// ...
$i++;
}
http://php.net/manual/en/control-structures.for.php for more information
In your code above, you should also check if interval was set. You should probably just do an if rather than a while, if only need one interval.
you could just do a simple division on the interval and print out the image that many times
$last_value_u = $last_value->format('U');
$a_u = $a->format('U');
$interval = $a_u - $last_value_u;
$image_count = intval($interval/86400);
for($i=0;$i<$image_count;$i++)
echo "<p><img src=\"day.jpg\" /></p>";
Update
An alternative option would be to loop through the interval:
for($i=$last_value_u;$i<$a_u;)
{
if(intval(($a_u - $i)/86400) == X)
{
// run special code for specific day
}
else
{
// run code for every other day
}
$i+=86400;
}

PHP loop to sort table

I'm querying a database for names that are numbered 1-26 alphabetically. I have the following code, but since HTML is structured tr then td, the table appears alphabetically by row as opposed to by column. How can I make it appear in order by column?
$query = mysql_query("SELECT name FROM people WHERE main=1 ORDER BY id");
$i = 0;
while($result = mysql_fetch_array($query)) {
$name = $result['name'];
if ($i % 5 == 0) echo "<tr>\n";
echo "<td width=\"150\">";
echo "".$name."<br />";
echo "</td>\n";
$i++;
if ($i % 5 == 0) echo "</tr>\n";
};
alpha beta charlie
delta echo foxtrot
vs.
alpha charlie echo
beta delta foxtrot
Also, I'm open to reworking the code if there's a more efficient way.
You could just access the output array in strides. Compute how many rows you need as the number of results divided by 5, and use the row count as the stride.
$ncols = 5;
$nrows = $nresults / $ncols + ($nresults % $ncols == 0 ? 0 : 1);
for ($i = 0; $i < $nrows; $i++)
{
// start row
for ($j = 0; $k < $ncols; $j++)
{
// print $results[$nrows * $j + $i]
}
// end row
}
You'll have to transfer your query results into an array $results first. Since you'll have to know the total number of results, this is sort of mandatory, though I'd be curious if anyone has a solution that can work while fetching the results.
Update: See Justin's answer for a cool solution that grows the output while fetching the query results line by line. Since it's currently being worked on, here's a summary (credits to Justin):
$nresults = mysql_num_rows($query);
$ncols = 5;
$nrows = (int) ceil($nresults / $ncols);
$i = 0; $cols = array_fill(0, $nrows, "");
while ($result = mysql_fetch_array($query))
$cols[$i++ % $nrows] .= "<td>$result['name']</td>";
echo "<tr>" . implode("</tr><tr>", $cols) . "</tr>";
Edit:
After the discussion in the comments between myself, Kerrek SB and the OP bswinnerton, the following code seems to be the most effective:
$columns = 3;
$rowcount = mysql_num_rows($query);
$rows = ceil($rowcount / $columns);
$rowdata = array_fill(0, $rows, "");
$ctr = 0;
while ($result = mysql_fetch_array($query))
$rowdata[$ctr++ % $rows] .= '<td>'.$result['name'].'</td>';
echo '<tr>'.implode('</tr><tr>',$rowdata).'</tr>';
This will create three columns, filled vertically (my original answer would create three rows). It also properly initializes the array (preventing PHP warnings), yields a correct row count for result counts that aren't divisible by the column count, and incorporates Kerrek's clever "calc-row-in-the-subscript" trick.
Original Post:
You could use arrays and implode() This way, you only have to make one pass through your results:
$row = 0;
$rows = 3;
$rowdata = array();
while($result = mysql_fetch_array($query))
{
if ($row >= $rows) $row = 0;
$rowdata[$row++] .= '<td>'.$result['name'].'</td>';
}
echo '<tr>'.implode('</tr><tr>',$rowdata).'</tr>';

Categories