C: sum of multiples + complex numbers
This commit is contained in:
51
c/complex-numbers/GNUmakefile
Normal file
51
c/complex-numbers/GNUmakefile
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# The original 'makefile' has a flaw:
|
||||||
|
# 1) it overrides CFLAGS
|
||||||
|
# 2) it does not pass extra "FLAGS" to $(CC) that could come from environment
|
||||||
|
#
|
||||||
|
# It means :
|
||||||
|
# - we need to edit 'makefile' for different builds (DEBUG, etc...), which is
|
||||||
|
# not practical at all.
|
||||||
|
# - Also, it does not allow to run all tests without editing the test source
|
||||||
|
# code.
|
||||||
|
#
|
||||||
|
# To use this makefile (GNU make only):
|
||||||
|
# "make": build with all predefined tests (without editing test source code)
|
||||||
|
# "make debugall": build with all predefined tests and debug code
|
||||||
|
# "make mem": perform memcheck with all tests enabled
|
||||||
|
# "make unit": build standalone (unit) test
|
||||||
|
# "make debug": build standalone test with debugging code
|
||||||
|
#
|
||||||
|
# Original 'makefile' targets can be used (test, memcheck, clean, ...)
|
||||||
|
|
||||||
|
.PHONY: default all mem unit debug std debugtest
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
# default is to build with all predefined tests
|
||||||
|
BUILD := teststall
|
||||||
|
|
||||||
|
include makefile
|
||||||
|
|
||||||
|
all: CFLAGS+=-DTESTALL
|
||||||
|
all: clean test
|
||||||
|
|
||||||
|
debugall: CFLAGS+=-DDEBUG
|
||||||
|
debugall: all
|
||||||
|
|
||||||
|
debugtest: CFLAGS+=-DDEBUG
|
||||||
|
debugtest: test
|
||||||
|
|
||||||
|
mem: CFLAGS+=-DTESTALL
|
||||||
|
mem: clean memcheck
|
||||||
|
|
||||||
|
unit: CFLAGS+=-DUNIT_TEST
|
||||||
|
unit: clean std
|
||||||
|
|
||||||
|
debug: CFLAGS+=-DUNIT_TEST -DDEBUG
|
||||||
|
debug: clean std
|
||||||
|
|
||||||
|
debugtest: CFLAGS+=-DDEBUG
|
||||||
|
debugtest: test
|
||||||
|
|
||||||
|
std: src/*.c src/*.h
|
||||||
|
$(CC) $(CFLAGS) src/*.c -o test.out
|
67
c/complex-numbers/README.md
Normal file
67
c/complex-numbers/README.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Complex Numbers
|
||||||
|
|
||||||
|
A complex number is a number in the form `a + b * i` where `a` and `b` are real and `i` satisfies `i^2 = -1`.
|
||||||
|
|
||||||
|
`a` is called the real part and `b` is called the imaginary part of `z`.
|
||||||
|
The conjugate of the number `a + b * i` is the number `a - b * i`.
|
||||||
|
The absolute value of a complex number `z = a + b * i` is a real number `|z| = sqrt(a^2 + b^2)`. The square of the absolute value `|z|^2` is the result of multiplication of `z` by its complex conjugate.
|
||||||
|
|
||||||
|
The sum/difference of two complex numbers involves adding/subtracting their real and imaginary parts separately:
|
||||||
|
`(a + i * b) + (c + i * d) = (a + c) + (b + d) * i`,
|
||||||
|
`(a + i * b) - (c + i * d) = (a - c) + (b - d) * i`.
|
||||||
|
|
||||||
|
Multiplication result is by definition
|
||||||
|
`(a + i * b) * (c + i * d) = (a * c - b * d) + (b * c + a * d) * i`.
|
||||||
|
|
||||||
|
The reciprocal of a non-zero complex number is
|
||||||
|
`1 / (a + i * b) = a/(a^2 + b^2) - b/(a^2 + b^2) * i`.
|
||||||
|
|
||||||
|
Dividing a complex number `a + i * b` by another `c + i * d` gives:
|
||||||
|
`(a + i * b) / (c + i * d) = (a * c + b * d)/(c^2 + d^2) + (b * c - a * d)/(c^2 + d^2) * i`.
|
||||||
|
|
||||||
|
Raising e to a complex exponent can be expressed as `e^(a + i * b) = e^a * e^(i * b)`, the last term of which is given by Euler's formula `e^(i * b) = cos(b) + i * sin(b)`.
|
||||||
|
|
||||||
|
Implement the following operations:
|
||||||
|
- addition, subtraction, multiplication and division of two complex numbers,
|
||||||
|
- conjugate, absolute value, exponent of a given complex number.
|
||||||
|
|
||||||
|
|
||||||
|
Assume the programming language you are using does not have an implementation of complex numbers.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
Make sure you have read the "Guides" section of the
|
||||||
|
[C track][c-track] on the Exercism site. This covers
|
||||||
|
the basic information on setting up the development environment expected
|
||||||
|
by the exercises.
|
||||||
|
|
||||||
|
## Passing the Tests
|
||||||
|
|
||||||
|
Get the first test compiling, linking and passing by following the [three
|
||||||
|
rules of test-driven development][3-tdd-rules].
|
||||||
|
|
||||||
|
The included makefile can be used to create and run the tests using the `test`
|
||||||
|
task.
|
||||||
|
|
||||||
|
make test
|
||||||
|
|
||||||
|
Create just the functions you need to satisfy any compiler errors and get the
|
||||||
|
test to fail. Then write just enough code to get the test to pass. Once you've
|
||||||
|
done that, move onto the next test.
|
||||||
|
|
||||||
|
As you progress through the tests, take the time to refactor your
|
||||||
|
implementation for readability and expressiveness and then go on to the next
|
||||||
|
test.
|
||||||
|
|
||||||
|
Try to use standard C99 facilities in preference to writing your own
|
||||||
|
low-level algorithms or facilities by hand.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Wikipedia [https://en.wikipedia.org/wiki/Complex_number](https://en.wikipedia.org/wiki/Complex_number)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
||||||
|
[c-track]: https://exercism.io/my/tracks/c
|
||||||
|
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
|
38
c/complex-numbers/makefile
Normal file
38
c/complex-numbers/makefile
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
### If you wish to use extra libraries (math.h for instance),
|
||||||
|
### add their flags here (-lm in our case) in the "LIBS" variable.
|
||||||
|
|
||||||
|
LIBS = -lm
|
||||||
|
|
||||||
|
###
|
||||||
|
CFLAGS = -std=c99
|
||||||
|
CFLAGS += -g
|
||||||
|
CFLAGS += -Wall
|
||||||
|
CFLAGS += -Wextra
|
||||||
|
CFLAGS += -pedantic
|
||||||
|
CFLAGS += -Werror
|
||||||
|
CFLAGS += -Wmissing-declarations
|
||||||
|
CFLAGS += -DUNITY_SUPPORT_64
|
||||||
|
CFLAGS += -DUNITY_INCLUDE_DOUBLE
|
||||||
|
|
||||||
|
ASANFLAGS = -fsanitize=address
|
||||||
|
ASANFLAGS += -fno-common
|
||||||
|
ASANFLAGS += -fno-omit-frame-pointer
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: tests.out
|
||||||
|
@./tests.out
|
||||||
|
|
||||||
|
.PHONY: memcheck
|
||||||
|
memcheck: test/*.c src/*.c src/*.h
|
||||||
|
@echo Compiling $@
|
||||||
|
@$(CC) $(ASANFLAGS) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o memcheck.out $(LIBS)
|
||||||
|
@./memcheck.out
|
||||||
|
@echo "Memory check passed"
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -rf *.o *.out *.out.dSYM
|
||||||
|
|
||||||
|
tests.out: test/*.c src/*.c src/*.h
|
||||||
|
@echo Compiling $@
|
||||||
|
@$(CC) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o tests.out $(LIBS)
|
96
c/complex-numbers/src/complex_numbers.c
Normal file
96
c/complex-numbers/src/complex_numbers.c
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include "complex_numbers.h"
|
||||||
|
|
||||||
|
#ifdef USE_COMPLEX_FUNCTIONS
|
||||||
|
|
||||||
|
complex_t c_add(complex_t a, complex_t b)
|
||||||
|
{
|
||||||
|
return (complex_t) {
|
||||||
|
.real = a.real+b.real,
|
||||||
|
.imag = a.imag+b.imag
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
complex_t c_sub(complex_t a, complex_t b)
|
||||||
|
{
|
||||||
|
return (complex_t) {
|
||||||
|
.real = a.real-b.real,
|
||||||
|
.imag = a.imag-b.imag
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
complex_t c_mul(complex_t a, complex_t b)
|
||||||
|
{
|
||||||
|
return (complex_t) {
|
||||||
|
.real = a.real*b.real - a.imag*b.imag,
|
||||||
|
.imag = a.imag*b.real + a.real*b.imag,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
complex_t c_div(complex_t a, complex_t b)
|
||||||
|
{
|
||||||
|
double d = b.real*b.real + b.imag*b.imag;
|
||||||
|
return (complex_t) {
|
||||||
|
.real = (a.real*b.real + a.imag*b.imag)/d,
|
||||||
|
.imag = (a.imag*b.real - a.real*b.imag)/d
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
double c_abs(complex_t x)
|
||||||
|
{
|
||||||
|
return sqrt(x.real*x.real + x.imag*x.imag);
|
||||||
|
}
|
||||||
|
|
||||||
|
complex_t c_conjugate(complex_t x)
|
||||||
|
{
|
||||||
|
return (complex_t) {
|
||||||
|
.real = x.real,
|
||||||
|
.imag = -x.imag
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
double c_real(complex_t x)
|
||||||
|
{
|
||||||
|
return x.real;
|
||||||
|
}
|
||||||
|
|
||||||
|
double c_imag(complex_t x)
|
||||||
|
{
|
||||||
|
return x.imag;
|
||||||
|
}
|
||||||
|
|
||||||
|
complex_t c_exp(complex_t x)
|
||||||
|
{
|
||||||
|
return (complex_t) {
|
||||||
|
.real = exp(x.real)*cos(x.imag),
|
||||||
|
.imag = exp(x.real)*sin(x.imag)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* See GNUmakefile below for explanation
|
||||||
|
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
|
||||||
|
*/
|
||||||
|
#ifdef UNIT_TEST
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main(int ac, char **av)
|
||||||
|
{
|
||||||
|
int arg=1;
|
||||||
|
complex_t c1, c2, c3;
|
||||||
|
|
||||||
|
for (; arg<ac-3; ++arg, ++arg) {
|
||||||
|
c1.real=atof(av[arg]);
|
||||||
|
c1.imag=atof(av[arg+1]);
|
||||||
|
|
||||||
|
c2.real=atof(av[arg+2]);
|
||||||
|
c2.imag=atof(av[arg+3]);
|
||||||
|
c3 = c_add(c1, c2);
|
||||||
|
printf("(%f + %fi) + (%f + %fi) = (%f + %fi)\n",
|
||||||
|
c1.real, c1.imag,
|
||||||
|
c2.real, c2.imag,
|
||||||
|
c3.real, c3.imag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
70
c/complex-numbers/src/complex_numbers.h
Normal file
70
c/complex-numbers/src/complex_numbers.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#ifndef _COMPLEX_NUMBERS_H_
|
||||||
|
#define _COMPLEX_NUMBERS_H_
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double real;
|
||||||
|
double imag;
|
||||||
|
} complex_t;
|
||||||
|
|
||||||
|
/* default is to use macros */
|
||||||
|
#ifdef USE_COMPLEX_FUNCTIONS
|
||||||
|
|
||||||
|
complex_t c_add(complex_t a, complex_t b);
|
||||||
|
complex_t c_sub(complex_t a, complex_t b);
|
||||||
|
complex_t c_mul(complex_t a, complex_t b);
|
||||||
|
complex_t c_div(complex_t a, complex_t b);
|
||||||
|
double c_abs(complex_t x);
|
||||||
|
complex_t c_conjugate(complex_t x);
|
||||||
|
double c_real(complex_t x);
|
||||||
|
double c_imag(complex_t x);
|
||||||
|
complex_t c_exp(complex_t x);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define c_add(a,b) (complex_t) { \
|
||||||
|
(a).real+(b).real, \
|
||||||
|
(a).imag+(b).imag }
|
||||||
|
|
||||||
|
#define c_sub(a,b) (complex_t) { \
|
||||||
|
(a).real-(b).real, \
|
||||||
|
(a).imag-(b).imag }
|
||||||
|
|
||||||
|
#define c_mul(a,b) (complex_t) { \
|
||||||
|
(a).real*(b).real - (a).imag*(b).imag, \
|
||||||
|
(a).imag*(b).real + (a).real*(b).imag }
|
||||||
|
|
||||||
|
#define c_div(a,b) (complex_t) { \
|
||||||
|
((a).real*(b).real + (a).imag*(b).imag)/ \
|
||||||
|
((b).real*(b).real + (b).imag*(b).imag), \
|
||||||
|
((a).imag*(b).real - (a).real*(b).imag)/ \
|
||||||
|
((b).real*(b).real + (b).imag*(b).imag) }
|
||||||
|
|
||||||
|
#define c_exp(x) (complex_t) { \
|
||||||
|
exp((x).real) * cos((x).imag), \
|
||||||
|
exp((x).real) * sin((x).imag) }
|
||||||
|
|
||||||
|
#define c_abs(x) { sqrt((x).real*(x).real + (x).imag*(x).imag) }
|
||||||
|
|
||||||
|
#define c_conjugate(x) (complex_t){ (x).real, -(x).imag }
|
||||||
|
|
||||||
|
#define c_real(x) (x).real
|
||||||
|
|
||||||
|
#define c_imag(x) (x).imag
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* See GNUmakefile below for explanation
|
||||||
|
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
|
||||||
|
*/
|
||||||
|
#if defined UNIT_TEST || defined DEBUG
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef TESTALL
|
||||||
|
#undef TEST_IGNORE
|
||||||
|
#define TEST_IGNORE() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@@ -39,7 +39,7 @@ int add_student(char *s, uint8_t g)
|
|||||||
*/
|
*/
|
||||||
roster_t get_grade(uint8_t g)
|
roster_t get_grade(uint8_t g)
|
||||||
{
|
{
|
||||||
static roster_t r;
|
roster_t r;
|
||||||
unsigned i, j=0;
|
unsigned i, j=0;
|
||||||
|
|
||||||
for (i=0; i<roster.count && GRADE(i)<=g; ++i) {
|
for (i=0; i<roster.count && GRADE(i)<=g; ++i) {
|
||||||
|
14
c/square-root/src/square_root.c
Normal file → Executable file
14
c/square-root/src/square_root.c
Normal file → Executable file
@@ -28,10 +28,9 @@ unsigned square_root(unsigned i)
|
|||||||
if (i<=1) /* 0 and 1 */
|
if (i<=1) /* 0 and 1 */
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
//nbits = (sizeof(unsigned) * 8);
|
for (j = 4, max = 16;; j += 2, max <<= 2) {
|
||||||
for (j = 4, max = 16L;; j += 2, max <<= 2L) {
|
|
||||||
if (j >= NBITS || i <= max) {
|
if (j >= NBITS || i <= max) {
|
||||||
sq2 = (1L << (j >> 1));
|
sq2 = (1 << (j >> 1));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,11 +44,18 @@ unsigned square_root(unsigned i)
|
|||||||
#ifdef UNIT_TEST
|
#ifdef UNIT_TEST
|
||||||
int main(int ac, char **av)
|
int main(int ac, char **av)
|
||||||
{
|
{
|
||||||
unsigned i, j;
|
unsigned i;
|
||||||
|
/* int arg=1;
|
||||||
|
|
||||||
|
for (; arg<ac; ++arg) {
|
||||||
|
i=atol(av[arg]);
|
||||||
|
printf("sqrt(%u)=%u\n", i, square_root(i));
|
||||||
|
}
|
||||||
|
*/
|
||||||
if (ac && *av)
|
if (ac && *av)
|
||||||
for (i=0; i<100000000; ++i)
|
for (i=0; i<100000000; ++i)
|
||||||
square_root(65025);
|
square_root(65025);
|
||||||
printf("sq=%u\n", square_root(65536));
|
printf("sq=%u\n", square_root(65536));
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
51
c/sum-of-multiples/GNUmakefile
Executable file
51
c/sum-of-multiples/GNUmakefile
Executable file
@@ -0,0 +1,51 @@
|
|||||||
|
# The original 'makefile' has a flaw:
|
||||||
|
# 1) it overrides CFLAGS
|
||||||
|
# 2) it does not pass extra "FLAGS" to $(CC) that could come from environment
|
||||||
|
#
|
||||||
|
# It means :
|
||||||
|
# - we need to edit 'makefile' for different builds (DEBUG, etc...), which is
|
||||||
|
# not practical at all.
|
||||||
|
# - Also, it does not allow to run all tests without editing the test source
|
||||||
|
# code.
|
||||||
|
#
|
||||||
|
# To use this makefile (GNU make only):
|
||||||
|
# "make": build with all predefined tests (without editing test source code)
|
||||||
|
# "make debugall": build with all predefined tests and debug code
|
||||||
|
# "make mem": perform memcheck with all tests enabled
|
||||||
|
# "make unit": build standalone (unit) test
|
||||||
|
# "make debug": build standalone test with debugging code
|
||||||
|
#
|
||||||
|
# Original 'makefile' targets can be used (test, memcheck, clean, ...)
|
||||||
|
|
||||||
|
.PHONY: default all mem unit debug std debugtest
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
# default is to build with all predefined tests
|
||||||
|
BUILD := teststall
|
||||||
|
|
||||||
|
include makefile
|
||||||
|
|
||||||
|
all: CFLAGS+=-DTESTALL
|
||||||
|
all: clean test
|
||||||
|
|
||||||
|
debugall: CFLAGS+=-DDEBUG
|
||||||
|
debugall: all
|
||||||
|
|
||||||
|
debugtest: CFLAGS+=-DDEBUG
|
||||||
|
debugtest: test
|
||||||
|
|
||||||
|
mem: CFLAGS+=-DTESTALL
|
||||||
|
mem: clean memcheck
|
||||||
|
|
||||||
|
unit: CFLAGS+=-DUNIT_TEST
|
||||||
|
unit: clean std
|
||||||
|
|
||||||
|
debug: CFLAGS+=-DUNIT_TEST -DDEBUG
|
||||||
|
debug: clean std
|
||||||
|
|
||||||
|
debugtest: CFLAGS+=-DDEBUG
|
||||||
|
debugtest: test
|
||||||
|
|
||||||
|
std: src/*.c src/*.h
|
||||||
|
$(CC) $(CFLAGS) src/*.c -o test.out
|
47
c/sum-of-multiples/README.md
Executable file
47
c/sum-of-multiples/README.md
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
# Sum Of Multiples
|
||||||
|
|
||||||
|
Given a number, find the sum of all the unique multiples of particular numbers up to
|
||||||
|
but not including that number.
|
||||||
|
|
||||||
|
If we list all the natural numbers below 20 that are multiples of 3 or 5,
|
||||||
|
we get 3, 5, 6, 9, 10, 12, 15, and 18.
|
||||||
|
|
||||||
|
The sum of these multiples is 78.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
Make sure you have read the "Guides" section of the
|
||||||
|
[C track][c-track] on the Exercism site. This covers
|
||||||
|
the basic information on setting up the development environment expected
|
||||||
|
by the exercises.
|
||||||
|
|
||||||
|
## Passing the Tests
|
||||||
|
|
||||||
|
Get the first test compiling, linking and passing by following the [three
|
||||||
|
rules of test-driven development][3-tdd-rules].
|
||||||
|
|
||||||
|
The included makefile can be used to create and run the tests using the `test`
|
||||||
|
task.
|
||||||
|
|
||||||
|
make test
|
||||||
|
|
||||||
|
Create just the functions you need to satisfy any compiler errors and get the
|
||||||
|
test to fail. Then write just enough code to get the test to pass. Once you've
|
||||||
|
done that, move onto the next test.
|
||||||
|
|
||||||
|
As you progress through the tests, take the time to refactor your
|
||||||
|
implementation for readability and expressiveness and then go on to the next
|
||||||
|
test.
|
||||||
|
|
||||||
|
Try to use standard C99 facilities in preference to writing your own
|
||||||
|
low-level algorithms or facilities by hand.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
A variation on Problem 1 at Project Euler [http://projecteuler.net/problem=1](http://projecteuler.net/problem=1)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
||||||
|
[c-track]: https://exercism.io/my/tracks/c
|
||||||
|
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
|
37
c/sum-of-multiples/makefile
Executable file
37
c/sum-of-multiples/makefile
Executable file
@@ -0,0 +1,37 @@
|
|||||||
|
### If you wish to use extra libraries (math.h for instance),
|
||||||
|
### add their flags here (-lm in our case) in the "LIBS" variable.
|
||||||
|
|
||||||
|
LIBS = -lm
|
||||||
|
|
||||||
|
###
|
||||||
|
CFLAGS = -std=c99
|
||||||
|
CFLAGS += -g
|
||||||
|
CFLAGS += -Wall
|
||||||
|
CFLAGS += -Wextra
|
||||||
|
CFLAGS += -pedantic
|
||||||
|
CFLAGS += -Werror
|
||||||
|
CFLAGS += -Wmissing-declarations
|
||||||
|
CFLAGS += -DUNITY_SUPPORT_64
|
||||||
|
|
||||||
|
ASANFLAGS = -fsanitize=address
|
||||||
|
ASANFLAGS += -fno-common
|
||||||
|
ASANFLAGS += -fno-omit-frame-pointer
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: tests.out
|
||||||
|
@./tests.out
|
||||||
|
|
||||||
|
.PHONY: memcheck
|
||||||
|
memcheck: test/*.c src/*.c src/*.h
|
||||||
|
@echo Compiling $@
|
||||||
|
@$(CC) $(ASANFLAGS) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o memcheck.out $(LIBS)
|
||||||
|
@./memcheck.out
|
||||||
|
@echo "Memory check passed"
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -rf *.o *.out *.out.dSYM
|
||||||
|
|
||||||
|
tests.out: test/*.c src/*.c src/*.h
|
||||||
|
@echo Compiling $@
|
||||||
|
@$(CC) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o tests.out $(LIBS)
|
57
c/sum-of-multiples/src/sum_of_multiples.c
Executable file
57
c/sum-of-multiples/src/sum_of_multiples.c
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
/* V1: initial version
|
||||||
|
* V2: bug fix: force full unsigned allocation instead of bytes.
|
||||||
|
*/
|
||||||
|
#include "sum_of_multiples.h"
|
||||||
|
|
||||||
|
#define BITS (sizeof(unsigned)*8)
|
||||||
|
|
||||||
|
#define getbit(i) (!!(sieve[(i) / BITS] & (1 << ((i) % BITS))))
|
||||||
|
#define setbit(i) (sieve[(i) / BITS] |= (1 << ((i) % BITS)))
|
||||||
|
|
||||||
|
/* use a kind of eratosthenes's sieve, to avoid the trivial solution :-)
|
||||||
|
*/
|
||||||
|
unsigned sum(const unsigned *f, const size_t n, const unsigned l)
|
||||||
|
{
|
||||||
|
unsigned sieve_size = (l-1)/BITS+1;
|
||||||
|
unsigned num, i, res=0;
|
||||||
|
unsigned *sieve;
|
||||||
|
|
||||||
|
sieve = calloc(sieve_size, sizeof(unsigned)); /* l bits array */
|
||||||
|
if (!sieve)
|
||||||
|
return 0;
|
||||||
|
for (i=0; i<n; ++i) {
|
||||||
|
if (f[i]) {
|
||||||
|
for (num=f[i]; num<l; num+=f[i]) {
|
||||||
|
if (!getbit(num)) {
|
||||||
|
res+=num;
|
||||||
|
setbit(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(sieve);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See GNUmakefile below for explanation
|
||||||
|
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
|
||||||
|
*/
|
||||||
|
#ifdef UNIT_TEST
|
||||||
|
int main(int ac, char **av)
|
||||||
|
{
|
||||||
|
unsigned input[256];
|
||||||
|
int last, i;
|
||||||
|
if (ac>2) {
|
||||||
|
last=atol(av[1]);
|
||||||
|
for (i=2; i<ac; ++i) {
|
||||||
|
input[i-2]=atoi(av[i]);
|
||||||
|
}
|
||||||
|
printf("sum(..., %u, %u)=%u\n", i-2, last,
|
||||||
|
sum(input, (unsigned)i-2, (unsigned)last));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
21
c/sum-of-multiples/src/sum_of_multiples.h
Executable file
21
c/sum-of-multiples/src/sum_of_multiples.h
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef SUM_OF_MULTIPLES_H
|
||||||
|
#define SUM_OF_MULTIPLES_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
unsigned int sum(const unsigned int *factors,
|
||||||
|
const size_t number_of_factors, const unsigned int limit);
|
||||||
|
|
||||||
|
/* See GNUmakefile below for explanation
|
||||||
|
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
|
||||||
|
*/
|
||||||
|
#if defined UNIT_TEST || defined DEBUG
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef TESTALL
|
||||||
|
#undef TEST_IGNORE
|
||||||
|
#define TEST_IGNORE() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue
Block a user