Skip to content

Commit

Permalink
Add diamond exercise
Browse files Browse the repository at this point in the history
  • Loading branch information
keiravillekode committed Nov 1, 2024
1 parent 9a82afe commit 4d93a25
Show file tree
Hide file tree
Showing 12 changed files with 3,649 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,14 @@
"prerequisites": [],
"difficulty": 5
},
{
"slug": "diamond",
"name": "Diamond",
"uuid": "a34c2fd9-268c-498f-be02-683e71b2e7e5",
"practices": [],
"prerequisites": [],
"difficulty": 5
},
{
"slug": "luhn",
"name": "Luhn",
Expand Down
52 changes: 52 additions & 0 deletions exercises/practice/diamond/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Instructions

The diamond kata takes as its input a letter, and outputs it in a diamond shape.
Given a letter, it prints a diamond starting with 'A', with the supplied letter at the widest point.

## Requirements

- The first row contains one 'A'.
- The last row contains one 'A'.
- All rows, except the first and last, have exactly two identical letters.
- All rows have as many trailing spaces as leading spaces. (This might be 0).
- The diamond is horizontally symmetric.
- The diamond is vertically symmetric.
- The diamond has a square shape (width equals height).
- The letters form a diamond shape.
- The top half has the letters in ascending order.
- The bottom half has the letters in descending order.
- The four corners (containing the spaces) are triangles.

## Examples

In the following examples, spaces are indicated by `·` characters.

Diamond for letter 'A':

```text
A
```

Diamond for letter 'C':

```text
··A··
·B·B·
C···C
·B·B·
··A··
```

Diamond for letter 'E':

```text
····A····
···B·B···
··C···C··
·D·····D·
E·······E
·D·····D·
··C···C··
···B·B···
····A····
```
19 changes: 19 additions & 0 deletions exercises/practice/diamond/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"keiravillekode"
],
"files": {
"solution": [
"diamond.s"
],
"test": [
"diamond_test.c"
],
"example": [
".meta/example.s"
]
},
"blurb": "Given a letter, print a diamond starting with 'A' with the supplied letter at the widest point.",
"source": "Seb Rose",
"source_url": "https://web.archive.org/web/20220807163751/http://claysnow.co.uk/recycling-tests-in-tdd/"
}
47 changes: 47 additions & 0 deletions exercises/practice/diamond/.meta/example.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
.text
.globl rows

/* void rows(char *buffer, char letter); */
rows:
mov w9, #' '
mov w10, #'\n'
mov x14, x0
sub w2, w1, #'A' /* offset from start of the alphabet */
lsl w3, w2, #1
add w3, w3, #1 /* number of rows */
add w4, w3, #2
mov w7, w3 /* number of rows remaining */

.row:
mov w8, w3 /* number of columns remaining, excluding newline */

.column:
strb w9, [x14], #1 /* store ' ' byte, post-increment */
sub w8, w8, #1
cbnz w8, .column

strb w10, [x14], #1 /* store '\n' byte, post-increment */
sub w7, w7, #1
cbnz w7, .row

strb wzr, [x14], #-2 /* store '\0' byte, post-decrement */
mov w11, #'A'
add x12, x0, x2
mov x13, x12
sub x14, x14, x2
mov x15, x14

.letter:
strb w11, [x12]
strb w11, [x13]
strb w11, [x14]
strb w11, [x15]
add x12, x12, x3
add x13, x13, x4
sub x14, x14, x4
sub x15, x15, x3
add w11, w11, #1
cmp w11, w1
ble .letter

ret
25 changes: 25 additions & 0 deletions exercises/practice/diamond/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[202fb4cc-6a38-4883-9193-a29d5cb92076]
description = "Degenerate case with a single 'A' row"

[bd6a6d78-9302-42e9-8f60-ac1461e9abae]
description = "Degenerate case with no row containing 3 distinct groups of spaces"

[af8efb49-14ed-447f-8944-4cc59ce3fd76]
description = "Smallest non-degenerate case with odd diamond side length"

[e0c19a95-9888-4d05-86a0-fa81b9e70d1d]
description = "Smallest non-degenerate case with even diamond side length"

[82ea9aa9-4c0e-442a-b07e-40204e925944]
description = "Largest possible diamond"
36 changes: 36 additions & 0 deletions exercises/practice/diamond/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
AS = aarch64-linux-gnu-as
CC = aarch64-linux-gnu-gcc

CFLAGS = -g -Wall -Wextra -pedantic -Werror
LDFLAGS =

ALL_LDFLAGS = -pie -Wl,--fatal-warnings

ALL_CFLAGS = -std=c99 -fPIE $(CFLAGS)
ALL_LDFLAGS += $(LDFLAGS)

C_OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
AS_OBJS = $(patsubst %.s,%.o,$(wildcard *.s))
ALL_OBJS = $(filter-out example.o,$(C_OBJS) $(AS_OBJS) vendor/unity.o)

CC_CMD = $(CC) $(ALL_CFLAGS) -c -o $@ $<

all: tests
qemu-aarch64 -L /usr/aarch64-linux-gnu ./$<

tests: $(ALL_OBJS)
@$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o $@ $(ALL_OBJS)

%.o: %.s
@$(AS) -o $@ $<

%.o: %.c
@$(CC_CMD)

vendor/unity.o: vendor/unity.c vendor/unity.h vendor/unity_internals.h
@$(CC_CMD)

clean:
@rm -f *.o vendor/*.o tests

.PHONY: all clean
5 changes: 5 additions & 0 deletions exercises/practice/diamond/diamond.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.text
.globl rows

rows:
ret
132 changes: 132 additions & 0 deletions exercises/practice/diamond/diamond_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include "vendor/unity.h"

#define BUFFER_SIZE 3200

void rows(char *buffer, char letter);

void setUp(void) {
}

void tearDown(void) {
}

void test_degenerate_case_with_a_single_a_row(void) {
const char expected[] =
"A\n";
char buffer[BUFFER_SIZE];

rows(buffer, 'A');
TEST_ASSERT_EQUAL_STRING(expected, buffer);
}

void test_degenerate_case_with_no_row_containing_3_distinct_groups_of_spaces(void) {
TEST_IGNORE();
const char expected[] =
" A \n"
"B B\n"
" A \n";
char buffer[BUFFER_SIZE];

rows(buffer, 'B');
TEST_ASSERT_EQUAL_STRING(expected, buffer);
}

void test_smallest_nondegenerate_case_with_odd_diamond_side_length(void) {
TEST_IGNORE();
const char expected[] =
" A \n"
" B B \n"
"C C\n"
" B B \n"
" A \n";
char buffer[BUFFER_SIZE];

rows(buffer, 'C');
TEST_ASSERT_EQUAL_STRING(expected, buffer);
}

void test_smallest_nondegenerate_case_with_even_diamond_side_length(void) {
TEST_IGNORE();
const char expected[] =
" A \n"
" B B \n"
" C C \n"
"D D\n"
" C C \n"
" B B \n"
" A \n";
char buffer[BUFFER_SIZE];

rows(buffer, 'D');
TEST_ASSERT_EQUAL_STRING(expected, buffer);
}

void test_largest_possible_diamond(void) {
TEST_IGNORE();
const char expected[] =
" A \n"
" B B \n"
" C C \n"
" D D \n"
" E E \n"
" F F \n"
" G G \n"
" H H \n"
" I I \n"
" J J \n"
" K K \n"
" L L \n"
" M M \n"
" N N \n"
" O O \n"
" P P \n"
" Q Q \n"
" R R \n"
" S S \n"
" T T \n"
" U U \n"
" V V \n"
" W W \n"
" X X \n"
" Y Y \n"
"Z Z\n"
" Y Y \n"
" X X \n"
" W W \n"
" V V \n"
" U U \n"
" T T \n"
" S S \n"
" R R \n"
" Q Q \n"
" P P \n"
" O O \n"
" N N \n"
" M M \n"
" L L \n"
" K K \n"
" J J \n"
" I I \n"
" H H \n"
" G G \n"
" F F \n"
" E E \n"
" D D \n"
" C C \n"
" B B \n"
" A \n";
char buffer[BUFFER_SIZE];

rows(buffer, 'Z');
TEST_ASSERT_EQUAL_STRING(expected, buffer);
}

int main(void) {
UNITY_BEGIN();
RUN_TEST(test_degenerate_case_with_a_single_a_row);
RUN_TEST(test_degenerate_case_with_no_row_containing_3_distinct_groups_of_spaces);
RUN_TEST(test_smallest_nondegenerate_case_with_odd_diamond_side_length);
RUN_TEST(test_smallest_nondegenerate_case_with_even_diamond_side_length);
RUN_TEST(test_largest_possible_diamond);
return UNITY_END();
}
Loading

0 comments on commit 4d93a25

Please sign in to comment.