Skip to content

Commit 1b43e74

Browse files
authored
Add darts exercise (#285)
by: oxe-i <[email protected]>
1 parent cf737c0 commit 1b43e74

File tree

12 files changed

+3651
-8
lines changed

12 files changed

+3651
-8
lines changed

config.json

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@
6060
"math"
6161
]
6262
},
63+
{
64+
"slug": "darts",
65+
"name": "Darts",
66+
"uuid": "98887d08-92b7-4559-8133-4c05453bfe14",
67+
"practices": [],
68+
"prerequisites": [],
69+
"difficulty": 1
70+
},
6371
{
6472
"slug": "difference-of-squares",
6573
"name": "Difference of Squares",
@@ -119,14 +127,6 @@
119127
"transforming"
120128
]
121129
},
122-
{
123-
"slug": "sieve",
124-
"name": "Sieve",
125-
"uuid": "6cc147ff-65cb-417d-9883-6b7cf910e828",
126-
"practices": [],
127-
"prerequisites": [],
128-
"difficulty": 5
129-
},
130130
{
131131
"slug": "space-age",
132132
"name": "Space Age",
@@ -524,6 +524,14 @@
524524
"prerequisites": [],
525525
"difficulty": 5
526526
},
527+
{
528+
"slug": "sieve",
529+
"name": "Sieve",
530+
"uuid": "6cc147ff-65cb-417d-9883-6b7cf910e828",
531+
"practices": [],
532+
"prerequisites": [],
533+
"difficulty": 5
534+
},
527535
{
528536
"slug": "food-chain",
529537
"name": "Food Chain",
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Instructions
2+
3+
Calculate the points scored in a single toss of a Darts game.
4+
5+
[Darts][darts] is a game where players throw darts at a [target][darts-target].
6+
7+
In our particular instance of the game, the target rewards 4 different amounts of points, depending on where the dart lands:
8+
9+
![Our dart scoreboard with values from a complete miss to a bullseye](https://assets.exercism.org/images/exercises/darts/darts-scoreboard.svg)
10+
11+
- If the dart lands outside the target, player earns no points (0 points).
12+
- If the dart lands in the outer circle of the target, player earns 1 point.
13+
- If the dart lands in the middle circle of the target, player earns 5 points.
14+
- If the dart lands in the inner circle of the target, player earns 10 points.
15+
16+
The outer circle has a radius of 10 units (this is equivalent to the total radius for the entire target), the middle circle a radius of 5 units, and the inner circle a radius of 1.
17+
Of course, they are all centered at the same point — that is, the circles are [concentric][] defined by the coordinates (0, 0).
18+
19+
Given a point in the target (defined by its [Cartesian coordinates][cartesian-coordinates] `x` and `y`, where `x` and `y` are [real][real-numbers]), calculate the correct score earned by a dart landing at that point.
20+
21+
## Credit
22+
23+
The scoreboard image was created by [habere-et-dispertire][habere-et-dispertire] using [Inkscape][inkscape].
24+
25+
[darts]: https://en.wikipedia.org/wiki/Darts
26+
[darts-target]: https://en.wikipedia.org/wiki/Darts#/media/File:Darts_in_a_dartboard.jpg
27+
[concentric]: https://mathworld.wolfram.com/ConcentricCircles.html
28+
[cartesian-coordinates]: https://www.mathsisfun.com/data/cartesian-coordinates.html
29+
[real-numbers]: https://www.mathsisfun.com/numbers/real-numbers.html
30+
[habere-et-dispertire]: https://exercism.org/profiles/habere-et-dispertire
31+
[inkscape]: https://en.wikipedia.org/wiki/Inkscape
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"authors": [
3+
"oxe-i"
4+
],
5+
"files": {
6+
"solution": [
7+
"darts.asm"
8+
],
9+
"test": [
10+
"darts_test.c"
11+
],
12+
"example": [
13+
".meta/example.asm"
14+
]
15+
},
16+
"blurb": "Calculate the points scored in a single toss of a Darts game.",
17+
"source": "Inspired by an exercise created by a professor Della Paolera in Argentina"
18+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
default rel
2+
3+
section .rodata
4+
outer_radius dq 10.0
5+
mid_radius dq 5.0
6+
inner_radius dq 1.0
7+
8+
section .text
9+
global score
10+
score:
11+
; xmm0 - a double representing x
12+
; xmm1 - a double representing y
13+
; output is a uint8_t in al
14+
15+
mulsd xmm0, xmm0 ; x^2
16+
mulsd xmm1, xmm1 ; y^2
17+
addsd xmm0, xmm1 ; x^2 + y^2
18+
sqrtsd xmm0, xmm0 ; square root of x^2 + y^2, or distance to the center
19+
20+
xor rax, rax ; base value is 0
21+
22+
movsd xmm1, qword [outer_radius]
23+
ucomisd xmm0, xmm1
24+
ja outside_target ; if distance is greater than outer circle, missed the target
25+
26+
movsd xmm1, qword [mid_radius]
27+
ucomisd xmm0, xmm1
28+
ja inside_outer_circle ; if distance is greater than mid circle, it's between mid and outer
29+
30+
movsd xmm1, qword [inner_radius]
31+
ucomisd xmm0, xmm1
32+
ja inside_middle_circle ; if distance is greater than inner circle, it's between inner and mid
33+
; otherwise, it's inside inner circle
34+
35+
; instructions fall through, accumulating values to give the total for each case
36+
add al, 5
37+
inside_middle_circle:
38+
add al, 4
39+
inside_outer_circle:
40+
add al, 1
41+
outside_target:
42+
ret
43+
44+
%ifidn __OUTPUT_FORMAT__,elf64
45+
section .note.GNU-stack noalloc noexec nowrite progbits
46+
%endif
47+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[9033f731-0a3a-4d9c-b1c0-34a1c8362afb]
13+
description = "Missed target"
14+
15+
[4c9f6ff4-c489-45fd-be8a-1fcb08b4d0ba]
16+
description = "On the outer circle"
17+
18+
[14378687-ee58-4c9b-a323-b089d5274be8]
19+
description = "On the middle circle"
20+
21+
[849e2e63-85bd-4fed-bc3b-781ae962e2c9]
22+
description = "On the inner circle"
23+
24+
[1c5ffd9f-ea66-462f-9f06-a1303de5a226]
25+
description = "Exactly on center"
26+
27+
[b65abce3-a679-4550-8115-4b74bda06088]
28+
description = "Near the center"
29+
30+
[66c29c1d-44f5-40cf-9927-e09a1305b399]
31+
description = "Just within the inner circle"
32+
33+
[d1012f63-c97c-4394-b944-7beb3d0b141a]
34+
description = "Just outside the inner circle"
35+
36+
[ab2b5666-b0b4-49c3-9b27-205e790ed945]
37+
description = "Just within the middle circle"
38+
39+
[70f1424e-d690-4860-8caf-9740a52c0161]
40+
description = "Just outside the middle circle"
41+
42+
[a7dbf8db-419c-4712-8a7f-67602b69b293]
43+
description = "Just within the outer circle"
44+
45+
[e0f39315-9f9a-4546-96e4-a9475b885aa7]
46+
description = "Just outside the outer circle"
47+
48+
[045d7d18-d863-4229-818e-b50828c75d19]
49+
description = "Asymmetric position between the inner and middle circles"

exercises/practice/darts/Makefile

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
AS = nasm
2+
3+
CFLAGS = -g -Wall -Wextra -pedantic -Werror
4+
LDFLAGS =
5+
ASFLAGS = -g -F dwarf -Werror
6+
7+
ifeq ($(shell uname -s),Darwin)
8+
ifeq ($(shell sysctl -n hw.optional.arm64 2>/dev/null),1)
9+
ALL_CFLAGS = -target x86_64-apple-darwin
10+
endif
11+
ALL_LDFLAGS = -Wl,-pie
12+
ALL_ASFLAGS = -f macho64 --prefix _
13+
else
14+
ALL_LDFLAGS = -pie -Wl,--fatal-warnings
15+
ALL_ASFLAGS = -f elf64
16+
endif
17+
18+
ALL_CFLAGS += -std=c99 -fPIE -m64 $(CFLAGS)
19+
ALL_LDFLAGS += $(LDFLAGS)
20+
ALL_ASFLAGS += $(ASFLAGS)
21+
22+
C_OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
23+
AS_OBJS = $(patsubst %.asm,%.o,$(wildcard *.asm))
24+
ALL_OBJS = $(filter-out example.o,$(C_OBJS) $(AS_OBJS) vendor/unity.o)
25+
26+
CC_CMD = $(CC) $(ALL_CFLAGS) -c -o $@ $<
27+
28+
all: tests
29+
@./$<
30+
31+
tests: $(ALL_OBJS)
32+
@$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o $@ $(ALL_OBJS)
33+
34+
%.o: %.asm
35+
@$(AS) $(ALL_ASFLAGS) -o $@ $<
36+
37+
%.o: %.c
38+
@$(CC_CMD)
39+
40+
vendor/unity.o: vendor/unity.c vendor/unity.h vendor/unity_internals.h
41+
@$(CC_CMD)
42+
43+
clean:
44+
@rm -f *.o vendor/*.o tests
45+
46+
.PHONY: all clean

exercises/practice/darts/darts.asm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
section .text
2+
global score
3+
score:
4+
; Provide your implementation here
5+
ret
6+
7+
%ifidn __OUTPUT_FORMAT__,elf64
8+
section .note.GNU-stack noalloc noexec nowrite progbits
9+
%endif

exercises/practice/darts/darts_test.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Version: 0
2+
3+
#include "vendor/unity.h"
4+
5+
extern uint8_t score(double x, double y);
6+
7+
void setUp(void) {
8+
}
9+
10+
void tearDown(void) {
11+
}
12+
13+
void test_missed_target(void) {
14+
uint8_t expected = 0;
15+
16+
TEST_ASSERT_EQUAL_UINT8(expected, score(-9, 9));
17+
}
18+
19+
void test_on_the_outer_circle(void) {
20+
TEST_IGNORE();
21+
uint8_t expected = 1;
22+
23+
TEST_ASSERT_EQUAL_UINT8(expected, score(0, 10));
24+
}
25+
26+
void test_on_the_middle_circle(void) {
27+
TEST_IGNORE();
28+
uint8_t expected = 5;
29+
30+
TEST_ASSERT_EQUAL_UINT8(expected, score(-5, 0));
31+
}
32+
33+
void test_on_the_inner_circle(void) {
34+
TEST_IGNORE();
35+
uint8_t expected = 10;
36+
37+
TEST_ASSERT_EQUAL_UINT8(expected, score(0, -1));
38+
}
39+
40+
void test_exactly_on_center(void) {
41+
TEST_IGNORE();
42+
uint8_t expected = 10;
43+
44+
TEST_ASSERT_EQUAL_UINT8(expected, score(0, 0));
45+
}
46+
47+
void test_near_the_center(void) {
48+
TEST_IGNORE();
49+
uint8_t expected = 10;
50+
51+
TEST_ASSERT_EQUAL_UINT8(expected, score(-0.1, -0.1));
52+
}
53+
54+
void test_just_within_the_inner_circle(void) {
55+
TEST_IGNORE();
56+
uint8_t expected = 10;
57+
58+
TEST_ASSERT_EQUAL_UINT8(expected, score(0.7, 0.7));
59+
}
60+
61+
void test_just_outside_the_inner_circle(void) {
62+
TEST_IGNORE();
63+
uint8_t expected = 5;
64+
65+
TEST_ASSERT_EQUAL_UINT8(expected, score(0.8, -0.8));
66+
}
67+
68+
void test_just_within_the_middle_circle(void) {
69+
TEST_IGNORE();
70+
uint8_t expected = 5;
71+
72+
TEST_ASSERT_EQUAL_UINT8(expected, score(-3.5, 3.5));
73+
}
74+
75+
void test_just_outside_the_middle_circle(void) {
76+
TEST_IGNORE();
77+
uint8_t expected = 1;
78+
79+
TEST_ASSERT_EQUAL_UINT8(expected, score(-3.6, -3.6));
80+
}
81+
82+
void test_just_within_the_outer_circle(void) {
83+
TEST_IGNORE();
84+
uint8_t expected = 1;
85+
86+
TEST_ASSERT_EQUAL_UINT8(expected, score(-7.0, 7.0));
87+
}
88+
89+
void test_just_outside_the_outer_circle(void) {
90+
TEST_IGNORE();
91+
uint8_t expected = 0;
92+
93+
TEST_ASSERT_EQUAL_UINT8(expected, score(7.1, -7.1));
94+
}
95+
96+
void test_asymmetric_position_between_the_inner_and_middle_circles(void) {
97+
TEST_IGNORE();
98+
uint8_t expected = 5;
99+
100+
TEST_ASSERT_EQUAL_UINT8(expected, score(0.5, -4));
101+
}
102+
103+
int main(void) {
104+
UNITY_BEGIN();
105+
RUN_TEST(test_missed_target);
106+
RUN_TEST(test_on_the_outer_circle);
107+
RUN_TEST(test_on_the_middle_circle);
108+
RUN_TEST(test_on_the_inner_circle);
109+
RUN_TEST(test_exactly_on_center);
110+
RUN_TEST(test_near_the_center);
111+
RUN_TEST(test_just_within_the_inner_circle);
112+
RUN_TEST(test_just_outside_the_inner_circle);
113+
RUN_TEST(test_just_within_the_middle_circle);
114+
RUN_TEST(test_just_outside_the_middle_circle);
115+
RUN_TEST(test_just_within_the_outer_circle);
116+
RUN_TEST(test_just_outside_the_outer_circle);
117+
RUN_TEST(test_asymmetric_position_between_the_inner_and_middle_circles);
118+
return UNITY_END();
119+
}

0 commit comments

Comments
 (0)