Skip to content

Commit

Permalink
Add prime-factors exercise
Browse files Browse the repository at this point in the history
  • Loading branch information
keiravillekode committed Oct 26, 2024
1 parent e88c618 commit 0cd3529
Show file tree
Hide file tree
Showing 12 changed files with 3,693 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,14 @@
"prerequisites": [],
"difficulty": 4
},
{
"slug": "prime-factors",
"name": "Prime Factors",
"uuid": "b0b7b69d-be21-43d0-9e9a-6b8650112a96",
"practices": [],
"prerequisites": [],
"difficulty": 4
},
{
"slug": "rotational-cipher",
"name": "Rotational Cipher",
Expand Down
36 changes: 36 additions & 0 deletions exercises/practice/prime-factors/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Instructions

Compute the prime factors of a given natural number.

A prime number is only evenly divisible by itself and 1.

Note that 1 is not a prime number.

## Example

What are the prime factors of 60?

- Our first divisor is 2.
2 goes into 60, leaving 30.
- 2 goes into 30, leaving 15.
- 2 doesn't go cleanly into 15.
So let's move on to our next divisor, 3.
- 3 goes cleanly into 15, leaving 5.
- 3 does not go cleanly into 5.
The next possible factor is 4.
- 4 does not go cleanly into 5.
The next possible factor is 5.
- 5 does go cleanly into 5.
- We're left only with 1, so now, we're done.

Our successful divisors in that computation represent the list of prime factors of 60: 2, 2, 3, and 5.

You can check this yourself:

```text
2 * 2 * 3 * 5
= 4 * 15
= 60
```

Success!
19 changes: 19 additions & 0 deletions exercises/practice/prime-factors/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"keiravillekode"
],
"files": {
"solution": [
"prime_factors.s"
],
"test": [
"prime_factors_test.c"
],
"example": [
".meta/example.s"
]
},
"blurb": "Compute the prime factors of a given natural number.",
"source": "The Prime Factors Kata by Uncle Bob",
"source_url": "https://web.archive.org/web/20221026171801/http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata"
}
35 changes: 35 additions & 0 deletions exercises/practice/prime-factors/.meta/example.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.text
.globl factors

/* extern size_t factors(uint64_t* dest, uint64_t value); */
factors:
mov x2, x0 /* start of output */
mov x3, #2 /* candidate factor */

.search:
cmp x1, #1
beq .return

udiv x4, x1, x3 /* quotient */
msub x5, x3, x4, x1 /* remainder */
cbz x5, .factor

cmp x3, x4
bgt .last

add x3, x3, 1
b .search

.last:
mov x3, x1
mov x4, #1

.factor:
str x3, [x0], #8 /* store, post-increment */
mov x1, x4
b .search

.return:
sub x0, x0, x2 /* number of bytes output */
lsr x0, x0, #3 /* number of primes output */
ret
46 changes: 46 additions & 0 deletions exercises/practice/prime-factors/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 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.

[924fc966-a8f5-4288-82f2-6b9224819ccd]
description = "no factors"

[17e30670-b105-4305-af53-ddde182cb6ad]
description = "prime number"

[238d57c8-4c12-42ef-af34-ae4929f94789]
description = "another prime number"

[f59b8350-a180-495a-8fb1-1712fbee1158]
description = "square of a prime"

[756949d3-3158-4e3d-91f2-c4f9f043ee70]
description = "product of first prime"

[bc8c113f-9580-4516-8669-c5fc29512ceb]
description = "cube of a prime"

[7d6a3300-a4cb-4065-bd33-0ced1de6cb44]
description = "product of second prime"

[073ac0b2-c915-4362-929d-fc45f7b9a9e4]
description = "product of third prime"

[6e0e4912-7fb6-47f3-a9ad-dbcd79340c75]
description = "product of first and second prime"

[00485cd3-a3fe-4fbe-a64a-a4308fc1f870]
description = "product of primes and non-primes"

[02251d54-3ca1-4a9b-85e1-b38f4b0ccb91]
description = "product of primes"

[070cf8dc-e202-4285-aa37-8d775c9cd473]
description = "factors include a large prime"
36 changes: 36 additions & 0 deletions exercises/practice/prime-factors/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/prime-factors/prime_factors.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.text
.globl factors

factors:
ret
157 changes: 157 additions & 0 deletions exercises/practice/prime-factors/prime_factors_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#include "vendor/unity.h"

#include <stddef.h>
#include <stdint.h>

#define MAX_ARRAY_SIZE 100
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

extern size_t factors(uint64_t* dest, uint64_t value);

void setUp(void) {
}

void tearDown(void) {
}

void test_no_factors(void) {
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 1);
TEST_ASSERT_EQUAL_UINT(0U, size);
}

void test_prime_number(void) {
TEST_IGNORE();
const uint64_t expected[] = {2};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 2);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_another_prime_number(void) {
TEST_IGNORE();
const uint64_t expected[] = {3};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 3);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_square_of_a_prime(void) {
TEST_IGNORE();
const uint64_t expected[] = {3, 3};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 9);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_product_of_first_prime(void) {
TEST_IGNORE();
const uint64_t expected[] = {2, 2};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 4);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_cube_of_a_prime(void) {
TEST_IGNORE();
const uint64_t expected[] = {2, 2, 2};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 8);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_product_of_second_prime(void) {
TEST_IGNORE();
const uint64_t expected[] = {3, 3, 3};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 27);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_product_of_third_prime(void) {
TEST_IGNORE();
const uint64_t expected[] = {5, 5, 5, 5};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 625);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_product_of_first_and_second_prime(void) {
TEST_IGNORE();
const uint64_t expected[] = {2, 3};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 6);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_product_of_primes_and_nonprimes(void) {
TEST_IGNORE();
const uint64_t expected[] = {2, 2, 3};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 12);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_product_of_primes(void) {
TEST_IGNORE();
const uint64_t expected[] = {5, 17, 23, 461};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 901255);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_factors_include_a_large_prime(void) {
TEST_IGNORE();
const uint64_t expected[] = {11, 9539, 894119};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 93819012551);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_product_of_three_large_primes(void) {
TEST_IGNORE();
const uint64_t expected[] = {2077681, 2099191, 2101243};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 9164464719174396253);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

void test_one_very_large_prime(void) {
TEST_IGNORE();
const uint64_t expected[] = {4016465016163};
uint64_t actual[MAX_ARRAY_SIZE];
const size_t size = factors(actual, 4016465016163);
TEST_ASSERT_EQUAL_UINT(ARRAY_SIZE(expected), size);
TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, size);
}

int main(void) {
UNITY_BEGIN();
RUN_TEST(test_no_factors);
RUN_TEST(test_prime_number);
RUN_TEST(test_another_prime_number);
RUN_TEST(test_square_of_a_prime);
RUN_TEST(test_product_of_first_prime);
RUN_TEST(test_cube_of_a_prime);
RUN_TEST(test_product_of_second_prime);
RUN_TEST(test_product_of_third_prime);
RUN_TEST(test_product_of_first_and_second_prime);
RUN_TEST(test_product_of_primes_and_nonprimes);
RUN_TEST(test_product_of_primes);
RUN_TEST(test_factors_include_a_large_prime);
RUN_TEST(test_product_of_three_large_primes);
RUN_TEST(test_one_very_large_prime);
return UNITY_END();
}
Loading

0 comments on commit 0cd3529

Please sign in to comment.