Skip to content

Commit

Permalink
Add difference-of-squares exercise (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
keiravillekode authored Oct 19, 2024
1 parent 0b77765 commit df3e55c
Show file tree
Hide file tree
Showing 12 changed files with 3,605 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@
"prerequisites": [],
"difficulty": 2
},
{
"slug": "difference-of-squares",
"name": "Difference of Squares",
"uuid": "88ebf02b-e19b-4058-a48b-2e1560345dd0",
"practices": [],
"prerequisites": [],
"difficulty": 3
},
{
"slug": "eliuds-eggs",
"name": "Eliud's Eggs",
Expand Down
14 changes: 14 additions & 0 deletions exercises/practice/difference-of-squares/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Instructions

Find the difference between the square of the sum and the sum of the squares of the first N natural numbers.

The square of the sum of the first ten natural numbers is
(1 + 2 + ... + 10)² = 55² = 3025.

The sum of the squares of the first ten natural numbers is
1² + 2² + ... + 10² = 385.

Hence the difference between the square of the sum of the first ten natural numbers and the sum of the squares of the first ten natural numbers is 3025 - 385 = 2640.

You are not expected to discover an efficient solution to this yourself from first principles; research is allowed, indeed, encouraged.
Finding the best algorithm for the problem is a key skill in software engineering.
19 changes: 19 additions & 0 deletions exercises/practice/difference-of-squares/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"keiravillekode"
],
"files": {
"solution": [
"difference_of_squares.s"
],
"test": [
"difference_of_squares_test.c"
],
"example": [
".meta/example.s"
]
},
"blurb": "Find the difference between the square of the sum and the sum of the squares of the first N natural numbers.",
"source": "Problem 6 at Project Euler",
"source_url": "https://projecteuler.net/problem=6"
}
35 changes: 35 additions & 0 deletions exercises/practice/difference-of-squares/.meta/example.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.text
.globl square_of_sum
.globl sum_of_squares
.globl difference_of_squares

/* extern uint64_t square_of_sum(uint64_t number); */
square_of_sum:
add x1, x0, #1
mul x0, x0, x1
lsr x0, x0, #1 /* number (number + 1) / 2 */
mul x0, x0, x0 /* number**2 (number + 1)**2 / 4 */
ret

/* extern uint64_t sum_of_squares(uint64_t number); */
sum_of_squares:
add x1, x0, #1
mul x2, x0, x1 /* number (number + 1) */
add x0, x0, x1 /* 2 * number + 1 */
mul x0, x0, x2
mov x1, #6
udiv x0, x0, x1 /* number (number + 1) (2 * number + 1) / 6 */
ret

/* extern uint64_t difference_of_squares(uint64_t number); */
difference_of_squares:
add x1, x0, #1
add x2, x0, x1 /* 2 * number + 1 */
mul x0, x0, x1
lsr x0, x0, #1 /* number (number + 1) / 2 */
mul x2, x0, x2
mov x1, #3
udiv x2, x2, x1 /* number (number + 1) (2 * number + 1) / 6 */
mul x0, x0, x0 /* number**2 (number + 1)**2 / 4 */
sub x0, x0, x2
ret
37 changes: 37 additions & 0 deletions exercises/practice/difference-of-squares/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 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.

[e46c542b-31fc-4506-bcae-6b62b3268537]
description = "Square the sum of the numbers up to the given number -> square of sum 1"

[9b3f96cb-638d-41ee-99b7-b4f9c0622948]
description = "Square the sum of the numbers up to the given number -> square of sum 5"

[54ba043f-3c35-4d43-86ff-3a41625d5e86]
description = "Square the sum of the numbers up to the given number -> square of sum 100"

[01d84507-b03e-4238-9395-dd61d03074b5]
description = "Sum the squares of the numbers up to the given number -> sum of squares 1"

[c93900cd-8cc2-4ca4-917b-dd3027023499]
description = "Sum the squares of the numbers up to the given number -> sum of squares 5"

[94807386-73e4-4d9e-8dec-69eb135b19e4]
description = "Sum the squares of the numbers up to the given number -> sum of squares 100"

[44f72ae6-31a7-437f-858d-2c0837adabb6]
description = "Subtract sum of squares from square of sums -> difference of squares 1"

[005cb2bf-a0c8-46f3-ae25-924029f8b00b]
description = "Subtract sum of squares from square of sums -> difference of squares 5"

[b1bf19de-9a16-41c0-a62b-1f02ecc0b036]
description = "Subtract sum of squares from square of sums -> difference of squares 100"
36 changes: 36 additions & 0 deletions exercises/practice/difference-of-squares/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
13 changes: 13 additions & 0 deletions exercises/practice/difference-of-squares/difference_of_squares.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.text
.globl square_of_sum
.globl sum_of_squares
.globl difference_of_squares

square_of_sum:
ret

sum_of_squares:
ret

difference_of_squares:
ret
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include "vendor/unity.h"

#include <stdint.h>

extern uint64_t square_of_sum(uint64_t number);

extern uint64_t sum_of_squares(uint64_t number);

extern uint64_t difference_of_squares(uint64_t number);

void setUp(void) {
}

void tearDown(void) {
}

void test_square_of_sum_1(void) {
TEST_ASSERT_EQUAL_UINT64(1U, square_of_sum(1));
}

void test_square_of_sum_5(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_UINT64(225U, square_of_sum(5));
}

void test_square_of_sum_100(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_UINT64(25502500U, square_of_sum(100));
}

void test_sum_of_squares_1(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_UINT64(1U, sum_of_squares(1));
}

void test_sum_of_squares_5(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_UINT64(55U, sum_of_squares(5));
}

void test_sum_of_squares_100(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_UINT64(338350U, sum_of_squares(100));
}

void test_difference_of_squares_1(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_UINT64(0U, difference_of_squares(1));
}

void test_difference_of_squares_5(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_UINT64(170U, difference_of_squares(5));
}

void test_difference_of_squares_100(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_UINT64(25164150U, difference_of_squares(100));
}

void test_square_of_sum_90000(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_UINT64(16402864502025000000U, square_of_sum(90000));
}

void test_sum_of_squares_90000(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_UINT64(243004050015000U, sum_of_squares(90000));
}

void test_difference_of_squares_90000(void) {
TEST_IGNORE();
TEST_ASSERT_EQUAL_UINT64(16402621497974985000U, difference_of_squares(90000));
}

int main(void) {
UNITY_BEGIN();
RUN_TEST(test_square_of_sum_1);
RUN_TEST(test_square_of_sum_5);
RUN_TEST(test_square_of_sum_100);
RUN_TEST(test_sum_of_squares_1);
RUN_TEST(test_sum_of_squares_5);
RUN_TEST(test_sum_of_squares_100);
RUN_TEST(test_difference_of_squares_1);
RUN_TEST(test_difference_of_squares_5);
RUN_TEST(test_difference_of_squares_100);
RUN_TEST(test_square_of_sum_90000);
RUN_TEST(test_sum_of_squares_90000);
RUN_TEST(test_difference_of_squares_90000);
return UNITY_END();
}
Loading

0 comments on commit df3e55c

Please sign in to comment.