To print diamond asterisk pattern based on inputs

I have to print the number of stars that increases on each line from the minimum number until it reaches the maximum number, and then decreases until it goes back to the minimum number. After printing out the lines of stars, it should also print the total number of stars printed.

I have tried using shell scripting and worked. But is there any other simplified and generic way to achieve this

echo "enter the mininum number "
read min
echo "enter the maximum number "
read max
for (( i=$min;i<=$max;i++))
do
   for (( j=$max;j>=i;j-- ))
   do
   echo -n " "
   done
   for (( c=1;c<=i;c++ ))
   do
   echo -n " *"
   sum=`expr $sum + 1`
   done
echo ""
done
d_max=`expr $max - 1`
for (( i=$d_max;i>=$min;i--))
do
   for (( j=i;j<=$d_max;j++ ))
   do
   if [ $j -eq $d_max ]
   then
   echo -n " "
   fi
   echo -n " "
   done
   for (( c=1;c<=i;c++ ))
   do
   echo -n " *"
   sum=`expr $sum + 1`
   done
echo ""
done
echo "Total No. : "  $sum

Exepcted output

 

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

faint memories... awk diamond code golf (just for fun!)

1 Like

Ancient books might tell you to

sum=`expr $sum + 1`

But only the old Bourne shell needs the external expr command for math ops.
Recent standard shells have

sum=$((sum + 1))

And, since you use (( )) with for, you can even try

((sum += 1))

or

((sum++))
echo "enter the mininum number "
read min
echo "enter the maximum number "
read max
stars=$(printf '%*s' $(( $max * 2 )) '')
stars=${stars//  / *}
cnt=0;
for (( i=$min;i<=$max;i++)); do printf "%*s%s\n" $((( max - i + 1 ))) " " "${stars:1:$((( $i * 2 )))}" ; (( cnt = cnt + i )) ; done
for (( i=$max-1;i>=$min;i--)); do printf "%*s%s\n" $((( max - i + 1 ))) " " "${stars:1:$((( $i * 2 )))}"; (( cnt = cnt + i )) ;done
echo Total: $cnt

Fully dash/POSIX shell only compliant.
Uses terminal escape codes for fun.

#!/usr/local/bin/dash
# DIAMOND.sh
# POSIX compliant, with no input error checking.
# Using terminal escape codes just for fun.

echo "Enter minimum value:"
read -r MIN
echo "Enter maximum value:"
read -r MAX
printf "\033c\n"
STRNG="* "
COUNT=1
STAR="${STRNG}"
HORIZ=34
VERT=4
while [ ${COUNT} -lt ${MIN} ]
do
    STRNG="${STRNG}"'* '
    COUNT=$(( COUNT + 1 ))
done

STAR="${STRNG}"
COUNT=$(( MAX + 1 ))
while [ ${COUNT} -ge ${MIN} ]
do
    printf "%b" "\033["${VERT}";"${HORIZ}"f${STAR}"
    STAR="${STAR}${STRNG}"
    COUNT=$(( COUNT - 1 ))
    HORIZ=$(( HORIZ - MIN ))
    VERT=$(( VERT + 1 ))
done
HORIZ=34
VERT=$(( VERT + MAX - MIN ))
STAR="${STRNG}"
COUNT=$(( MAX + 1 ))
while [ ${COUNT} -ge ${MIN} ]
do
    printf "%b" "\033["${VERT}";"${HORIZ}"f${STAR}"
    STAR="${STAR}${STRNG}"
    COUNT=$(( COUNT - 1 ))
    HORIZ=$(( HORIZ - MIN ))
    VERT=$(( VERT - 1 ))
done
printf "\033[H"

Result OSX 10.14.3, default bash terminal calling dash, values given, 3 MIN, 10 MAX:

AMIGA:amiga~/Desktop/Code/Shell> 


                                 * * * 
                              * * * * * * 
                           * * * * * * * * * 
                        * * * * * * * * * * * * 
                     * * * * * * * * * * * * * * * 
                  * * * * * * * * * * * * * * * * * * 
               * * * * * * * * * * * * * * * * * * * * * 
            * * * * * * * * * * * * * * * * * * * * * * * * 
         * * * * * * * * * * * * * * * * * * * * * * * * * * * 
            * * * * * * * * * * * * * * * * * * * * * * * * 
               * * * * * * * * * * * * * * * * * * * * * 
                  * * * * * * * * * * * * * * * * * * 
                     * * * * * * * * * * * * * * * 
                        * * * * * * * * * * * * 
                           * * * * * * * * * 
                              * * * * * * 
                                 * * * 
#!/bin/bash

MIN=1
MAX=10
STARS=0

S=$(printf '%*s' "$((MAX*2))" '')
D=${S//  / *}

for ((N=MIN; N < (MAX*2); N++ && (STARS += W)))
do
        [ "$N" -gt "$MAX" ] && W=$(((MAX*2)-N)) || W="$N"
        [ "$W" -lt "$MIN" ] && break;
        echo "${S:0:$((MAX-W))}${D:0:$((W*2))}"
done

echo "Total stars: $STARS"
          *
         * *
        * * *
       * * * *
      * * * * *
     * * * * * *
    * * * * * * *
   * * * * * * * *
  * * * * * * * * *
 * * * * * * * * * *
  * * * * * * * * *
   * * * * * * * *
    * * * * * * *
     * * * * * *
      * * * * *
       * * * *
        * * *
         * *
          *
Total stars: 100
2 Likes

Love that solution Corona688 but the MIN and MAX tests and the loop break feel awkward.

Bash makes it hard without an abs() function, I was forced to use ${A#-} in it's place, but, in my opinion this is an improvement:

MIN=1
MAX=10

S=$(printf '%*s' "$((MAX*2))" '')
D=${S//  / *}

for((N=MIN; N <= (MAX*2-MIN); N++ && (STARS +=W)))
do
    ((A=N-MAX))
    ((W=MAX-${A#-}))
    echo "${S:0:$((MAX-W))}${D:0:$((W*2))}"
done
echo "Total stars: $STARS"
3 Likes

Hi C688, Chubler_XL...

Be aware they only work with MIN=1...
Try 'MIN=6' and 'MAX=11'.

I also made the mistake of thinking MIN was also the number of stars in each horizontal plot.

The OP ALWAYS wants a DIAMOND with SINGLE stars, where say the MIN and MAX values of say '3 and 7' give the same results as '4 and 8' or '5 and 9'.

Here is my POSIX update...

#!/usr/local/bin/dash
# DIAMOND.sh
# POSIX compliant, with no input error checking.
# Using terminal escape codes just for fun.

echo "Enter minimum value:"
read -r MIN
echo "Enter maximum value:"
read -r MAX
printf "\033c\n"
STRNG="* "
STAR="* "
COUNT=1
HORIZ=34
VERT=4
STAR_COUNT=0

STAR="* "
COUNT=${MAX}
while [ ${COUNT} -ge ${MIN} ]
do
    printf "%b" "\033["${VERT}";"${HORIZ}"f${STAR}"
    STAR="${STAR}${STRNG}"
    COUNT=$(( COUNT - 1 ))
    HORIZ=$(( HORIZ - 1 ))
    VERT=$(( VERT + 1 ))
done

HORIZ=34
VERT=$(( VERT + MAX - MIN -1 ))
STAR="${STRNG}"
COUNT=${MAX}
while [ ${COUNT} -ge ${MIN} ]
do
    printf "%b" "\033["${VERT}";"${HORIZ}"f${STAR}"
    STAR="${STAR}${STRNG}"
    COUNT=$(( COUNT - 1 ))
    HORIZ=$(( HORIZ - 1 ))
    VERT=$(( VERT - 1 ))
done

COUNT=$(( MAX - MIN ))
STAR_COUNT=0
while [ ${COUNT} -ge 0 ]
do
    STAR_COUNT=$(( STAR_COUNT + COUNT ))
    COUNT=$(( COUNT - 1 ))
done
STAR_COUNT=$(( ( STAR_COUNT * 2 ) + ( MAX - MIN ) + 1 ))

printf "\033[H"
echo "Number of stars: ${STAR_COUNT}..."

Results using MIN and MAX of 3 and 7, 4 and 8, and 5 and 9.
OSX 10.14.3, default bash terminal calling dash...

Number of stars: 25...
AMIGA:amiga~/Desktop/Code/Shell> 

                                 * 
                                * * 
                               * * * 
                              * * * * 
                             * * * * * 
                              * * * * 
                               * * * 
                                * * 
                                 * 
2 Likes

wisecracker, your solution in post #8 doesn't seem to match the description (or code) the OP posted.

Testing the original posted code I get:

enter the mininum number 
3
enter the maximum number 
5
    * * *
   * * * *
  * * * * *
   * * * *
    * * *
Total No. :  19

Can you explain further why you believe '3 and 7' should be giveing the same result as '4 and 8'?

Hi Chubler_XL...
Your quote:

My quote:

Your quote:

Because the OP showed a diamond for every valid inputted value, AND, he thanked my post #8.
Also it calls dash so should work on just about any shell.
The code using various values, Linux Mint 19, default terminal calling 'dash'...

Using 2, 11...
  
Number of stars: 100...
bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ 

                                 * 
                                * * 
                               * * * 
                              * * * * 
                             * * * * * 
                            * * * * * * 
                           * * * * * * * 
                          * * * * * * * * 
                         * * * * * * * * * 
                        * * * * * * * * * * 
                         * * * * * * * * * 
                          * * * * * * * * 
                           * * * * * * * 
                            * * * * * * 
                             * * * * * 
                              * * * * 
                               * * * 
                                * * 
                                 * 
Using 1, 10...
The same...

Using 7, 8...
Number of stars: 4...
bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ 

                                 * 
                                * * 
                                 * 
Using 1, 2...
The same...

Using 4, 9...
Number of stars: 36...
bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ 

                                 * 
                                * * 
                               * * * 
                              * * * * 
                             * * * * * 
                            * * * * * * 
                             * * * * * 
                              * * * * 
                               * * * 
                                * * 
                                 * 
And using 1, 6...
 The same...

AND finally are you sure it was my code you tested because the original version did NOT count the stars, I forgot to add it...

I was demonstrating how the original code we were asked to simplify in Post #1 works .
I believe this was indicated as doing what was required.

Here is a solution using dash. I make use of a function fill. fill's first argument is the total length of output required and the 2nd (optional) argument specifies the string to use (single space being the default).

As an example fill 3 gives 3 spaces, and fill 5 "AB" gives ABABA .

This function can be used to output a diamond in this fashion:

fill 3 ; fill 2 '* ' ; echo
fill 2 ; fill 4 '* ' ; echo
fill 1 ; fill 6 '* ' ; echo
fill 0 ; fill 8 '* ' ; echo
fill 1 ; fill 6 '* ' ; echo
fill 2 ; fill 4 '* ' ; echo
fill 3 ; fill 2 '* ' ; echo

And here is the full dash solution using this method:

#!/bin/dash

fill ()
{
    # fill string to width of count from string chars 
    #
    # usage:
    #      fill count [chars]
    #
    # if count is zero (or less) a blank string is output
    # chars defaults to a space
    #
    local width=$(( ($1) ))
    local str="${2:- }"

    while [ $width -gt 0 ]
    do
        while [ ${#str} -gt $width ]
        do
            str=${str%?}
        done
        width=$((width-${#str}))
        printf "%s" "$str"
    done
}

printf "Enter the mininum number: "
read MIN
printf "Enter the maximum number: "
read MAX

STARS=0
N=$MIN
while [ $N -le $((MAX*2-MIN)) ]
do
    A=$((N-MAX))
    W=$(($MAX-${A#-}))
    fill MAX-W ; fill W*2 '* ' ; echo
    STARS=$((STARS+W))
    N=$((N+1))
done
echo "Total stars: $STARS"
1 Like

I disagree, the image distinctly shows a DIAMOND, period.
Your code:

bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ ./DIAMOND_CXL.sh
Enter the mininum number: 4
Enter the maximum number: 7
   * * * * 
  * * * * * 
 * * * * * * 
* * * * * * * 
 * * * * * * 
  * * * * * 
   * * * * 
Total stars: 37
bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ 

AND

bazza@amiga-MacBookPro:~$ cd Desktop/Code/Shell
bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ ./DIAMOND_CXL.sh
Enter the mininum number: -7
Enter the maximum number: -1
      
     
    
   
  
 

 
  
   
    
     
      
Total stars: -55
bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ 

My code:

bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ ./DIAMOND.sh
Enter minimum value:
-7
Enter maximum value:
-1

Number of stars: 49...
bazza@amiga-MacBookPro:~/Desktop/Code/Shell$ 

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

So best not to start a flame war and let the OP tell us EXACTLY which one he wants...

1 Like

I completely agree with your approach which handles all type of scenarios. Thanks guys for your help

2 Likes

Dear All,

All solutions are welcome, not only the original posters request, and thanks to everyone who posted their code and the thoughts behind their design.

Keep those great solutions coming.

Thanks!

1 Like