PHP Question: PHP Script Shape

Sunday, May 1, 2011 - 22:58

Question

Write a PHP script that will print out the following text in the correct diamond shape.

1
2
3
4
5
6
7
8
9
10
    *
   ***
  *****
 *******
*********
*********
 *******
  *****
   ***
    *










Answer

The diamond shape consists of 10 'levels' of stars. Each level consists of one or more stars and some whitespace that pushes the middle star into the middle of the line. Each line must also consist of an odd number of stars as an even number of starts can't have a middle star.

What we need to do to draw the shape is to loop from 1 until we reach the middle of the star and then go back down until we reach 1 again. Because we are only using odd numbers we can simply use 10 as the count of the number of levels and then increment by 2 until we reach that value before going back down the numbers again. The only thing we need to change when going down the levels is a check for an odd or even number of levels. If the number is even then we need to take 1 away so that we are still counting in odd numbers. The whitespace can be worked out by subtracting the increment value by the number of levels.

Rather than doing individual loops over the whitespace and star values we can use the PHP str_pad() function. The second parameter is the length that the string must be and the third parameter is a custom pad value, which we either put a space or a star. The first parameter is is string we need to pad, but as this isn't going to be used here we can just put a blank string.

We therefore end up with this code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Top of star
for ($i = 1; $i <= $levels; $i = $i + 2) {
  $whitespace = ($levels - $i / 2);
  echo str_pad('', $whitespace, ' ') . str_pad('', $i, '*') . "\n";
}
 
// Odd or even number of levels?
if ($levels % 2 == 0) {
  $downlevels = $levels - 1; 
} else {
  $downlevels = $levels; 
}
 
// Bottom of star
for ($i = $downlevels; $i >= 0; $i = $i - 2) {
  $whitespace = ($levels - $i / 2);
  echo str_pad('', $whitespace, ' ') . str_pad('', $i, '*') . "\n";
}

Some of you might have noticed that we are doing the same thing twice here. Essentially, the second loop is repeating the work done by the first loop, just in the opposite direction. What we can do to improve the efficiancy of this code is remove the second loop and make the first loop create a serires of array elements. We can then use a combination of the PHP implode() and array_reverse() functions to print the output from a single run of the loop. Changing the above code to incorporate these functions we get the following code.

1
2
3
4
5
6
7
8
9
10
11
12
$levels = 10;
$output = array();
 
for ($i = 1; $i <= $levels; $i = $i + 2) {
  $whitespace = ($levels - $i / 2);
  $output[] = str_pad('', $whitespace, ' ') . str_pad('', $i, '*');
}
 
echo implode("\n", $output);
echo "\n";
echo implode("\n", array_reverse($output));
echo "\n";

This prints out the following.

1
2
3
4
5
6
7
8
9
10
    *
   ***
  *****
 *******
*********
*********
 *******
  *****
   ***
    *

We can do some final tidying up of the output generated by removing the large amount of whitespace on the left hand side of the shape. We do this by creating a whitespace factor variable that is half of the number of levels, and subtracting this from the amount of whitespace generated. We can also wrap the code in a function call to make things more convenient when running.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function draw_diamond($levels) {
  $whitespaceFactor = $levels/2;
 
  $output = array();
 
  for ($i = 1; $i <= $levels; $i = $i + 2) {
    $whitespace = ($levels - $i / 2) - $whitespaceFactor;
    $output[] = str_pad('', $whitespace, '-') . str_pad('', $i, '*');
  }
 
  echo implode("\n", $output);
  echo "\n";
  echo implode("\n", array_reverse($output));
  echo "\n";
}
 
draw_diamond(10);

Running the above code gives us the following output, which is exactly the shape we are looking for.

1
2
3
4
5
6
7
8
9
10
    *
   ***
  *****
 *******
*********
*********
 *******
  *****
   ***
    *
Category: 
philipnorton42's picture

Philip Norton

Phil is the founder and administrator of #! code and is an IT professional working in the North West of the UK.
Google+ | Twitter

Comments

Nice Code

what about a half diamond just like this

1
12
123
1234
12345
123456
12345
1234
123
12
1

what's the code?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
 
for($i=1;$i<=6;$i++)
{    
        for($j=1;$j<=$i;$j++)
        {
                echo $j;
        }
        echo '<br>';
        echo " ";
}
for($i=8;$i>=3;$i--)
{
        for($k=1;$k<=$i-3;$k++)
        {
                echo $k;
        
        }
        echo '<br>';
}
?>

______________*
_____________ ***
____________ *****
___________ *******
__________ *********
_________***********
________*************
_______***************
_______***************
________*************
_________***********
__________*********
___________*******
____________*****
_____________***
_____________*
ur ans is showing this and i don't want "_" i want white space so please help me

philipnorton42's picture
Submitted by philipnorton42 on Wed, 08/03/2016 - 15:04

Corrected. You just needed to alter the str_pad() function a little.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 <?php
     
  for($i=0;$i<=6;$i++)
  {
     for($j=5;$j>=$i;$j--)
      {      echo "&nbsp";
  }
  
      
      for($j=0;$j<=$i;$j++)
          
      {      echo "*";
  }
    echo "<br>";
  }
    
  for($i=0;$i<=5;$i++)
  {
     for($j=1;$j<=$i+1;$j++)
      {      echo "&nbsp";
  }
           for($j=5;$j>=$i;$j--)
          
      {      echo "*";
  }
    echo "<br>";
  }
    
    ?>
Hope This Helps :P

Add new comment