2
\$\begingroup\$

I have a program that prints the star pattern.

Starr Pattern is:

          * 
          * 
          * 
          * 
  * * * * * * * * * 
          * 
          * 
          * 
          * 

My code is:

$n=5;

for($i=0; $i<$n; $i++){

  for($k=$n-$i; $k>0; $k--){
      echo ' '.' ';
  }
  for($j=0; $j< ($tot = $i+1); $j++){

      if($i==$j && $tot<$n){
        echo '* ';
      }else{
          if($tot<$n){
            echo ' '.' ';  
          }else{
             echo '* ';
          }
      }


  }

  if($i == ($n-1)){
      for($l=$n-1; $l>0;$l--){
         echo '* ';      
       }
     }  
  echo '<br/>';

}

for($i=0;$i<$n;$i++){
  for($k=$n-$i; $k>0; $k--){
      echo ' '.' ';
  }

  for($j=0; $j< ($tot = $i+1); $j++){

      if($i==$j && $tot<$n){
        echo '* ';
            }else{
              echo ' '.' '; 
            }
    }
  echo '<br/>';
}

My question is that how can I calculate the complexity of this code?

And also Is there a good way to reduce loops?

\$\endgroup\$
  • \$\begingroup\$ Looks like a Plus + to me, guess it's just semantics.... \$\endgroup\$ – ArtisticPhoenix Mar 22 at 14:35
  • \$\begingroup\$ good way to reduce loops yes str_repeat and chunk_split you can see this example (a code golf answer I did) of what you can do with these 2, codegolf.stackexchange.com/questions/171679/… basically you could make one long string with the space or * by using str_repeat and then split it into rows with chunk_split \$\endgroup\$ – ArtisticPhoenix Mar 22 at 14:45
  • \$\begingroup\$ Thanks, @ArtisticPhoenix, I have seen it but didn't get any logic because of the code in a single line. \$\endgroup\$ – Gufran Hasan Mar 22 at 14:50
  • 1
    \$\begingroup\$ For example function f($n){$s='';$b=str_pad('*',($m=$n*2+1),' ',2);for($i=0;$i<$m;++$i)$s.=($i==$n)?str_repeat('*',$m):$b;return chunk_split($s, $m);} Sandbox \$\endgroup\$ – ArtisticPhoenix Mar 22 at 14:56
  • \$\begingroup\$ It looks nice. Can you please make me understand how it works. \$\endgroup\$ – Gufran Hasan Mar 22 at 14:59
3
\$\begingroup\$

It looks nice. Can you please make me understand how it works

For example

 function f($n){$s='';$b=str_pad('*',($m=$n*2+1),' ',2);for($i=0;$i<$m;++$i)$s.=($i==$n)?str_repeat('*',$m):$b;return chunk_split($s, $m);}

Output

     *     
     *     
     *     
     *     
     *     
***********
     *     
     *     
     *     
     *  

Sandbox

Let me write it in a way that is easier to see

$n = 5;
$row_len = $n*2+1;
$output = '';
//pad $n spaces on each side of *
$default = str_pad('*',$row_len,' ',STR_PAD_BOTH); //is = "     *     "

//loop once for each vertical row (same as width)
for($i=0;$i<$row_len;++$i){
    if($i==$n){
        //do the center line all *'s
        $output .= str_repeat('*',$row_len);//is = "***********"
    }else{
        //use the default line from above
        $output .= $default;
    }
}

//now we have a single line that is the length squared so we can chunk it
//into equal parts, to make a square
echo chunk_split($output, $row_len);  //is = "     *          *     ***********"

Sandbox

Basically we can create the " * " row by using string pad. Because we can pad spaces on both sides of a * up to the length of a row ($n*2)+1.

Then the center row, is just * so we can use string repeat to the length of the row for that line.

Last we take our big huge line of spaces and * and split it into chunks (\n) on the length of our row we want.

\$\endgroup\$
  • 2
    \$\begingroup\$ Hope that helps explain it a bit better. Basically were exploiting the fact that it conforms to a set pattern. So for example we know if $n is 5 to do 5 spaces a star and 5 more spaces ($n*2)+1 So we can just use String Pad for that and pad 5 spaces on each side. String Pad takes the total length of the string you want. So it's the full length of the row. \$\endgroup\$ – ArtisticPhoenix Mar 22 at 15:18
  • \$\begingroup\$ I think your output is skinnier than the OPs. \$\endgroup\$ – mickmackusa Mar 26 at 21:05
  • \$\begingroup\$ @mickmackusa - it is. I didn't put a space between * * the stars. Shouldn't be too hard to fix, but it adds a variable in. So I was too lazy .... lol \$\endgroup\$ – ArtisticPhoenix Mar 26 at 21:26
  • \$\begingroup\$ DEREGISTERED!!!! What have you done, you mad man! What causes a person to do that?!? An occupational requirement? Witness protection? \$\endgroup\$ – mickmackusa Apr 15 at 1:58
2
\$\begingroup\$

Here's my array-functional spin on the task. It is not likely to be faster than @ArtisticPhoenix's solution, but it provides the desired output without loop constructs or conditions. ...just different for the sake of being different.

The process generates a full-sized array of strings that "looks" like a vertical stroke of asterisks, then replaces the middle element with a horizontal stroke element.

Code: (Demo)

$size = 7;                                                     // circumference not radius 
$vertical = str_pad('*', $size * 2 - 1, ' ', STR_PAD_BOTH);    // row w/ central symbol
$result = array_fill(0, $size, $vertical);                     // top-to-bottom stroke of symbols
$result[$size / 2] = implode(' ', array_fill(0, $size, '*'));  // left-to-right stroke of symbols
echo implode(PHP_EOL, $result);

For improved readability, I've declared the single-use variable $vertical.

Output: (highlight the text with your cursor to see that the pattern has no unnecessary trailing spaces in any line.)

      *      
      *      
      *      
* * * * * * *
      *      
      *      
      *      

*notice that I am not bothering to floor() the "horizontal stroke" element key, because php casts float keys to integers. https://www.php.net/manual/en/language.types.array.php

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.