Skip to content

Commit

Permalink
Add resistor-color-duo exercise (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
keiravillekode authored Oct 25, 2023
1 parent 571f3dc commit 9e44561
Show file tree
Hide file tree
Showing 12 changed files with 3,619 additions and 0 deletions.
11 changes: 11 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,17 @@
"arrays"
]
},
{
"slug": "resistor-color-duo",
"name": "Resistor Color Duo",
"uuid": "d2a983d7-3e9a-43fd-a916-23d51401c68e",
"practices": [],
"prerequisites": [],
"difficulty": 3,
"topics": [
"arrays"
]
},
{
"slug": "space-age",
"name": "Space Age",
Expand Down
33 changes: 33 additions & 0 deletions exercises/practice/resistor-color-duo/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Instructions

If you want to build something using a Raspberry Pi, you'll probably use _resistors_.
For this exercise, you need to know two things about them:

- Each resistor has a resistance value.
- Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read.

To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values.
Each band has a position and a numeric value.

The first 2 bands of a resistor have a simple encoding scheme: each color maps to a single number.
For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15.

In this exercise you are going to create a helpful program so that you don't have to remember the values of the bands.
The program will take color names as input and output a two digit number, even if the input is more than two colors!

The band colors are encoded as follows:

- Black: 0
- Brown: 1
- Red: 2
- Orange: 3
- Yellow: 4
- Green: 5
- Blue: 6
- Violet: 7
- Grey: 8
- White: 9

From the example above:
brown-green should return 15
brown-green-violet should return 15 too, ignoring the third color.
2 changes: 2 additions & 0 deletions exercises/practice/resistor-color-duo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.o
tests
19 changes: 19 additions & 0 deletions exercises/practice/resistor-color-duo/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"keiravillekode"
],
"files": {
"solution": [
"resistor_color_duo.asm"
],
"test": [
"resistor_color_duo_test.c"
],
"example": [
".meta/example.asm"
]
},
"blurb": "Convert color codes, as used on resistors, to a numeric value.",
"source": "Maud de Vries, Erik Schierboom",
"source_url": "https://github.com/exercism/problem-specifications/issues/1464"
}
108 changes: 108 additions & 0 deletions exercises/practice/resistor-color-duo/.meta/example.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
default rel

; From the resistor-color exercise
section .rodata
black: db "black", 0
brown: db "brown", 0
red: db "red", 0
orange: db "orange", 0
yellow: db "yellow", 0
green: db "green", 0
blue: db "blue", 0
violet: db "violet", 0
grey: db "grey", 0
white: db "white", 0

; From the resistor-color exercise
section .data
color_array:
dq black
dq brown
dq red
dq orange
dq yellow
dq green
dq blue
dq violet
dq grey
dq white
dq 0 ; Sentinel value to indicate end of array

section .text
global value
value:
;
; Convert from resistor band colors to the numeric representation.
;
; Parameters:
; rdi - address of first input string
; rsi - address of second input string
; rdx - address of third input string, or 0 (NULL)
; Returns:
; rax - numeric value of resistor's first two color codes
;
mov r9, rsi
call color_code
mov rdx, 10
mul rdx
mov r10, rax
mov rdi, r9
call color_code
add rax, r10
ret

; From the resistor-color exercise

;
; Convert a resistor band's color to its numeric representation.
;
; Parameters:
; rdi - color
; Returns:
; rax - the resistor band's numeric representation or -1 if not found
;
color_code:
xor eax, eax ; Initialize array index
lea rcx, [color_array] ; Load color array
mov rdx, [rcx + rax * 8] ; Read color from array
.arr_loop_start:
mov rsi, rdi ; Save input color

mov r8b, byte [rdx] ; Read char from color
cmp r8b, byte [rsi] ; Compare with char from input color
jne .str_loop_end ; If not equal, skip loop
.str_loop_start:
inc rdx ; Advance color to next char
inc rsi ; Advance input color to next char
mov r8b, byte [rdx] ; Read char from color
cmp r8b, byte [rsi] ; Compare with char from input color
jne .str_loop_end ; If not equal, exit loop
test r8b, r8b ; See if we reached end of color
jne .str_loop_start ; If chars remain, loop back

.str_loop_end:
cmp r8b, byte [rsi] ; Check if we found a match
je .return ; If we found a match, return the array index
inc eax ; Increment array index
mov rdx, [rcx + rax * 8] ; Read color from array
test rdx, rdx ; See if we reached end of array
jne .arr_loop_start ; If colors remain, loop back

mov eax, -1 ; Return -1

.return:
ret

;
; Get a list of resistor band colors.
;
; Returns:
; rax - a list of colors
;
colors:
lea rax, [color_array] ; Return the list of colors
ret

%ifidn __OUTPUT_FORMAT__,elf64
section .note.GNU-stack noalloc noexec nowrite progbits
%endif
31 changes: 31 additions & 0 deletions exercises/practice/resistor-color-duo/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 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.

[ce11995a-5b93-4950-a5e9-93423693b2fc]
description = "Brown and black"

[7bf82f7a-af23-48ba-a97d-38d59406a920]
description = "Blue and grey"

[f1886361-fdfd-4693-acf8-46726fe24e0c]
description = "Yellow and violet"

[b7a6cbd2-ae3c-470a-93eb-56670b305640]
description = "White and red"

[77a8293d-2a83-4016-b1af-991acc12b9fe]
description = "Orange and orange"

[0c4fb44f-db7c-4d03-afa8-054350f156a8]
description = "Ignore additional colors"

[4a8ceec5-0ab4-4904-88a4-daf953a5e818]
description = "Black and brown, one-digit"
46 changes: 46 additions & 0 deletions exercises/practice/resistor-color-duo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
AS = nasm

CFLAGS = -g -Wall -Wextra -pedantic -Werror
LDFLAGS =
ASFLAGS = -g -F dwarf -Werror

ifeq ($(shell uname -s),Darwin)
ifeq ($(shell sysctl -n hw.optional.arm64 2>/dev/null),1)
ALL_CFLAGS = -target x86_64-apple-darwin
endif
ALL_LDFLAGS = -Wl,-pie -Wl,-fatal_warnings
ALL_ASFLAGS = -f macho64 --prefix _
else
ALL_LDFLAGS = -pie -Wl,--fatal-warnings
ALL_ASFLAGS = -f elf64
endif

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

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

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

all: tests
@./$<

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

%.o: %.asm
@$(AS) $(ALL_ASFLAGS) -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
9 changes: 9 additions & 0 deletions exercises/practice/resistor-color-duo/resistor_color_duo.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
section .text
global value
value:
; Provide your implementation here
ret

%ifidn __OUTPUT_FORMAT__,elf64
section .note.GNU-stack noalloc noexec nowrite progbits
%endif
57 changes: 57 additions & 0 deletions exercises/practice/resistor-color-duo/resistor_color_duo_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Version: 1.0.0

#include "vendor/unity.h"

extern int value(const char *first, const char *second, const char *third);

void setUp(void) {
}

void tearDown(void) {
}

void test_brown_and_black(void) {
TEST_ASSERT_EQUAL_INT(10, value("brown", "black", NULL));
}

void test_blue_and_grey(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(68, value("blue", "grey", NULL));
}

void test_yellow_and_violet(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(47, value("yellow", "violet", NULL));
}

void test_white_and_red(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(92, value("white", "red", NULL));
}

void test_orange_and_orange(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(33, value("orange", "orange", NULL));
}

void test_ignore_additional_colors(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(51, value("green", "brown", "orange"));
}

void test_black_and_brown_one_digit(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(1, value("black", "brown", NULL));
}

int main(void) {
UNITY_BEGIN();
RUN_TEST(test_brown_and_black);
RUN_TEST(test_blue_and_grey);
RUN_TEST(test_yellow_and_violet);
RUN_TEST(test_white_and_red);
RUN_TEST(test_orange_and_orange);
RUN_TEST(test_ignore_additional_colors);
RUN_TEST(test_black_and_brown_one_digit);
return UNITY_END();
}
Loading

0 comments on commit 9e44561

Please sign in to comment.