## Pages

### print "squashed-circle" diamond

There's been a bit of a buzz about the Print-Diamond practice recently. I recall doing this a couple of years ago with Johannes Brodwall. In cyber-dojo naturally. We took a wrong turn and were making a thorough mess of it. I vividly recall Johannes saying:
This is too difficult. We're doing it wrong.
I love that. If it's difficult you're probably doing it wrong. We gave up and took a break. We got a really nice Indian take away. Then we went back to Print-Diamond. Very quickly we came up with a new idea. We imagined the diamond lying in the center of an x,y axis. The Print-Diamond of 'C' would therefore look like this:
```
-2 -1  0 +1 +2

-2    -  -  A  -  -
-1    -  B  -  B  -
0    C  -  -  -  C
+1    -  B  -  B  -
+2    -  -  A  -  -

```

Viewed like this you can think of the Diamond as a sort of squashed circle with the A,B,C characters all lying on the circumference. From here it was a short step to this:
```(-2..+2).map{|row|
(-2..+2).map{|col|
row.abs + col.abs == 2 ? 'X' : '-'
}.join
}
```

which, when puts'd gives:
```--X--
-X-X-
X---X
-X-X-
--X--
```

And we knew we were on our way.
Let's hear it for Indian Food Driven Development!

### yet another interesting TDD episode

In the previous episode I described how a custom assert function declared a local array which I did not initialize.
```static void assert_fizz_buzz(const char * expected, int n)
{
char actual[16];
...
}
```

The effect of not initializing the array was that state from one test leaked into another test and I got an unexpectedly passing test. I fixed the problem by initializing the array.
```static void assert_fizz_buzz(const char * expected, int n)
{
char actual[16] = "";
...
}
```

The most recent episode (in cyber-dojo naturally) revolved around this same issue. This time I was redoing the roman numerals exercise (1 → "I", 2 → "II", etc) in C. My custom assert function started like this.
```...
#define PRINT(s) print_string(#s, s)

static void print_string(const char * name, const char * s)
{
printf("%10s: \"%s\"\n", name, s);
}

static void assert_to_roman(const char * expected, int n)
{
char actual[32];
to_roman(actual, sizeof actual, n);
if (strcmp(expected, actual) != 0)
{
printf("to_roman(%d) FAILED\n", n);
PRINT(expected);
PRINT(actual);
assert(false);
}
}
```

Once again I failed to initialize the array. I'm a slow learner. This time the test failed unexpectedly! And the diagnostic was even more unexpected:
```to_roman(1) FAILED
expected: "I"
actual: "I"
```

This is a less than ideal diagnostic! It seemed that `strcmp` and `printf` had differing opinions on what a string is! I fixed it by adding initialization.
```...
static void assert_to_roman(const char * expected, int n)
{
char actual[32] = "";
to_roman(actual, sizeof actual, n);
if (strcmp(expected, actual) != 0)
{
printf("to_roman(%d) FAILED\n", n);
PRINT(expected);
PRINT(actual);
assert(false);
}
}
```

After this the tests passed. This addressed the immediate problem but it did not address to the root cause. So I removed the initialization and (with a hat tip to Mr Jonathon Wakely) I reworked `print_string` to display the length of the string as well as an indication of the (un)printability of each character:
```static void print_string(const char * name, const char * s)
{
printf("%10s: \"%s\" %d ", name, s, (int)strlen(s));
for (size_t i = 0; i != strlen(s); i++)
{
putchar(isprint(s[i]) ? 'P' : 'U');
}
putchar('\n');
}
```

With this change the diagnostic became:
```to_roman(1) FAILED
expected: "I" 1 P
actual: "I" 4 UUUP
```

Much better. Then I thought about initializing the array a bit more. I realized that initializing the array to the empty string was a poor choice since it masked a fault in the implementation of `to_roman` which did not start like this:
```void to_roman(char buffer[], size_t size, int n)
{
buffer[0] = '\0';
...
}
```

So I added that and reworked `print_string` as follows:
```static void assert_to_roman(const char * expected, int n)
{
char actual[32];
memset(actual, '!', sizeof actual);
to_roman(actual, sizeof actual, n);
...
}
```

And I was back to green :-)