## Drawing Diamonds

### September 9, 2014

We begin with auxiliary functions that write an asterisk, a row of n blanks, a properly-spaced row of n asterisks, and an unfilled row of n asterisks:

`(define (star) (display #\*))`

```(define (blanks n)   (do ((n n (- n 1))) ((zero? n)) (display #\space)))```

```(define (filled n)   (do ((n n (- n 1))) ((= n 1) (star)) (star) (blanks 1)))```

```(define (unfilled n)   (cond ((= n 1) (star))   (else (star) (blanks (+ n n -3)) (star))))```

Note that the `unfilled` function writes two stars except for the case n = 1, when it writes only one star.

Then the function that draws a diamond is easy. It takes two parameters, the width of the diamond n and a boolean that is `#t` when the diamond is filled and `#f` when it is outlined:

```(define (diamond n filled?)   (do ((i 1 (+ i 1))) ((< n i))     (blanks (- n i))     (if filled? (filled i) (unfilled i))     (newline))   (do ((i (- n 1) (- i 1))) ((zero? i))     (blanks (- n i))     (if filled? (filled i) (unfilled i))     (newline)))```

Here are some examples:

```> (diamond 5 #t)
*
* *
* * *
* * * *
* * * * *
* * * *
* * *
* *
*
> (diamond 5 #f)
*
* *
*   *
*     *
*       *
*     *
*   *
* *
*
```

You can run the program at http://programmingpraxis.codepad.org/bvsiQ3LM.

Pages: 1 2

### 20 Responses to “Drawing Diamonds”

1. ```use strict;
use warnings;

print diamond( @ARGV );

## Really a one-liner - but we'll make it easier to read
sub diamond {
my( \$filled, \$size ) = @_;
return join q(), map {
q( )x(\$size-\$_),
q(*),
\$filled ? q( *)x(\$_-1)
: \$_>1    ? q(  )x(\$_-2).q( *)
: q(),
"\n" } (1..\$size, reverse 1..(\$size-1));
}
```
2. Paul said

In Python.

```def diamond(n, filled=False):
for i in range(1, n) + range(n, 0, -1):
txt = ["*"] * i if filled else ["*"] + [" "] * (i-2) + ["*"] * (i > 1)
print ("{:^" + str(n * 2  - 1) + "s}").format(" ".join(txt))
```
3. Andras said

In Java, another approach

```public class DrawingDiamonds {

private static final String S = System.lineSeparator();

public static String drawDiamond(int size, boolean filled) {
String diamond = "";
for (int y = 1 - size; y <= (size - 1); y++) {
for (int x = 1 - size; x <= size - 1; x++) {
if (filled) {
if ((x + size - 1 >= -y) && (x + size - 1 >= y) && (x - size + 1 <= -y) && (x - size + 1 <= y)) {
diamond += "*";
} else {
diamond += " ";
}
} else {
if ((x + size - 1 == -y) || (x + size - 1 == y) || (x - size + 1 == -y) || (x - size + 1 == y)) {
diamond += "*";
} else {
diamond += " ";
}
}
}
diamond += S;
}
return diamond;
}
}```
4. Jussi Piitulainen said

``` (define (<> n fill?)   (let ((b (- 1 n)))     (do ((r b (+ r 1))) ((>= r n))       (do ((k b (+ k 1))) ((= k n) (newline))         (write-char (if (fill? n r k) #\* #\space))))))```

``` (define (solid n r k) (and (< (+ (abs r) (abs k)) n) (odd? (+ r k n)))) (define (hollow n r k) (= (+ (abs r) (abs k) 1) n)) ```

```; Usage: (<> n solid) or (<> n hollow) for n = 0, 1, 2, 3, ... ```

5. Christophe said

My solution in Scheme:

```(#%require srfi/1)
(define (draw-diamond n fill?)
; Repeats a string n times.
(define (string-repeat str n)
(fold string-append "" (make-list n str)))
; Prints a string n times, centered in the given
; width. Fill? determines if the string should be repeated.
(define (print n width string stringwidth)
(let* ((whitespace (/ (- width (* n stringwidth)) 2))
(center-width (max 0 (- (* n stringwidth) (* 2 stringwidth))))
(center-spaces (string-repeat " " center-width))
(ws-string (string-repeat " " whitespace)))
(if fill?
(string-append ws-string (string-repeat string n) ws-string "\n")
(if (> n 1)
(string-append ws-string string center-spaces string ws-string "\n")
(string-append ws-string string ws-string "\n")))))
(let ((total-width (* n 2))
(single-star "* ")
(output ""))
; Print the top pyramid.
(let top ((counter 1))
(set! output (string-append output (print counter total-width "* " 2)))
(if (> n counter)
(top (+ 1 counter))))
; Print bottom half.

(let bottom ((counter (- n 1)))
(set! output (string-append output (print counter total-width "* " 2)))
(if (> counter 1)
(bottom (- counter 1))))
(display output)))

(draw-diamond 10 #t)
```
6. matthew said

Let’s use some old-style VT100 cursor movement commands to draw the diamond, instead of generating a bunch of strings (obviously, needs to be run in a suitable terminal window). Looks nicer with a small delay when drawing characters:

```#include <stdlib.h>
#include <stdio.h>
#include <time.h>

timespec delay;

void cls() { fprintf(stderr,"\x1b""[2J"); }
void moveto(int x, int y) { fprintf(stderr,"\x1b""[%d;%dH",y,x); }

void printat(int x, int y, const char *s)
{
nanosleep(&delay,NULL);
moveto(x,y);
fprintf(stderr,"%s", s);
}

int main(int argc, char *argv[])
{
int N = atoi(argv[1]);
delay.tv_nsec = 2000/(N*N)*1000000;
int k = N, x = N+1, y = 0, xinc = -1, yinc = 1;
cls();
while (true) {
for (int i = 0; i < k; i++) {
x += xinc; y += yinc;
printat(x,y,"*");
}
xinc = -xinc;
k--; if (k == 0) break;
for (int i = 0; i < k; i++) {
x += xinc; y += yinc;
printat(x,y,"*");
}
yinc = -yinc;
}
moveto(1,2*N);
}
```
7. matthew said

And if we want to use strings, it’s easy to generate them recursively. We can extend a solution for n to a solution for n+1 by adding an extra ” ” at the start of each line and adding an extended duplicate of the last line. How we do the extension determines how the diamond is filled:

```-- Unfilled
e1 1 s = "* " ++ s
e1 _ (_:s) = "*  " ++ s -- skip previously inserted *
-- Filled with alternate blanks
e2 _ s = "* " ++ s
-- Completely filled
e3 _ s = "**" ++ s

h _ 0 = ["*\n"]
h e n = (e n (head s)): map (" "++) s where s = h e (n-1)
d e n = concat (reverse (tail s) ++ s) where s = h e (n-1)
main = do putStr (d e1 5) >> putStr (d e2 5) >> putStr (d e3 5)
```
8. matthew said

This is better for the main loop of my C++ solution – we don’t need to treat the two passes separately, just rotate by 90° at each corner:

```int main(int argc, char *argv[])
{
int N = atoi(argv[1]);
int x = N+1, y = 0, xinc = -1, yinc = 1;
delay.tv_nsec = 2000/(N*N)*1000000;
cls();
for (int k = 2*N; k > 1; k--) {
for (int i = 0; i < k/2; i++) {
x += xinc; y += yinc;
printat(x,y,"*");
}
int t = xinc; xinc = yinc; yinc = -t;
}
moveto(1,2*N);
}
```
9. Mike said

Python 3 version. Depends on print function to insert spaces between each argument.

```def foo(n, fill='*'):
for i in it.chain(range(1,n), range(n,0,-1)):
print(*(['']*(n-i) + ['*'] + [fill]*(i-2) + ['*'][:i-1]))
```
10. R.Bravo said
```d = int( input() )
double = d * 2
offset = 0
for i in xrange( 1 , double + 1 ) :
if i > d :
stars = ' '.join('*' * (double - i) )
offset = i - d
else :
stars = ' '.join('*' * i)
offset = d - i
print ' ' * (offset) + stars
```
11. novatech said
```void diamond(int n)
{
for (int i = n-1;i>-n;i--)
{
int g=abs(i)+1;
printf("%*c%*c\n",g,'*',2*(n-g),g-n?'*':0);
}
}

int main()
{
diamond(1);
diamond(2);
diamond(-5);
diamond(5);
diamond(8);

return 0;
}
```
12. Globules said
```import Data.List (intercalate)

mirror :: [a] -> [a]
mirror xs = xs ++ tail (reverse xs)

half :: Char -> Int -> Int -> String
half fill n i = replicate (n-i-1) ' ' ++ "*" ++ take i (cycle [' ', fill])

line :: Char -> Int -> Int -> String
line fill n i = mirror \$ half fill n i

diamond :: Char -> Int -> [String]
diamond fill n = mirror \$ map (line fill n) [0..n-1]

beside :: [String] -> [String] -> [String]
left `beside` right = zipWith ((++) . (++ "    ")) left right

printLines :: [String] -> IO ()
printLines = putStrLn . intercalate "\n"

main :: IO ()
main = printLines \$ diamond '*' 5 `beside` diamond ' ' 5
```

When run the output looks like this:

```    *            *
* *          * *
* * *        *   *
* * * *      *     *
* * * * *    *       *
* * * *      *     *
* * *        *   *
* *          * *
*            *
```
13. svenningsson said

```import Data.List

diamond :: Bool -> Int -> String
diamond fill size = unlines [ replicate (size - stars) ' ' ++  dots fill stars | stars <- [1..size] ++ [size-1,size-2..1] ]
where
dots False 1 = "*"
dots False s = "*" ++ replicate (2 * s - 3) ' ' ++ "*"
dots True  s = intersperse ' ' (replicate s '*')
```
14. Naj said

In C++
#include
#include
int main()
{
int i,n;
cout<>n;
for( i=0;ii;j–)
cout<<" ";
for(int k=0;k<i;k++)
cout<<" *";
cout<0;i–)
{
for(int j=n;j>i;j–)
cout<<" ";
for(int k=0;k<i;k++)
cout<<" *";
cout<<"\n";
}
getch();
}

15. Jussi Piitulainen said
```/* gcc -std=c99 -Wall */
#include <stdio.h>
void draw(int n, int (*filled)(int, int, int)) {
for (int r = 1 - n ; r < n ; ++ r) {
for (int k = 1 - n ; k < n ; ++ k)
putchar(filled(n, r, k) ? '*' : ' ');
putchar('\n');
}
}
int abs(int m) { return (m < 0) ? (-m) : m; }
int odd(int m) { return m & 1; }
int sol(int n, int r, int k) { return abs(r) + abs(k) < n && odd(r + k + n); }
int hol(int n, int r, int k) { return abs(r) + abs(k) + 1 == n; }
int main() { draw(4, sol); draw(4, hol); return 0; }
```
16. Without string, formatting, … support and only basic operators (but comprehension lists):

```t n f=[[if c<=0 &&(f||c==0)&& mod x 2==mod y 2 then '*' else ' '
|x<-w,let c=abs x+abs y-n+1]|y<-w]where w=[-n+1..n-1]
```
17. (the previous one is wrong, cannot be deleted/edited?)

```t n f=[[if c<=0&&(x+n).&.1/=y.&.1&&f||c==0 then '*'else ' '|x<-w,let c=abs x+abs y-n+1]|let w=[-n+1..n-1],y<-w]
```
18. Another Java solution:

```import java.util.Arrays;

public class DrawDiamond {

public static void draw(int size, boolean filled) {
int middle = (2 * size - 1) / 2;
char[] line = new char[2 * size - 1];
for (int i = 0; i <= middle; i++) {
Arrays.fill(line, ' ');
int l = middle - i;
int r = middle + i;
line[l] = '*';
line[r] = '*';
if (filled) {
for (int j = l + 2; j < r; j += 2) {
line[j] = '*';
}
}
println(line);
}
for (int i = middle - 1; i >= 0; i--) {
Arrays.fill(line, ' ');
int l = middle - i;
int r = middle + i;
line[l] = '*';
line[r] = '*';
if (filled) {
for (int j = l + 2; j < r; j += 2) {
line[j] = '*';
}
}
println(line);
}
}

private static void println(char[] chars) {
StringBuilder out = new StringBuilder();
out.append(chars);
System.out.println(out);
}

public static void main(String[] args) {
draw(5, true);
}
}
```
19. Sarthak Mehta said

j = 7
k = 7
p = 1
for i in range(8):
print ” ” * k,” *” * i
k -=1
while j > 1:
j -= 1
print ” ” * p,” *” * j
p +=1

20. Rey Diamond said

Hy, why print if using php programming te output number 2