Compare commits

..

47 Commits

Author SHA1 Message Date
f4acc1434a C: improve templates 2021-09-10 18:22:24 +02:00
67b2d3ec40 C: run-length-encoding 2021-09-10 18:21:53 +02:00
9a3d216a65 bulk changes, forgot what ;-) 2021-09-08 16:51:29 +02:00
10f4f8572d C two-bucket: final version + separate main 2021-09-08 14:10:05 +02:00
3a3d50b0a5 two-buckets: changes in move handling 2021-09-08 12:57:42 +02:00
7b92456167 C two-buckets, 1st running version 2021-09-07 21:46:23 +02:00
07eb95fb58 Tentative improvement of exercism warning handling... 2021-09-07 21:44:42 +02:00
916c67f31e revert C99 test - typo in fallthrough macro 2021-09-05 21:06:10 +02:00
dd929471f2 C: more comments in phone number, rename list.h, C99 tests 2021-09-05 18:52:45 +02:00
c1a62521c4 C phone-number: more comments 2021-09-05 12:46:41 +02:00
0333652fdc C phone-number: more comments 2021-09-05 12:29:12 +02:00
c6d39e8702 C phone-number: more comments, code improvement (maybe ;-) 2021-09-05 12:00:53 +02:00
064f3d27a9 linked list V1 / phone-number typos / student setup script V1 2021-09-04 20:57:50 +02:00
33cc1343cb C: change phone-number to exercism V3 2021-09-03 15:51:40 +02:00
77a8072c73 C: change phone-number to exercism V3 2021-09-03 15:50:08 +02:00
215629a19c C: create my own include file 2021-09-03 15:17:18 +02:00
8ebb596c9f GNUmakefile: typo 2021-08-29 13:21:25 +02:00
e988624f95 GNUmakefile: removes -Werror instead of -Wall and -Wextra 2021-08-29 13:09:30 +02:00
3795a5b605 C: phone-number + new GNUmakefile 2021-08-29 13:07:47 +02:00
c9ddb8b3ce C template GNUmakefile: remove redundant clean in "nowarn" target 2021-08-27 21:54:27 +02:00
9cc619e37f C templates GNUmakefile : cleanup and doc update 2021-08-27 21:29:04 +02:00
9e85bd36df C templates GNUmakefile: add nowarn target 2021-08-27 20:15:16 +02:00
e45819d3ef C: allergies 2021-08-27 20:14:58 +02:00
29905d7894 C: allergies 2021-08-26 15:05:12 +02:00
5a35db2396 C: pythagorean-triplet and saddle-point 2021-08-25 20:35:55 +02:00
b200831b51 C list-ops: removed unused macro 2021-08-23 18:19:00 +02:00
d3002514a5 C: list-ops 2021-08-23 17:32:21 +02:00
7cf02bc336 C: circular buffer 2021-08-22 16:29:11 +02:00
002ce9c313 C: rational-numbers 2021-08-21 15:06:04 +02:00
4f882b01cc GNUmakefile: fix $(LIBS) missing 2021-08-21 15:05:17 +02:00
9901680424 git: ignore users/ 2021-08-20 16:42:33 +02:00
6c5e61efe9 C: simplify hamming/binary search 2021-08-20 16:41:13 +02:00
01fcdc8566 C: binary search 2021-08-20 01:02:07 +02:00
01365f370b grade-school: fix header declarions 2021-08-18 22:05:42 +02:00
f8574c2f4e C: Two fer 2021-08-16 18:55:37 +02:00
03ab0349a3 roman numerals: avoid useless n-=0*val 2021-08-16 17:18:26 +02:00
04f1f5e23b C: roman numerals 2021-08-16 16:58:27 +02:00
e357f5c26a C: sum of multiples + complex numbers 2021-08-15 16:58:11 +02:00
ccb96a4f2a C bob: added unit testing code 2021-08-13 17:03:02 +02:00
46d0fa38b2 C: bob 2021-08-13 16:25:38 +02:00
021b014151 C: secret handshake 2021-08-13 14:39:36 +02:00
01dd79be15 square root: improvement on square root seed 2021-08-13 11:53:56 +02:00
4cf3fb610a C: grade school 2021-08-13 11:53:31 +02:00
58d81e96a6 C: raindrops 2021-08-12 12:24:38 +02:00
6e9a77168e C: beer song 2021-08-12 11:18:40 +02:00
69ffe15ed6 C: leap 2021-08-12 09:34:38 +02:00
9542b0bf09 C: nucleotide-count & rna-transcription 2021-08-11 20:57:57 +02:00
143 changed files with 7901 additions and 75 deletions

3
.gitignore vendored
View File

@@ -2,4 +2,7 @@ core
*.out
*_test.sh
test/
test-framework/
users/
.exercism
.projectile

View File

@@ -1 +1 @@
My solutions to some [exercism](https://exercism.io/) exercises.
My solutions to some [exercism](https://exercism.org/) exercises.

51
c/allergies/GNUmakefile Normal file
View 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 tests.out $(LIBS)

68
c/allergies/README.md Normal file
View File

@@ -0,0 +1,68 @@
# Allergies
Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.
An allergy test produces a single numeric score which contains the
information about all the allergies the person has (that they were
tested for).
The list of items (and their value) that were tested are:
* eggs (1)
* peanuts (2)
* shellfish (4)
* strawberries (8)
* tomatoes (16)
* chocolate (32)
* pollen (64)
* cats (128)
So if Tom is allergic to peanuts and chocolate, he gets a score of 34.
Now, given just that score of 34, your program should be able to say:
- Whether Tom is allergic to any one of those allergens listed above.
- All the allergens Tom is allergic to.
Note: a given score may include allergens **not** listed above (i.e.
allergens that score 256, 512, 1024, etc.). Your program should
ignore those components of the score. For example, if the allergy
score is 257, your program should only report the eggs (1) allergy.
## 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
Jumpstart Lab Warm-up [http://jumpstartlab.com](http://jumpstartlab.com)
## 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/allergies/makefile Normal file
View 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)

View File

@@ -0,0 +1,20 @@
#include "allergies.h"
#ifdef USE_ALLERGIC_TO_FUNCTION
bool is_allergic_to(const allergen_t all, const uint32_t val)
{
return !!(val & (1 << all));
}
#endif
allergen_list_t get_allergens(uint32_t val)
{
allergen_list_t list = { .count = 0 };
allergen_t i;
for (i=0; i<ALLERGEN_COUNT; ++i) {
list.allergens[i] = is_allergic_to(i, val);
list.count += list.allergens[i];
}
return list;
}

View File

@@ -0,0 +1,46 @@
#ifndef ALLERGIES_H
#define ALLERGIES_H
#include <stdbool.h>
#include <stdint.h>
typedef enum {
ALLERGEN_EGGS = 0,
ALLERGEN_PEANUTS,
ALLERGEN_SHELLFISH,
ALLERGEN_STRAWBERRIES,
ALLERGEN_TOMATOES,
ALLERGEN_CHOCOLATE,
ALLERGEN_POLLEN,
ALLERGEN_CATS,
ALLERGEN_COUNT,
} allergen_t;
typedef struct {
int count;
bool allergens[ALLERGEN_COUNT];
} allergen_list_t;
// We can choose macro or function
#ifdef USE_ALLERGIC_TO_FUNCTION
bool is_allergic_to(const allergen_t allergen, const uint32_t value);
#else
#define is_allergic_to(allerg, val) (!!((val) & (1 << (allerg))))
#endif
allergen_list_t get_allergens(uint32_t value);
/* 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

51
c/beer-song/GNUmakefile Normal file
View 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

359
c/beer-song/README.md Normal file
View File

@@ -0,0 +1,359 @@
# Beer Song
Recite the lyrics to that beloved classic, that field-trip favorite: 99 Bottles of Beer on the Wall.
Note that not all verses are identical.
```text
99 bottles of beer on the wall, 99 bottles of beer.
Take one down and pass it around, 98 bottles of beer on the wall.
98 bottles of beer on the wall, 98 bottles of beer.
Take one down and pass it around, 97 bottles of beer on the wall.
97 bottles of beer on the wall, 97 bottles of beer.
Take one down and pass it around, 96 bottles of beer on the wall.
96 bottles of beer on the wall, 96 bottles of beer.
Take one down and pass it around, 95 bottles of beer on the wall.
95 bottles of beer on the wall, 95 bottles of beer.
Take one down and pass it around, 94 bottles of beer on the wall.
94 bottles of beer on the wall, 94 bottles of beer.
Take one down and pass it around, 93 bottles of beer on the wall.
93 bottles of beer on the wall, 93 bottles of beer.
Take one down and pass it around, 92 bottles of beer on the wall.
92 bottles of beer on the wall, 92 bottles of beer.
Take one down and pass it around, 91 bottles of beer on the wall.
91 bottles of beer on the wall, 91 bottles of beer.
Take one down and pass it around, 90 bottles of beer on the wall.
90 bottles of beer on the wall, 90 bottles of beer.
Take one down and pass it around, 89 bottles of beer on the wall.
89 bottles of beer on the wall, 89 bottles of beer.
Take one down and pass it around, 88 bottles of beer on the wall.
88 bottles of beer on the wall, 88 bottles of beer.
Take one down and pass it around, 87 bottles of beer on the wall.
87 bottles of beer on the wall, 87 bottles of beer.
Take one down and pass it around, 86 bottles of beer on the wall.
86 bottles of beer on the wall, 86 bottles of beer.
Take one down and pass it around, 85 bottles of beer on the wall.
85 bottles of beer on the wall, 85 bottles of beer.
Take one down and pass it around, 84 bottles of beer on the wall.
84 bottles of beer on the wall, 84 bottles of beer.
Take one down and pass it around, 83 bottles of beer on the wall.
83 bottles of beer on the wall, 83 bottles of beer.
Take one down and pass it around, 82 bottles of beer on the wall.
82 bottles of beer on the wall, 82 bottles of beer.
Take one down and pass it around, 81 bottles of beer on the wall.
81 bottles of beer on the wall, 81 bottles of beer.
Take one down and pass it around, 80 bottles of beer on the wall.
80 bottles of beer on the wall, 80 bottles of beer.
Take one down and pass it around, 79 bottles of beer on the wall.
79 bottles of beer on the wall, 79 bottles of beer.
Take one down and pass it around, 78 bottles of beer on the wall.
78 bottles of beer on the wall, 78 bottles of beer.
Take one down and pass it around, 77 bottles of beer on the wall.
77 bottles of beer on the wall, 77 bottles of beer.
Take one down and pass it around, 76 bottles of beer on the wall.
76 bottles of beer on the wall, 76 bottles of beer.
Take one down and pass it around, 75 bottles of beer on the wall.
75 bottles of beer on the wall, 75 bottles of beer.
Take one down and pass it around, 74 bottles of beer on the wall.
74 bottles of beer on the wall, 74 bottles of beer.
Take one down and pass it around, 73 bottles of beer on the wall.
73 bottles of beer on the wall, 73 bottles of beer.
Take one down and pass it around, 72 bottles of beer on the wall.
72 bottles of beer on the wall, 72 bottles of beer.
Take one down and pass it around, 71 bottles of beer on the wall.
71 bottles of beer on the wall, 71 bottles of beer.
Take one down and pass it around, 70 bottles of beer on the wall.
70 bottles of beer on the wall, 70 bottles of beer.
Take one down and pass it around, 69 bottles of beer on the wall.
69 bottles of beer on the wall, 69 bottles of beer.
Take one down and pass it around, 68 bottles of beer on the wall.
68 bottles of beer on the wall, 68 bottles of beer.
Take one down and pass it around, 67 bottles of beer on the wall.
67 bottles of beer on the wall, 67 bottles of beer.
Take one down and pass it around, 66 bottles of beer on the wall.
66 bottles of beer on the wall, 66 bottles of beer.
Take one down and pass it around, 65 bottles of beer on the wall.
65 bottles of beer on the wall, 65 bottles of beer.
Take one down and pass it around, 64 bottles of beer on the wall.
64 bottles of beer on the wall, 64 bottles of beer.
Take one down and pass it around, 63 bottles of beer on the wall.
63 bottles of beer on the wall, 63 bottles of beer.
Take one down and pass it around, 62 bottles of beer on the wall.
62 bottles of beer on the wall, 62 bottles of beer.
Take one down and pass it around, 61 bottles of beer on the wall.
61 bottles of beer on the wall, 61 bottles of beer.
Take one down and pass it around, 60 bottles of beer on the wall.
60 bottles of beer on the wall, 60 bottles of beer.
Take one down and pass it around, 59 bottles of beer on the wall.
59 bottles of beer on the wall, 59 bottles of beer.
Take one down and pass it around, 58 bottles of beer on the wall.
58 bottles of beer on the wall, 58 bottles of beer.
Take one down and pass it around, 57 bottles of beer on the wall.
57 bottles of beer on the wall, 57 bottles of beer.
Take one down and pass it around, 56 bottles of beer on the wall.
56 bottles of beer on the wall, 56 bottles of beer.
Take one down and pass it around, 55 bottles of beer on the wall.
55 bottles of beer on the wall, 55 bottles of beer.
Take one down and pass it around, 54 bottles of beer on the wall.
54 bottles of beer on the wall, 54 bottles of beer.
Take one down and pass it around, 53 bottles of beer on the wall.
53 bottles of beer on the wall, 53 bottles of beer.
Take one down and pass it around, 52 bottles of beer on the wall.
52 bottles of beer on the wall, 52 bottles of beer.
Take one down and pass it around, 51 bottles of beer on the wall.
51 bottles of beer on the wall, 51 bottles of beer.
Take one down and pass it around, 50 bottles of beer on the wall.
50 bottles of beer on the wall, 50 bottles of beer.
Take one down and pass it around, 49 bottles of beer on the wall.
49 bottles of beer on the wall, 49 bottles of beer.
Take one down and pass it around, 48 bottles of beer on the wall.
48 bottles of beer on the wall, 48 bottles of beer.
Take one down and pass it around, 47 bottles of beer on the wall.
47 bottles of beer on the wall, 47 bottles of beer.
Take one down and pass it around, 46 bottles of beer on the wall.
46 bottles of beer on the wall, 46 bottles of beer.
Take one down and pass it around, 45 bottles of beer on the wall.
45 bottles of beer on the wall, 45 bottles of beer.
Take one down and pass it around, 44 bottles of beer on the wall.
44 bottles of beer on the wall, 44 bottles of beer.
Take one down and pass it around, 43 bottles of beer on the wall.
43 bottles of beer on the wall, 43 bottles of beer.
Take one down and pass it around, 42 bottles of beer on the wall.
42 bottles of beer on the wall, 42 bottles of beer.
Take one down and pass it around, 41 bottles of beer on the wall.
41 bottles of beer on the wall, 41 bottles of beer.
Take one down and pass it around, 40 bottles of beer on the wall.
40 bottles of beer on the wall, 40 bottles of beer.
Take one down and pass it around, 39 bottles of beer on the wall.
39 bottles of beer on the wall, 39 bottles of beer.
Take one down and pass it around, 38 bottles of beer on the wall.
38 bottles of beer on the wall, 38 bottles of beer.
Take one down and pass it around, 37 bottles of beer on the wall.
37 bottles of beer on the wall, 37 bottles of beer.
Take one down and pass it around, 36 bottles of beer on the wall.
36 bottles of beer on the wall, 36 bottles of beer.
Take one down and pass it around, 35 bottles of beer on the wall.
35 bottles of beer on the wall, 35 bottles of beer.
Take one down and pass it around, 34 bottles of beer on the wall.
34 bottles of beer on the wall, 34 bottles of beer.
Take one down and pass it around, 33 bottles of beer on the wall.
33 bottles of beer on the wall, 33 bottles of beer.
Take one down and pass it around, 32 bottles of beer on the wall.
32 bottles of beer on the wall, 32 bottles of beer.
Take one down and pass it around, 31 bottles of beer on the wall.
31 bottles of beer on the wall, 31 bottles of beer.
Take one down and pass it around, 30 bottles of beer on the wall.
30 bottles of beer on the wall, 30 bottles of beer.
Take one down and pass it around, 29 bottles of beer on the wall.
29 bottles of beer on the wall, 29 bottles of beer.
Take one down and pass it around, 28 bottles of beer on the wall.
28 bottles of beer on the wall, 28 bottles of beer.
Take one down and pass it around, 27 bottles of beer on the wall.
27 bottles of beer on the wall, 27 bottles of beer.
Take one down and pass it around, 26 bottles of beer on the wall.
26 bottles of beer on the wall, 26 bottles of beer.
Take one down and pass it around, 25 bottles of beer on the wall.
25 bottles of beer on the wall, 25 bottles of beer.
Take one down and pass it around, 24 bottles of beer on the wall.
24 bottles of beer on the wall, 24 bottles of beer.
Take one down and pass it around, 23 bottles of beer on the wall.
23 bottles of beer on the wall, 23 bottles of beer.
Take one down and pass it around, 22 bottles of beer on the wall.
22 bottles of beer on the wall, 22 bottles of beer.
Take one down and pass it around, 21 bottles of beer on the wall.
21 bottles of beer on the wall, 21 bottles of beer.
Take one down and pass it around, 20 bottles of beer on the wall.
20 bottles of beer on the wall, 20 bottles of beer.
Take one down and pass it around, 19 bottles of beer on the wall.
19 bottles of beer on the wall, 19 bottles of beer.
Take one down and pass it around, 18 bottles of beer on the wall.
18 bottles of beer on the wall, 18 bottles of beer.
Take one down and pass it around, 17 bottles of beer on the wall.
17 bottles of beer on the wall, 17 bottles of beer.
Take one down and pass it around, 16 bottles of beer on the wall.
16 bottles of beer on the wall, 16 bottles of beer.
Take one down and pass it around, 15 bottles of beer on the wall.
15 bottles of beer on the wall, 15 bottles of beer.
Take one down and pass it around, 14 bottles of beer on the wall.
14 bottles of beer on the wall, 14 bottles of beer.
Take one down and pass it around, 13 bottles of beer on the wall.
13 bottles of beer on the wall, 13 bottles of beer.
Take one down and pass it around, 12 bottles of beer on the wall.
12 bottles of beer on the wall, 12 bottles of beer.
Take one down and pass it around, 11 bottles of beer on the wall.
11 bottles of beer on the wall, 11 bottles of beer.
Take one down and pass it around, 10 bottles of beer on the wall.
10 bottles of beer on the wall, 10 bottles of beer.
Take one down and pass it around, 9 bottles of beer on the wall.
9 bottles of beer on the wall, 9 bottles of beer.
Take one down and pass it around, 8 bottles of beer on the wall.
8 bottles of beer on the wall, 8 bottles of beer.
Take one down and pass it around, 7 bottles of beer on the wall.
7 bottles of beer on the wall, 7 bottles of beer.
Take one down and pass it around, 6 bottles of beer on the wall.
6 bottles of beer on the wall, 6 bottles of beer.
Take one down and pass it around, 5 bottles of beer on the wall.
5 bottles of beer on the wall, 5 bottles of beer.
Take one down and pass it around, 4 bottles of beer on the wall.
4 bottles of beer on the wall, 4 bottles of beer.
Take one down and pass it around, 3 bottles of beer on the wall.
3 bottles of beer on the wall, 3 bottles of beer.
Take one down and pass it around, 2 bottles of beer on the wall.
2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.
1 bottle of beer on the wall, 1 bottle of beer.
Take it down and pass it around, no more bottles of beer on the wall.
No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
```
## For bonus points
Did you get the tests passing and the code clean? If you want to, these
are some additional things you could try:
* Remove as much duplication as you possibly can.
* Optimize for readability, even if it means introducing duplication.
* If you've removed all the duplication, do you have a lot of
conditionals? Try replacing the conditionals with polymorphism, if it
applies in this language. How readable is it?
Then please share your thoughts in a comment on the submission. Did this
experiment make the code better? Worse? Did you learn anything from it?
## 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
Learn to Program by Chris Pine [http://pine.fm/LearnToProgram/?Chapter=06](http://pine.fm/LearnToProgram/?Chapter=06)
## 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/beer-song/makefile Normal file
View 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)

View File

@@ -0,0 +1,44 @@
#include "beer_song.h"
#include <stdio.h>
static char *fmt1="%s bottle%s of beer on the wall, %s bottle%s of beer.\n" \
"Take %s down and pass it around, %s bottle%s of beer on the wall.\n%s";
static char *fmt2="%s bottle%s of beer on the wall, %s bottle%s of beer.\n" \
"%sGo to the store and buy some more, %s bottle%s of beer on the wall.\n%s";
void recite(unsigned int start, unsigned int down, char *buffer)
{
char n1[16], n2[16];
char *p=buffer;
while (down--) {
sprintf(n1, "%d", start);
sprintf(n2, "%d", start>1? start-1: 99);
p+=sprintf(p, start? fmt1: fmt2,
start? n1: "No more", start==1? "": "s", start? n1: "no more",
start==1? "": "s",
start==1? "it": start? "one": "", start-1? n2: "no more",
start==2? "": "s", down? "\n": "");
start=start? start-1: 99;
}
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
int main(int ac, char **av)
{
int arg=1;
unsigned i, j;
char buffer[1024];
for (; arg<ac-1; ++arg, ++arg) {
i=atoi(av[arg]);
j=atoi(av[arg+1]);
recite(i, j, buffer);
printf("recite(%d, %d):\n%s", i, j, buffer);
}
}
#endif

View File

@@ -0,0 +1,18 @@
#ifndef BEER_SONG_H
#define BEER_SONG_H
void recite(unsigned int start_bottles, unsigned int take_down, char *buffer);
/* 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

View 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

73
c/binary-search/README.md Normal file
View File

@@ -0,0 +1,73 @@
# Binary Search
Implement a binary search algorithm.
Searching a sorted collection is a common task. A dictionary is a sorted
list of word definitions. Given a word, one can find its definition. A
telephone book is a sorted list of people's names, addresses, and
telephone numbers. Knowing someone's name allows one to quickly find
their telephone number and address.
If the list to be searched contains more than a few items (a dozen, say)
a binary search will require far fewer comparisons than a linear search,
but it imposes the requirement that the list be sorted.
In computer science, a binary search or half-interval search algorithm
finds the position of a specified input value (the search "key") within
an array sorted by key value.
In each step, the algorithm compares the search key value with the key
value of the middle element of the array.
If the keys match, then a matching element has been found and its index,
or position, is returned.
Otherwise, if the search key is less than the middle element's key, then
the algorithm repeats its action on the sub-array to the left of the
middle element or, if the search key is greater, on the sub-array to the
right.
If the remaining array to be searched is empty, then the key cannot be
found in the array and a special "not found" indication is returned.
A binary search halves the number of items to check with each iteration,
so locating an item (or determining its absence) takes logarithmic time.
A binary search is a dichotomic divide and conquer search algorithm.
## 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 [http://en.wikipedia.org/wiki/Binary_search_algorithm](http://en.wikipedia.org/wiki/Binary_search_algorithm)
## 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/binary-search/makefile Normal file
View 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)

View File

@@ -0,0 +1,37 @@
#include "binary_search.h"
const int *binary_search(int v, const int *a, size_t size)
{
size_t lo, hi, i;
/* early exclude invalid/trivial result: NULL/empty array, value off bounds
*/
if (!size || !a || v < *a || v > *(a+size-1))
return NULL;
for (lo=0, hi=size-1, i=hi/2; lo<hi && a[i]!=v; i=lo+(hi-lo)/2) {
if (a[i] < v)
lo=i+1;
else
hi=i-1;
}
return a[i]==v? a+i: NULL;
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
int main(int ac, char **av)
{
int arg=1, *res;
int i, array[] = {1, 2, 3, 4, 6, 7, 8, 9 };
size_t size = sizeof(array) / sizeof(array[0]);
for (; arg<ac; ++arg) {
i=atoi(av[arg]);
res=binary_search(i, array, size);
printf("binary_search(%d)=%ld\n", i,
res? res-array: -1);
}
}
#endif

View File

@@ -0,0 +1,21 @@
#ifndef BINARY_SEARCH_H
#define BINARY_SEARCH_H
#include <stddef.h>
const int *binary_search(int value, const int *arr, size_t length);
/* 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

51
c/bob/GNUmakefile Normal file
View 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

54
c/bob/README.md Normal file
View File

@@ -0,0 +1,54 @@
# Bob
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
Bob answers 'Sure.' if you ask him a question, such as "How are you?".
He answers 'Whoa, chill out!' if you YELL AT HIM (in all capitals).
He answers 'Calm down, I know what I'm doing!' if you yell a question at him.
He says 'Fine. Be that way!' if you address him without actually saying
anything.
He answers 'Whatever.' to anything else.
Bob's conversational partner is a purist when it comes to written communication and always follows normal rules regarding sentence punctuation in English.
## 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
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [http://pine.fm/LearnToProgram/?Chapter=06](http://pine.fm/LearnToProgram/?Chapter=06)
## 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/bob/makefile Normal file
View 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)

40
c/bob/src/bob.c Normal file
View File

@@ -0,0 +1,40 @@
#include <ctype.h>
#include "bob.h"
char*answers[] = {
"Whatever.",
"Sure.",
"Whoa, chill out!",
"Calm down, I know what I'm doing!",
"Fine. Be that way!"
};
char *hey_bob(char *w)
{
int yell=2, question=0, empty=4, text=0;
for (;*w; w++) {
if (!isspace(*w)) {
empty=0;
if (isalpha(*w)) text=2;
if (islower (*w)) yell=0;
question=*w=='?'? 1: 0;
}
}
return answers[(text&yell)|question|empty];
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
#include <stdio.h>
int main(int ac, char **av)
{
int arg=1;
for (; arg<ac; ++arg) {
printf("bob(%s)=%s\n", av[arg], hey_bob(av[arg]));
}
}
#endif

18
c/bob/src/bob.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef BOB_H
#define BOB_H
char *hey_bob(char *greeting);
/* 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

View 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 tests.out $(LIBS)

View File

@@ -0,0 +1,89 @@
# Circular Buffer
A circular buffer, cyclic buffer or ring buffer is a data structure that
uses a single, fixed-size buffer as if it were connected end-to-end.
A circular buffer first starts empty and of some predefined length. For
example, this is a 7-element buffer:
[ ][ ][ ][ ][ ][ ][ ]
Assume that a 1 is written into the middle of the buffer (exact starting
location does not matter in a circular buffer):
[ ][ ][ ][1][ ][ ][ ]
Then assume that two more elements are added — 2 & 3 — which get
appended after the 1:
[ ][ ][ ][1][2][3][ ]
If two elements are then removed from the buffer, the oldest values
inside the buffer are removed. The two elements removed, in this case,
are 1 & 2, leaving the buffer with just a 3:
[ ][ ][ ][ ][ ][3][ ]
If the buffer has 7 elements then it is completely full:
[6][7][8][9][3][4][5]
When the buffer is full an error will be raised, alerting the client
that further writes are blocked until a slot becomes free.
When the buffer is full, the client can opt to overwrite the oldest
data with a forced write. In this case, two more elements — A & B —
are added and they overwrite the 3 & 4:
[6][7][8][9][A][B][5]
3 & 4 have been replaced by A & B making 5 now the oldest data in the
buffer. Finally, if two elements are removed then what would be
returned is 5 & 6 yielding the buffer:
[ ][7][8][9][A][B][ ]
Because there is space available, if the client again uses overwrite
to store C & D then the space where 5 & 6 were stored previously will
be used not the location of 7 & 8. 7 is still the oldest element and
the buffer is once again full.
[D][7][8][9][A][B][C]
## 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 [http://en.wikipedia.org/wiki/Circular_buffer](http://en.wikipedia.org/wiki/Circular_buffer)
## 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

View 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)

View File

@@ -0,0 +1,75 @@
#include <malloc.h>
#include <errno.h>
#include "circular_buffer.h"
#define INC(v, size) {if (++v==size) v=0;}
circular_buffer_t *new_circular_buffer(size_t size)
{
circular_buffer_t *head = NULL;
if (size > 0) {
if ((head=malloc(sizeof(*head)))) {
clear_buffer(head);
head->size = size;
/* we could have only 1 alloc, I just prefer this double alloc
*/
if (!(head->buf = calloc(size, sizeof(buffer_value_t)))) {
free(head);
head = NULL;
}
}
}
return head;
}
int do_write(circular_buffer_t *b, buffer_value_t v, int f)
{
if (!f && b->used == b->size) {
errno = ENOBUFS;
return EXIT_FAILURE;
}
b->buf[b->head] = v;
INC(b->head, b->size);
if (f && b->used == b->size) /* overwrite and full */
INC(b->tail, b->size);
if (b->used < b->size) /* normal write */
b->used++;
return EXIT_SUCCESS;
}
int read(circular_buffer_t *b, buffer_value_t *p)
{
if (!b->used) {
errno = ENODATA;
return EXIT_FAILURE;
}
b->used--;
*p = b->buf[b->tail];
INC(b->tail, b->size);
return EXIT_SUCCESS;
}
int clear_buffer(circular_buffer_t *b)
{
b->head = 0;
b->tail = 0;
b->used = 0;
return EXIT_SUCCESS;
}
void delete_buffer(circular_buffer_t *b) {
free(b->buf);
free(b);
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
int main(int ac, char **av)
{
/* not done for circular buffer : simple exercise, with difficult testing */
}
#endif

View File

@@ -0,0 +1,41 @@
#ifndef CIRCULAR_BUFFER_H
#define CIRCULAR_BUFFER_H
#include <stdlib.h>
typedef char buffer_value_t;
/* used and tail are redundant, but allow easier code (and maybe easier
* to read ?).
*/
typedef struct circular_buffer {
int head;
int tail;
int used;
int size;
buffer_value_t *buf;
} circular_buffer_t;
extern circular_buffer_t *new_circular_buffer(size_t size);
extern int do_write(circular_buffer_t *buffer, buffer_value_t value, int force);
extern int read(circular_buffer_t *buffer, buffer_value_t *retval);
extern int clear_buffer(circular_buffer_t *buffer);
extern void delete_buffer(circular_buffer_t *buffer);
#define write(buffer, value) do_write((buffer), (value), 0)
#define overwrite(buffer, value) do_write((buffer), (value), 1)
/* 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

View 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

View 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

View 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)

View 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

View 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

View 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

76
c/grade-school/README.md Normal file
View File

@@ -0,0 +1,76 @@
# Grade School
Given students' names along with the grade that they are in, create a roster
for the school.
In the end, you should be able to:
- Add a student's name to the roster for a grade
- "Add Jim to grade 2."
- "OK."
- Get a list of all students enrolled in a grade
- "Which students are in grade 2?"
- "We've only got Jim just now."
- Get a sorted list of all students in all grades. Grades should sort
as 1, 2, 3, etc., and students within a grade should be sorted
alphabetically by name.
- "Who all is enrolled in school right now?"
- "Let me think. We have
Anna, Barb, and Charlie in grade 1,
Alex, Peter, and Zoe in grade 2
and Jim in grade 5.
So the answer is: Anna, Barb, Charlie, Alex, Peter, Zoe and Jim"
Note that all our students only have one name. (It's a small town, what
do you want?)
## For bonus points
Did you get the tests passing and the code clean? If you want to, these
are some additional things you could try:
- If you're working in a language with mutable data structures and your
implementation allows outside code to mutate the school's internal DB
directly, see if you can prevent this. Feel free to introduce additional
tests.
Then please share your thoughts in a comment on the submission. Did this
experiment make the code better? Worse? Did you learn anything from it?
## 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 pairing session with Phil Battos at gSchool [http://gschool.it](http://gschool.it)
## 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/grade-school/makefile Normal file
View 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)

View File

@@ -0,0 +1,83 @@
#include "grade_school.h"
#include <string.h>
#include <stdio.h>
#define STD(i) roster.students[i]
#define NAME(i) roster.students[i].name
#define GRADE(i) roster.students[i].grade
static roster_t roster;
void clear_roster()
{
roster.count=0;
}
/* testing program expects bool here, but I prefer to return students count,
* it makes more sense for me.
*/
int add_student(const char *s, const uint8_t g)
{
int c=roster.count, i;
if (c >= MAX_STUDENTS)
return 0;
// find correct place to insert name
for (i=0; i<c && (GRADE(i)<g || (GRADE(i)==g && strcmp(s, NAME(i))>0)); ++i)
;
for (int j=c-1; j>=i; --j) /* move rest to right */
STD(j+1)=STD(j);
NAME(i)=s; /* insert new name */
GRADE(i)=g;
return ++roster.count;
}
/* to avoid this everytime, we could build up one roster per grade while
* adding students, but really overkill here.
*/
roster_t get_grade(const uint8_t g)
{
roster_t r;
unsigned i, j;
for (i=0, j=0; i<roster.count && GRADE(i)<=g; ++i) {
if (GRADE(i)==g)
r.students[j++]=STD(i);
}
r.count=j;
return r;
}
roster_t get_roster()
{
return roster;
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
static void print_roster()
{
unsigned i;
printf("======== roster size: %lu\n", roster.count);
for (i=0; i<roster.count; ++i)
printf("roster(%02d): [%d]%s\n", i, GRADE(i), NAME(i));
printf("\n");
}
int main(int ac, char **av)
{
int arg=1;
uint8_t i;
for (; arg<ac-1; ++arg, ++arg) {
i=atoi(av[arg]);
add_student(av[arg+1], i);
}
print_roster();
}
#endif

View File

@@ -0,0 +1,36 @@
#ifndef GRADE_SCHOOL_H
#define GRADE_SCHOOL_H
#include <stddef.h>
#include <stdint.h>
#define MAX_STUDENTS 20
typedef struct student_s {
uint8_t grade;
const char *name;
} student_t;
typedef struct {
size_t count;
student_t students[MAX_STUDENTS];
} roster_t;
void clear_roster(void);
int add_student(const char *student, const uint8_t grade);
roster_t get_grade(const uint8_t grade);
roster_t get_roster(void);
/* 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

View File

@@ -1,14 +1,5 @@
#include "hamming.h"
/* Note: For explanation on section below, see 'GNUfilename' included in
* link below :
* https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7
*/
#if defined UNIT_TEST || defined DEBUG
#include <stdio.h>
#include <stdlib.h>
#endif
/* test does not include invalid input, but it should, as the subject is
* about DNA sequence, not ASCII chars sequence :-)
* exercism test needs only:
@@ -16,22 +7,25 @@
*/
#define V(p) (*(p)=='A' || *(p)=='C' || *(p)=='G' || *(p)=='T')
int compute(const char *lhs, const char *rhs)
int compute(const char *l, const char *r)
{
int res=0;
const char *l=lhs, *r=rhs;
if (!l || !r)
return -1;
for (; V(l) && V(r); ++l, ++r) {
for (; V(l) && V(r); ++l, ++r)
if (*l != *r)
res++;
}
return *r || *l? -1: res;
return *l || *r? -1: res;
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#if defined UNIT_TEST
#include <stdio.h>
#include <stdlib.h>
#ifdef UNIT_TEST
int main(int ac, char **av)
{
if (ac==3) {

View File

@@ -3,9 +3,8 @@
int compute(const char *lhs, const char *rhs);
/* Note: For explanation on section below, see 'GNUfilename' included in
* link below :
* https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef TESTALL
#undef TEST_IGNORE

51
c/leap/GNUmakefile Normal file
View 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

62
c/leap/README.md Normal file
View File

@@ -0,0 +1,62 @@
# Leap
Given a year, report if it is a leap year.
The tricky thing here is that a leap year in the Gregorian calendar occurs:
```text
on every year that is evenly divisible by 4
except every year that is evenly divisible by 100
unless the year is also evenly divisible by 400
```
For example, 1997 is not a leap year, but 1996 is. 1900 is not a leap
year, but 2000 is.
## Notes
Though our exercise adopts some very simple rules, there is more to
learn!
For a delightful, four minute explanation of the whole leap year
phenomenon, go watch [this youtube video][video].
[video]: http://www.youtube.com/watch?v=xX96xng7sAE
## 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
JavaRanch Cattle Drive, exercise 3 [http://www.javaranch.com/leap.jsp](http://www.javaranch.com/leap.jsp)
## 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/leap/makefile Normal file
View 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)

24
c/leap/src/leap.c Normal file
View File

@@ -0,0 +1,24 @@
#include "leap.h"
/* already dont in meetup exercise */
bool leap_year(int y)
{
return ((y % 4) ||
(y % 400 && !(y % 100)))? false: true;
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
int main(int ac, char **av)
{
int arg=1, i;
for (; arg<ac; ++arg) {
i=atoi(av[arg]);
printf("leap_year(%d)=%d\n", i, leap_year(i));
}
}
#endif

20
c/leap/src/leap.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef LEAP_H
#define LEAP_H
#include <stdbool.h>
bool leap_year(int year);
/* 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

56
c/linked-list/GNUmakefile Normal file
View File

@@ -0,0 +1,56 @@
# 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):
# 1) copy it into exercise directory
# 2) add ex.h to exercise include file
# 3) add ex.c to exercise source code, and create a suitable main function
# 4) use make with one of the following targets :
# all: compile and run all predefined tests.
# nowarn: compile with no -Werror, and run all predefined tests
# debug: compile with -DDEBUG and run all predefined tests
# mem: perform memcheck with all tests enabled
# unit: build standalone (unit) bimary
# unitnowarn: build standalone (unit) binary with -Werror disabled
# unitdebug: build standalone binary with -DDEBUG
#
# Original 'makefile' targets can be used (test, memcheck, clean, ...)
.PHONY: default all nowarn debug mem unit unitnowarn unitdebug standalone
default: all
ALLSOURCES:=$(wildcard ./*.c)
TESTSOURCES:=$(wildcard ./test_*.c)
SRC:=$(filter-out $(TESTSOURCES),$(ALLSOURCES))
include makefile
all: CFLAGS+=-DTESTALL
all: clean test
nowarn: CFLAGS:=$(filter-out -Werror,$(CFLAGS))
nowarn: clean all
debug: CFLAGS+=-DDEBUG
debug: all
mem: CFLAGS+=-DTESTALL
mem: clean memcheck
unitnowarn: CFLAGS:=$(filter-out -Werror,$(CFLAGS))
unitnowarn: clean unit
unitdebug: CFLAGS+=-DDEBUG
unitdebug: clean unit
unit: CFLAGS+=-DUNIT_TEST
unit: *.c *.h
$(CC) $(CFLAGS) $(SRC) -o tests.out $(LIBS)

63
c/linked-list/HELP.md Normal file
View File

@@ -0,0 +1,63 @@
# Help
## Running 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.
```console
$ 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.
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
## Submitting your solution
You can submit your solution using the `exercism submit linked_list.c linked_list.h` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [C track's documentation](https://exercism.org/docs/tracks/c)
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
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.
## Submitting Incomplete Solutions
If you are struggling with a particular exercise, it is possible to submit an incomplete solution so you can see how others have completed the exercise.
## Resources
To get help if having trouble, you can use the following resources:
- [StackOverflow][] can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.
- [CPPReference][] can be used to look up information on C concepts, operators, types, standard library functions and more.
- [TutorialsPoint][] has similar content as CPPReference in its C programming section.
- [The C Programming][K&R] book by K&R is the original source of the language and is still useful today.
[c-track]: https://exercism.io/my/tracks/c
[stackoverflow]: http://stackoverflow.com/questions/tagged/c
[cppreference]: https://en.cppreference.com/w/c
[tutorialspoint]: https://www.tutorialspoint.com/cprogramming/
[K&R]: https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628/

50
c/linked-list/README.md Normal file
View File

@@ -0,0 +1,50 @@
# Linked List
Welcome to Linked List on Exercism's C Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
Implement a doubly linked list.
Like an array, a linked list is a simple linear data structure. Several
common data types can be implemented using linked lists, like queues,
stacks, and associative arrays.
A linked list is a collection of data elements called *nodes*. In a
*singly linked list* each node holds a value and a link to the next node.
In a *doubly linked list* each node also holds a link to the previous
node.
You will write an implementation of a doubly linked list. Implement a
Node to hold a value and pointers to the next and previous nodes. Then
implement a List which holds references to the first and last node and
offers an array-like interface for adding and removing items:
* `push` (*insert value at back*);
* `pop` (*remove value at back*);
* `shift` (*remove value at front*).
* `unshift` (*insert value at front*);
To keep your implementation simple, the tests will not cover error
conditions. Specifically: `pop` or `shift` will never be called on an
empty list.
If you want to know more about linked lists, check [Wikipedia](https://en.wikipedia.org/wiki/Linked_list).
## Source
### Created by
- @wolf99
### Contributed to by
- @patricksjackson
- @QLaille
- @ryanplusplus
- @siebenschlaefer
### Based on
Classic computer science topic

45
c/linked-list/br-common.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef __BR_COMMON_H
#define __BR_COMMON_H
/* ${LINUX_SRC}/include/linux/compiler_attributes.h, around line 30
*
* __has_attribute is supported on gcc >= 5, clang >= 2.9 and icc >= 17.
* For other compilers, simple implementation (for __falltrough__ only)
*/
#ifndef __has_attribute
# define __has_attribute(x) __GCC4_has_attribute_##x
# define __GCC4_has_attribute___assume_aligned__ (__GNUC_MINOR__ >= 9)
# define __GCC4_has_attribute___copy__ 0
# define __GCC4_has_attribute___designated_init__ 0
# define __GCC4_has_attribute___externally_visible__ 1
# define __GCC4_has_attribute___no_caller_saved_registers__ 0
# define __GCC4_has_attribute___noclone__ 1
# define __GCC4_has_attribute___nonstring__ 0
# define __GCC4_has_attribute___no_sanitize_address__ (__GNUC_MINOR__ >= 8)
# define __GCC4_has_attribute___no_sanitize_undefined__ (__GNUC_MINOR__ >= 9)
# define __GCC4_has_attribute___fallthrough__ 0
# define __GCC4_has_attribute___fallthrough__ 0
#endif
/* ${LINUX_SRC}/include/linux/compiler_attributes.h, around line 200
*/
#if __has_attribute(__fallthrough__)
# define fallthrough __attribute__((__fallthrough__))
#else
# define fallthrough do {} while (0) /* fallthrough */
#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 /* __BR_COMMON_H */

138
c/linked-list/linked_list.c Normal file
View File

@@ -0,0 +1,138 @@
#include <malloc.h>
#include "list.h"
#include "linked_list.h"
/* How it works :
*
* The usual way to use linked lists is to have a list_head whith
* 'next' pointing to first node, and 'prev' pointing to last node.
* Each node has also 'prev' and 'next' pointers.
*
* Here, list_head points to the node own list_head structure,
* and each node list_head points to next/previous node list_head.
*
* Advantage: We don't need to manipulate the pointers, all lists
* use the same code, independently of the object (node) structure.
*/
struct list_node {
ll_data_t data;
struct list_head list;
};
/* duplicate of list_head struct
*/
struct list {
struct list_head *next, *prev;
};
/* constructs a new (empty) list
*/
struct list *list_create()
{
struct list_head *list;
if (!(list=malloc(sizeof (*list))))
return NULL;
INIT_LIST_HEAD(list);
return (struct list *) list;
}
/* counts the items on a list
*/
size_t list_count(const struct list *list_head)
{
size_t len = 0;
struct list_head *p;
list_for_each(p, (struct list_head *)list_head)
len++;
return len;
}
/* inserts item at back of a list
*/
void list_push(const struct list *list, const ll_data_t item_data)
{
struct list_node *p;
if ((p=malloc(sizeof(*p)))) {
p->data = item_data;
list_add_tail(&p->list, (struct list_head*)list);
}
}
/* deletes an element
*/
static ll_data_t _list_del(const struct list_head *list)
{
struct list_node *node;
ll_data_t data;
node = list_entry(list, struct list_node, list);
data = node->data;
list_del(&node->list);
free(node);
return data;
}
/* removes item from back of a list
*/
ll_data_t list_pop(const struct list *list)
{
return list_empty((struct list_head*)list) ? -1 : _list_del(list->prev);
}
/* inserts item at front of a list
*/
void list_unshift(const struct list *list, const ll_data_t item_data)
{
struct list_node *p;
if ((p=malloc(sizeof(*p)))) {
p->data = item_data;
list_add(&p->list, (struct list_head*)list);
}
}
/* removes item from front of a list
*/
ll_data_t list_shift(const struct list *list)
{
return list_empty((struct list_head*)list) ? -1 : _list_del(list->next);
}
/* finds a element that matches data
*/
static struct list_node *_node_find(const struct list *list, const ll_data_t data)
{
struct list_node *p;
list_for_each_entry(p, (struct list_head *)list, list) {
if (p->data == data)
return p;
}
return NULL;
}
/* deletes a node that holds the matching data
*/
void list_delete(const struct list *list, const ll_data_t data)
{
struct list_node *p;
if ((p = _node_find(list, data)))
_list_del(&p->list);
}
/* destroys an entire list
* list will be a dangling pointer after calling this method on it
*/
void list_destroy(struct list *list)
{
struct list_head *cur, *tmp;
list_for_each_safe(cur, tmp, (struct list_head *)list)
_list_del(cur);
free(list);
}

View File

@@ -0,0 +1,36 @@
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
#include <stddef.h>
typedef int ll_data_t;
struct list;
// constructs a new (empty) list
struct list *list_create(void);
// counts the items on a list
size_t list_count(const struct list *list);
// inserts item at back of a list
void list_push(const struct list *list, const ll_data_t item_data);
// removes item from back of a list
ll_data_t list_pop(const struct list *list);
// inserts item at front of a list
void list_unshift(const struct list *list, const ll_data_t item_data);
// removes item from front of a list
ll_data_t list_shift(const struct list *list);
// deletes a node that holds the matching data
void list_delete(const struct list *list, const ll_data_t data);
// destroys an entire list
// list will be a dangling pointer after calling this method on it
void list_destroy(struct list *list);
#endif
#include "br-common.h"

229
c/linked-list/list.h Normal file
View File

@@ -0,0 +1,229 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* stripped down version of my adaptation of Linux kernel lists management :
* https://github.com/braoult/Tools/blob/master/C/list.h
*/
#ifndef __LIST_H
#define __LIST_H
#include <stddef.h>
#include <stdbool.h>
/************ originally in <include/linux/types.h> */
struct list_head {
struct list_head *next, *prev;
};
/************ originally in <include/linux/poison.h> */
#define LIST_POISON1 ((void *) 0x100)
#define LIST_POISON2 ((void *) 0x122)
/************ originally in <include/linux/kernel.h> */
#define container_of(ptr, type, member) \
((type *)((char *)(ptr) - offsetof(type, member)))
/*
* Circular doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
/**
* INIT_LIST_HEAD - Initialize a list_head structure
* @list: list_head structure to be initialized.
*
* Initializes the list_head to point to itself. If it is a list header,
* the result is an empty list.
*/
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
static inline void __list_del_entry(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del_entry(entry);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_last_entry - get the last element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_last_entry(ptr, type, member) \
list_entry((ptr)->prev, type, member)
/**
* list_next_entry - get the next element in list
* @pos: the type * to cursor
* @member: the name of the list_head within the struct.
*/
#define list_next_entry(pos, member) \
list_entry((pos)->member.next, __typeof__(*(pos)), member)
/**
* list_prev_entry - get the prev element in list
* @pos: the type * to cursor
* @member: the name of the list_head within the struct.
*/
#define list_prev_entry(pos, member) \
list_entry((pos)->member.prev, __typeof__(*(pos)), member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_entry_is_head - test if the entry points to the head of the list
* @pos: the type * to cursor
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_entry_is_head(pos, head, member) \
(&pos->member == (head))
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_first_entry(head, __typeof__(*pos), member); \
!list_entry_is_head(pos, head, member); \
pos = list_next_entry(pos, member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_first_entry(head, __typeof__(*pos), member), \
n = list_next_entry(pos, member); \
!list_entry_is_head(pos, head, member); \
pos = n, n = list_next_entry(n, member))
#endif /* __LIST_H */

37
c/linked-list/makefile Normal file
View 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: ./*.c ./*.h
@echo Compiling $@
@$(CC) $(ASANFLAGS) $(CFLAGS) test-framework/unity.c ./*.c -o memcheck.out $(LIBS)
@./memcheck.out
@echo "Memory check passed"
.PHONY: clean
clean:
rm -rf *.o *.out *.out.dSYM
tests.out: ./*.c ./*.h
@echo Compiling $@
@$(CC) $(CFLAGS) test-framework/unity.c ./*.c -o tests.out $(LIBS)

View File

@@ -0,0 +1,243 @@
#include <stddef.h>
#include "test-framework/unity.h"
#include "linked_list.h"
struct list *list = NULL;
void setUp(void)
{
list = list_create();
}
void tearDown(void)
{
if (list) {
list_destroy(list);
list = NULL;
}
}
static void test_pop_gets_element_from_the_list(void)
{
list_push(list, 7);
TEST_ASSERT_EQUAL(7, list_pop(list));
}
static void test_push_pop_respectively_add_remove_at_the_end_of_the_list(void)
{
TEST_IGNORE(); // delete this line to run test
list_push(list, 11);
list_push(list, 13);
TEST_ASSERT_EQUAL(13, list_pop(list));
TEST_ASSERT_EQUAL(11, list_pop(list));
}
static void test_shift_gets_an_element_from_the_list(void)
{
TEST_IGNORE();
list_push(list, 17);
TEST_ASSERT_EQUAL(17, list_shift(list));
}
static void test_shift_gets_first_element_from_the_list(void)
{
TEST_IGNORE();
list_push(list, 23);
list_push(list, 5);
TEST_ASSERT_EQUAL(23, list_shift(list));
TEST_ASSERT_EQUAL(5, list_shift(list));
}
static void test_unshift_adds_element_at_start_of_the_list(void)
{
TEST_IGNORE();
list_unshift(list, 23);
list_unshift(list, 5);
TEST_ASSERT_EQUAL(5, list_shift(list));
TEST_ASSERT_EQUAL(23, list_shift(list));
}
static void test_pop_push_shift_and_unshift_can_be_used_in_any_order(void)
{
TEST_IGNORE();
list_push(list, 1);
list_push(list, 2);
TEST_ASSERT_EQUAL(2, list_pop(list));
list_push(list, 3);
TEST_ASSERT_EQUAL(1, list_shift(list));
list_unshift(list, 4);
list_push(list, 5);
TEST_ASSERT_EQUAL(4, list_shift(list));
TEST_ASSERT_EQUAL(5, list_pop(list));
TEST_ASSERT_EQUAL(3, list_shift(list));
}
static void test_count_an_empty_list(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL(0, list_count(list));
}
static void test_count_a_list_with_items(void)
{
TEST_IGNORE();
list_push(list, 37);
list_push(list, 1);
TEST_ASSERT_EQUAL(2, list_count(list));
}
static void test_count_is_correct_after_mutation(void)
{
TEST_IGNORE();
list_push(list, 31);
TEST_ASSERT_EQUAL(1, list_count(list));
list_unshift(list, 43);
TEST_ASSERT_EQUAL(2, list_count(list));
list_shift(list);
TEST_ASSERT_EQUAL(1, list_count(list));
list_pop(list);
TEST_ASSERT_EQUAL(0, list_count(list));
}
static void test_popping_to_empty_does_not_break_the_list(void)
{
TEST_IGNORE();
list_push(list, 41);
list_push(list, 59);
list_pop(list);
list_pop(list);
list_push(list, 47);
TEST_ASSERT_EQUAL(1, list_count(list));
TEST_ASSERT_EQUAL(47, list_pop(list));
}
static void test_shifting_to_empty_does_not_break_the_list(void)
{
TEST_IGNORE();
list_push(list, 41);
list_push(list, 59);
list_shift(list);
list_shift(list);
list_push(list, 47);
TEST_ASSERT_EQUAL(1, list_count(list));
TEST_ASSERT_EQUAL(47, list_shift(list));
}
static void test_deletes_the_only_element(void)
{
TEST_IGNORE();
list_push(list, 61);
list_delete(list, 61);
TEST_ASSERT_EQUAL(0, list_count(list));
}
static void
test_deletes_the_element_with_the_specified_value_from_the_list(void)
{
TEST_IGNORE();
list_push(list, 71);
list_push(list, 83);
list_push(list, 79);
list_delete(list, 83);
TEST_ASSERT_EQUAL(2, list_count(list));
TEST_ASSERT_EQUAL(79, list_pop(list));
TEST_ASSERT_EQUAL(71, list_shift(list));
}
static void
test_deletes_the_element_with_the_specified_value_from_the_list_reassigns_tail
(void) {
TEST_IGNORE();
list_push(list, 71);
list_push(list, 83);
list_push(list, 79);
list_delete(list, 83);
TEST_ASSERT_EQUAL(2, list_count(list));
TEST_ASSERT_EQUAL(79, list_pop(list));
TEST_ASSERT_EQUAL(71, list_pop(list));
}
static void
test_deletes_the_element_with_the_specified_value_from_the_list_reassigns_head
(void) {
TEST_IGNORE();
list_push(list, 71);
list_push(list, 83);
list_push(list, 79);
list_delete(list, 83);
TEST_ASSERT_EQUAL(2, list_count(list));
TEST_ASSERT_EQUAL(71, list_shift(list));
TEST_ASSERT_EQUAL(79, list_shift(list));
}
static void test_deletes_the_first_of_two_elements(void)
{
TEST_IGNORE();
list_push(list, 97);
list_push(list, 101);
list_delete(list, 97);
TEST_ASSERT_EQUAL(1, list_count(list));
TEST_ASSERT_EQUAL(101, list_pop(list));
}
static void test_deletes_the_second_of_two_elements(void)
{
TEST_IGNORE();
list_push(list, 97);
list_push(list, 101);
list_delete(list, 101);
TEST_ASSERT_EQUAL(1, list_count(list));
TEST_ASSERT_EQUAL(97, list_pop(list));
}
static void
test_delete_does_not_modify_the_list_if_the_element_is_not_found(void)
{
TEST_IGNORE();
list_push(list, 89);
list_delete(list, 103);
TEST_ASSERT_EQUAL(1, list_count(list));
}
static void test_deletes_only_the_first_occurrence(void)
{
TEST_IGNORE();
list_push(list, 73);
list_push(list, 9);
list_push(list, 9);
list_push(list, 107);
list_delete(list, 9);
TEST_ASSERT_EQUAL(3, list_count(list));
TEST_ASSERT_EQUAL(107, list_pop(list));
TEST_ASSERT_EQUAL(9, list_pop(list));
TEST_ASSERT_EQUAL(73, list_pop(list));
}
int main(void)
{
UnityBegin("test_linked_list.c");
RUN_TEST(test_pop_gets_element_from_the_list);
RUN_TEST(test_push_pop_respectively_add_remove_at_the_end_of_the_list);
RUN_TEST(test_shift_gets_an_element_from_the_list);
RUN_TEST(test_shift_gets_first_element_from_the_list);
RUN_TEST(test_unshift_adds_element_at_start_of_the_list);
RUN_TEST(test_pop_push_shift_and_unshift_can_be_used_in_any_order);
RUN_TEST(test_count_an_empty_list);
RUN_TEST(test_count_a_list_with_items);
RUN_TEST(test_count_is_correct_after_mutation);
RUN_TEST(test_popping_to_empty_does_not_break_the_list);
RUN_TEST(test_shifting_to_empty_does_not_break_the_list);
RUN_TEST(test_deletes_the_only_element);
RUN_TEST(test_deletes_the_element_with_the_specified_value_from_the_list);
RUN_TEST
(test_deletes_the_element_with_the_specified_value_from_the_list_reassigns_tail);
RUN_TEST
(test_deletes_the_element_with_the_specified_value_from_the_list_reassigns_head);
RUN_TEST(test_deletes_the_first_of_two_elements);
RUN_TEST(test_deletes_the_second_of_two_elements);
RUN_TEST(test_delete_does_not_modify_the_list_if_the_element_is_not_found);
RUN_TEST(test_deletes_only_the_first_occurrence);
return UnityEnd();
}

51
c/list-ops/GNUmakefile Normal file
View 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 tests.out $(LIBS)

54
c/list-ops/README.md Normal file
View File

@@ -0,0 +1,54 @@
# List Ops
Implement basic list operations.
In functional languages list operations like `length`, `map`, and
`reduce` are very common. Implement a series of basic list operations,
without using existing functions.
The precise number and names of the operations to be implemented will be
track dependent to avoid conflicts with existing names, but the general
operations you will implement include:
* `append` (*given two lists, add all items in the second list to the end of the first list*);
* `concatenate` (*given a series of lists, combine all items in all lists into one flattened list*);
* `filter` (*given a predicate and a list, return the list of all items for which `predicate(item)` is True*);
* `length` (*given a list, return the total number of items within it*);
* `map` (*given a function and a list, return the list of the results of applying `function(item)` on all items*);
* `foldl` (*given a function, a list, and initial accumulator, fold (reduce) each item into the accumulator from the left using `function(accumulator, item)`*);
* `foldr` (*given a function, a list, and an initial accumulator, fold (reduce) each item into the accumulator from the right using `function(item, accumulator)`*);
* `reverse` (*given a list, return a list with all the original items, but in reversed order*);
## 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.
## 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/list-ops/makefile Normal file
View 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)

136
c/list-ops/src/list_ops.c Normal file
View File

@@ -0,0 +1,136 @@
#include <malloc.h>
#include <string.h>
#include <stdint.h>
#include "list_ops.h"
list_t *new_list(size_t len, list_element_t elts[])
{
list_t *list;
if (len > MAX_LIST_LENGTH ||
!(list=malloc(sizeof(list_t) + len*sizeof(list_element_t))))
return NULL;
list->length = len;
if (elts)
memcpy(list->elements, elts, len * sizeof(list_element_t));
return list;
}
list_t *append_list(list_t *l1, list_t *l2)
{
list_t *l;
size_t len=l1->length+l2->length;
if (!(l=new_list(len, NULL)))
return NULL;
memcpy(l->elements, l1->elements, l1->length * sizeof(list_element_t));
memcpy(l->elements + l1->length, l2->elements,
l2->length * sizeof(list_element_t));
l->length=len;
return l;
}
list_t *filter_list(list_t * l, bool(*f) (list_element_t))
{
size_t p1, p2;
list_t *list=new_list(l->length, NULL);
if (list) {
for (p1=0, p2=0; p1 < l->length; ++p1) {
if (f(l->elements[p1]))
list->elements[p2++]=l->elements[p1];
}
}
list->length=p2;
return list;
}
/* I don't like this function return value, and more generally using size_t
* as list length.
*/
size_t length_list(list_t *l)
{
return l? l->length: INVALID_LENGTH;
}
list_t *map_list(list_t * l, list_element_t(*map) (list_element_t))
{
size_t i;
list_t *list=new_list(l->length, NULL);
if (list) {
for (i=0; i < l->length; ++i)
list->elements[i] = map(l->elements[i]);
}
return list;
}
list_element_t foldl_list(list_t * l, list_element_t init,
list_element_t(*f) (list_element_t, list_element_t))
{
size_t i;
for (i = 0; i < l->length; ++i)
init = f(l->elements[i], init);
return init;
}
list_element_t foldr_list(list_t * l, list_element_t init,
list_element_t(*f) (list_element_t, list_element_t))
{
ptrdiff_t i;
for (i = l->length-1; i >= 0; --i)
init = f(l->elements[i], init);
return init;
}
list_t *reverse_list(list_t * l)
{
size_t i;
list_t *list=new_list(l->length, NULL);
if (list) {
for (i=0; i < l->length; ++i)
list->elements[l->length-i-1] = l->elements[i];
}
return list;
}
void delete_list(list_t * l)
{
free(l);
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
static void print_list(list_t *l)
{
printf("list (%lu) = ", l->length);
for (size_t i=0; i<l->length; ++i)
printf("%d ", l->elements[i]);
printf("\n");
}
int main(int ac, char **av)
{
int arg=1, i;
list_t *l1=new_list(0, NULL);
list_t *l2, *l3;
for (; arg<ac; ++arg) {
i=atoi(av[arg]);
l2 = new_list(1, (list_element_t[]){ i });
l3 = append_list(l1, l2);
delete_list(l2);
delete_list(l1);
l1=l3;
}
print_list(l1);
delete_list(l1);
}
#endif

62
c/list-ops/src/list_ops.h Normal file
View File

@@ -0,0 +1,62 @@
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
#include <stdlib.h>
#include <stdbool.h>
typedef char list_element_t;
typedef struct {
size_t length;
list_element_t elements[];
} list_t;
#define MAX_LIST_LENGTH 1024
#define INVALID_LENGTH (size_t)-1
// constructs a new list
extern list_t *new_list(size_t length, list_element_t elements[]);
// append entries to a list and return the new list
extern list_t *append_list(list_t * list1, list_t * list2);
// filter list returning only values that satisfy the filter function
extern list_t *filter_list(list_t * list, bool(*filter) (list_element_t));
// returns the length of the list
extern size_t length_list(list_t * list);
// return a list of elements whose values equal the list value transformed by
// the mapping function
extern list_t *map_list(list_t * list, list_element_t(*map) (list_element_t));
// folds (reduces) the given list from the left with a function
extern list_element_t foldl_list(list_t * list, list_element_t initial,
list_element_t(*foldl) (list_element_t,
list_element_t));
// folds (reduces) the given list from the right with a function
extern list_element_t foldr_list(list_t * list, list_element_t initial,
list_element_t(*foldr) (list_element_t,
list_element_t));
// reverse the elements of the list
extern list_t *reverse_list(list_t * list);
// destroy the entire list
// list will be a dangling pointer after calling this method on it
extern void delete_list(list_t * list);
/* 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

View 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

View File

@@ -0,0 +1,59 @@
# Nucleotide Count
Each of us inherits from our biological parents a set of chemical instructions known as DNA that influence how our bodies are constructed. All known life depends on DNA!
> Note: You do not need to understand anything about nucleotides or DNA to complete this exercise.
DNA is a long chain of other chemicals and the most important are the four nucleotides, adenine, cytosine, guanine and thymine. A single DNA chain can contain billions of these four nucleotides and the order in which they occur is important!
We call the order of these nucleotides in a bit of DNA a "DNA sequence".
We represent a DNA sequence as an ordered collection of these four nucleotides and a common way to do that is with a string of characters such as "ATTACG" for a DNA sequence of 6 nucleotides.
'A' for adenine, 'C' for cytosine, 'G' for guanine, and 'T' for thymine.
Given a string representing a DNA sequence, count how many of each nucleotide is present.
If the string contains characters that aren't A, C, G, or T then it is invalid and you should signal an error.
For example:
```
"GATTACA" -> 'A': 3, 'C': 1, 'G': 1, 'T': 2
"INVALID" -> error
```
## 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
The Calculating DNA Nucleotides_problem at Rosalind [http://rosalind.info/problems/dna/](http://rosalind.info/problems/dna/)
## 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

View 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)

View File

@@ -0,0 +1,68 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "nucleotide_count.h"
typedef unsigned char uchar;
static int C[256] = {
['A']=1, ['C']=2, ['G']=3, ['T']=4
};
/* not in C99: we implement asprintf */
static char *asprintf(const char *fmt, ...)
{
int n = 0;
char *p = NULL;
va_list ap;
va_start(ap, fmt);
n = vsnprintf(p, 0, fmt, ap);
va_end(ap);
if (n < 0 || !(p=malloc(n+1)))
return NULL;
va_start(ap, fmt);
n = vsnprintf(p, n+1, fmt, ap);
va_end(ap);
if (n < 0) {
free(p);
return NULL;
}
return p;
}
char *count(const char *dna)
{
int res[4]={ 0 };
if (!dna)
return NULL; /* should it be "" ? */
for (const uchar *p=(uchar *)dna; *p; ++p) {
if (!C[*p])
return asprintf("");
res[C[*p]-1]++;
}
return asprintf("A:%d C:%d G:%d T:%d", res[0], res[1], res[2], res[3]);
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
int main(int ac, char **av)
{
int arg=1;
char *p;
//printf("%s: %s\n", asprintf("%d %d %d %d %s", (long)av-(long)av, ac, arg, 1000, "foobar"));
for (; arg<ac; ++arg) {
p=count(av[arg]);
printf("%s: [%s] len=%lu\n", av[arg], p, strlen(p));
}
}
#endif

View File

@@ -0,0 +1,18 @@
#ifndef _NUCLEOTIDE_COUNT_H
#define _NUCLEOTIDE_COUNT_H
char *count(const char *dna_strand);
/* 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

View File

@@ -0,0 +1,56 @@
# 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):
# 1) copy it into exercise directory
# 2) add ex.h to exercise include file
# 3) add ex.c to exercise source code, and create a suitable main function
# 4) use make with one of the following targets :
# all: compile and run all predefined tests.
# nowarn: compile with no -Werror, and run all predefined tests
# debug: compile with -DDEBUG and run all predefined tests
# mem: perform memcheck with all tests enabled
# unit: build standalone (unit) bimary
# unitnowarn: build standalone (unit) binary with -Werror disabled
# unitdebug: build standalone binary with -DDEBUG
#
# Original 'makefile' targets can be used (test, memcheck, clean, ...)
.PHONY: default all nowarn debug mem unit unitnowarn unitdebug standalone
default: all
ALLSOURCES:=$(wildcard ./*.c)
TESTSOURCES:=$(wildcard ./test_*.c)
SRC:=$(filter-out $(TESTSOURCES),$(ALLSOURCES))
include makefile
all: CFLAGS+=-DTESTALL
all: clean test
nowarn: CFLAGS:=$(filter-out -Werror,$(CFLAGS))
nowarn: clean all
debug: CFLAGS+=-DDEBUG
debug: all
mem: CFLAGS+=-DTESTALL
mem: clean memcheck
unitnowarn: CFLAGS:=$(filter-out -Werror,$(CFLAGS))
unitnowarn: clean unit
unitdebug: CFLAGS+=-DDEBUG
unitdebug: clean unit
unit: CFLAGS+=-DUNIT_TEST
unit: *.c *.h
$(CC) $(CFLAGS) $(SRC) -o tests.out $(LIBS)

63
c/phone-number/HELP.md Normal file
View File

@@ -0,0 +1,63 @@
# Help
## Running 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.
```console
$ 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.
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
## Submitting your solution
You can submit your solution using the `exercism submit phone_number.c phone_number.h` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [C track's documentation](https://exercism.org/docs/tracks/c)
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
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.
## Submitting Incomplete Solutions
If you are struggling with a particular exercise, it is possible to submit an incomplete solution so you can see how others have completed the exercise.
## Resources
To get help if having trouble, you can use the following resources:
- [StackOverflow][] can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.
- [CPPReference][] can be used to look up information on C concepts, operators, types, standard library functions and more.
- [TutorialsPoint][] has similar content as CPPReference in its C programming section.
- [The C Programming][K&R] book by K&R is the original source of the language and is still useful today.
[c-track]: https://exercism.io/my/tracks/c
[stackoverflow]: http://stackoverflow.com/questions/tagged/c
[cppreference]: https://en.cppreference.com/w/c
[tutorialspoint]: https://www.tutorialspoint.com/cprogramming/
[K&R]: https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628/

56
c/phone-number/README.md Normal file
View File

@@ -0,0 +1,56 @@
# Phone Number
Welcome to Phone Number on Exercism's C Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
Clean up user-entered phone numbers so that they can be sent SMS messages.
The **North American Numbering Plan (NANP)** is a telephone numbering system used by many countries in North America like the United States, Canada or Bermuda. All NANP-countries share the same international country code: `1`.
NANP numbers are ten-digit numbers consisting of a three-digit Numbering Plan Area code, commonly known as *area code*, followed by a seven-digit local number. The first three digits of the local number represent the *exchange code*, followed by the unique four-digit number which is the *subscriber number*.
The format is usually represented as
```text
(NXX)-NXX-XXXX
```
where `N` is any digit from 2 through 9 and `X` is any digit from 0 through 9.
Your task is to clean up differently formatted telephone numbers by removing punctuation and the country code (1) if present.
For example, the inputs
- `+1 (613)-995-0253`
- `613-995-0253`
- `1 613 995 0253`
- `613.995.0253`
should all produce the output
`6139950253`
**Note:** As this exercise only deals with telephone numbers used in NANP-countries, only 1 is considered a valid country code.
## Source
### Created by
- @RealBarrettBrown
### Contributed to by
- @bcc32
- @Gamecock
- @gea-migration
- @h-3-0
- @mikewalker
- @patricksjackson
- @QLaille
- @ryanplusplus
- @wolf99
### Based on
Event Manager by JumpstartLab - http://tutorials.jumpstartlab.com/projects/eventmanager.html

View File

@@ -0,0 +1,45 @@
#ifndef __BR_COMMON_H
#define __BR_COMMON_H
/* ${LINUX_SRC}/include/linux/compiler_attributes.h, around line 30
*
* __has_attribute is supported on gcc >= 5, clang >= 2.9 and icc >= 17.
* For other compilers, simple implementation (for __falltrough__ only)
*/
#ifndef __has_attribute
# define __has_attribute(x) __GCC4_has_attribute_##x
# define __GCC4_has_attribute___assume_aligned__ (__GNUC_MINOR__ >= 9)
# define __GCC4_has_attribute___copy__ 0
# define __GCC4_has_attribute___designated_init__ 0
# define __GCC4_has_attribute___externally_visible__ 1
# define __GCC4_has_attribute___no_caller_saved_registers__ 0
# define __GCC4_has_attribute___noclone__ 1
# define __GCC4_has_attribute___nonstring__ 0
# define __GCC4_has_attribute___no_sanitize_address__ (__GNUC_MINOR__ >= 8)
# define __GCC4_has_attribute___no_sanitize_undefined__ (__GNUC_MINOR__ >= 9)
# define __GCC4_has_attribute___fallthrough__ 0
# define __GCC4_has_attribute___fallthrough__ 0
#endif
/* ${LINUX_SRC}/include/linux/compiler_attributes.h, around line 200
*/
#if __has_attribute(__fallthrough__)
# define fallthrough __attribute__((__fallthrough__))
#else
# define fallthrough do {} while (0); /* fallthrough */
#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 /* __BR_COMMON_H */

51
c/phone-number/makefile Normal file
View File

@@ -0,0 +1,51 @@
### 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
# detect compiler.
REALCC=$(realpath $(shell which $(CC)))
CC_VERSION_TEXT=$(shell $(REALCC) --version 2>/dev/null | head -n 1)
# fix discrepancies in compilers warnings. Only gcc and clang for now.
ifneq ($(findstring clang,$(CC_VERSION_TEXT)),)
CFLAGS += -Wimplicit-fallthrough
else
ifneq ($(findstring gcc,$(CC_VERSION_TEXT)),)
CFLAGS := $(filter-out -Wimplicit-fallthrough%,$(CFLAGS))
CFLAGS += -Wimplicit-fallthrough=5
endif
endif
ASANFLAGS = -fsanitize=address
ASANFLAGS += -fno-common
ASANFLAGS += -fno-omit-frame-pointer
.PHONY: test
test: tests.out
@./tests.out
.PHONY: memcheck
memcheck: ./*.c ./*.h
@echo Compiling $@
$(CC) $(ASANFLAGS) $(CFLAGS) test-framework/unity.c ./*.c -o memcheck.out $(LIBS)
@./memcheck.out
@echo "Memory check passed"
.PHONY: clean
clean:
rm -rf *.o *.out *.out.dSYM
tests.out: ./*.c ./*.h
@echo Compiling $@
$(CC) $(CFLAGS) test-framework/unity.c ./*.c -o tests.out $(LIBS)

View File

@@ -0,0 +1,91 @@
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <stdint.h>
#include "phone_number.h"
#define LEN_NUM 10
#define LPAREN '('
/* this version is likely not very stable, due to poor scanf() capabilities
* I made it to offer an option to traditional strtok() or manual string
* parsing.
* Examples:
* (1 (222-333.4444
* 1)))))) 222))) ...---... 333 ...---... 4444
* are both valid here, when they surely should not :-)
*/
static char *scan="%m[+(0-9]%*[()-. ]%m[0-9]%*[)-. ]%m[0-9]%*[-. ]%m[0-9]";
char *phone_number_clean(const char *input)
{
char *sn[4];
uint64_t num[4];
uint64_t *p = &*num;
int nmatch;
char *res;
if (!(res = malloc(LEN_NUM+1)))
return NULL;
memset(res, '0', LEN_NUM);
*(res+LEN_NUM) = 0;
nmatch = sscanf(input, scan, &sn[0], &sn[1], &sn[2], &sn[3]);
for (int i=0; i<nmatch; ++i) {
*(p+i) = atol(*sn[i] == LPAREN? sn[i]+1: sn[i]);
free(sn[i]); /* due to scanf %m */
}
switch (nmatch) {
case 2:
/* maybe 2 could be valid, like 333 3334444 ?
*/
case 0:
return res;
case 1: /* full number */
if (*p > 10000000000) /* 1 000 000 0000 */
*p -= 10000000000;
if (*p > 9999999999 || /* 999 999 9999 */
*p < 2000000000) /* 200 000 0000 */
return res;
break;
case 4: /* country code */
if (*p != 1)
return res;
p++; /* go to area number */
fallthrough; /* only gcc>=7 & clang>=12 */
case 3: /* start with area number */
if (*p < 200 || *p > 999 ||
*(p+1) < 200 || *(p+1) > 999 ||
*(p+2) > 9999)
return res;
break;
}
/* we don't care if some num has random value here (initialized), snprintf
* will consume only what is needed to fill the number
*/
snprintf(res, LEN_NUM+1, "%ld%ld%ld", *p, *(p+1), *(p+2));
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)
{
int arg;
char *res;
for (arg=1; arg<ac; ++arg) {
res=phone_number_clean(av[arg]);
printf("orig = [%s]\n", av[arg]);
printf("\t-> [%s]\n", res);
free(res);
}
}
#endif

View File

@@ -0,0 +1,10 @@
#ifndef PHONE_NUMBER_H
#define PHONE_NUMBER_H
#define NUMBER_LENGTH 10
char *phone_number_clean(const char *input);
#endif
#include "br-common.h"

View File

@@ -0,0 +1,246 @@
#include "test-framework/unity.h"
#include "phone_number.h"
#include <stdlib.h>
static char *result = NULL;
void setUp(void)
{
}
void tearDown(void)
{
free(result);
result = NULL;
}
static void test_cleans_the_number(void)
{
const char input[] = "(223) 456-7890";
const char expected[] = "2234567890";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_cleans_numbers_with_dots(void)
{
TEST_IGNORE(); // delete this line to run test
const char input[] = "223.456.7890";
const char expected[] = "2234567890";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_cleans_numbers_with_multiple_spaces(void)
{
TEST_IGNORE();
const char input[] = "223 456 7890 ";
const char expected[] = "2234567890";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_invalid_when_9_digits(void)
{
TEST_IGNORE();
const char input[] = "123456789";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_invalid_when_11_digits_does_not_start_with_a_1(void)
{
TEST_IGNORE();
const char input[] = "22234567890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_valid_when_11_digits_and_starting_with_1(void)
{
TEST_IGNORE();
const char input[] = "12234567890";
const char expected[] = "2234567890";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void
test_valid_when_11_digits_and_starting_with_1_even_with_punctuation(void)
{
TEST_IGNORE();
const char input[] = "+1 (223) 456-7890";
const char expected[] = "2234567890";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_invalid_when_more_than_11_digits(void)
{
TEST_IGNORE();
const char input[] = "321234567890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_invalid_with_letters(void)
{
TEST_IGNORE();
const char input[] = "123-abc-7890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_invalid_with_punctuations(void)
{
TEST_IGNORE();
const char input[] = "123-@:!-7890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_invalid_if_area_code_starts_with_0(void)
{
TEST_IGNORE();
const char input[] = "(023) 456-7890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_invalid_if_area_code_starts_with_1(void)
{
TEST_IGNORE();
const char input[] = "(123) 456-7890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_invalid_if_exchange_code_starts_with_0(void)
{
TEST_IGNORE();
const char input[] = "(223) 056-7890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void test_invalid_if_exchange_code_starts_with_1(void)
{
TEST_IGNORE();
const char input[] = "(223) 156-7890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void
test_invalid_if_area_code_starts_with_0_on_valid_11_digit_number(void)
{
TEST_IGNORE();
const char input[] = "1 (023) 456-7890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void
test_invalid_if_area_code_starts_with_1_on_valid_11_digit_number(void)
{
TEST_IGNORE();
const char input[] = "1 (123) 456-7890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void
test_invalid_if_exchange_code_starts_with_0_on_valid_11_digit_number(void)
{
TEST_IGNORE();
const char input[] = "1 (223) 056-7890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
static void
test_invalid_if_exchange_code_starts_with_1_on_valid_11_digit_number(void)
{
TEST_IGNORE();
const char input[] = "1 (123) 156-7890";
const char expected[] = "0000000000";
result = phone_number_clean(input);
TEST_ASSERT_EQUAL_STRING(expected, result);
}
int main(void)
{
UnityBegin("test_phone_number.c");
RUN_TEST(test_cleans_the_number);
RUN_TEST(test_cleans_numbers_with_dots);
RUN_TEST(test_cleans_numbers_with_multiple_spaces);
RUN_TEST(test_invalid_when_9_digits);
RUN_TEST(test_invalid_when_11_digits_does_not_start_with_a_1);
RUN_TEST(test_valid_when_11_digits_and_starting_with_1);
RUN_TEST
(test_valid_when_11_digits_and_starting_with_1_even_with_punctuation);
RUN_TEST(test_invalid_when_more_than_11_digits);
RUN_TEST(test_invalid_with_letters);
RUN_TEST(test_invalid_with_punctuations);
RUN_TEST(test_invalid_if_area_code_starts_with_0);
RUN_TEST(test_invalid_if_area_code_starts_with_1);
RUN_TEST(test_invalid_if_exchange_code_starts_with_0);
RUN_TEST(test_invalid_if_exchange_code_starts_with_1);
RUN_TEST(test_invalid_if_area_code_starts_with_0_on_valid_11_digit_number);
RUN_TEST(test_invalid_if_area_code_starts_with_1_on_valid_11_digit_number);
RUN_TEST
(test_invalid_if_exchange_code_starts_with_0_on_valid_11_digit_number);
RUN_TEST
(test_invalid_if_exchange_code_starts_with_1_on_valid_11_digit_number);
return UnityEnd();
}

View 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 tests.out $(LIBS)

View File

@@ -0,0 +1,62 @@
# Pythagorean Triplet
A Pythagorean triplet is a set of three natural numbers, {a, b, c}, for
which,
```text
a**2 + b**2 = c**2
```
and such that,
```text
a < b < c
```
For example,
```text
3**2 + 4**2 = 9 + 16 = 25 = 5**2.
```
Given an input integer N, find all Pythagorean triplets for which `a + b + c = N`.
For example, with N = 1000, there is exactly one Pythagorean triplet for which `a + b + c = 1000`: `{200, 375, 425}`.
## 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
Problem 9 at Project Euler [http://projecteuler.net/problem=9](http://projecteuler.net/problem=9)
## 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

View 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)

View File

@@ -0,0 +1,89 @@
#include <malloc.h>
#include "pythagorean_triplet.h"
#define POOL_SIZE 10
/* V1: initial version
* V2: cormetic changes
* V3: add pool for realloc instead of single realloc
*/
void free_triplets(triplets_t *t)
{
free(t->triplets);
free(t);
}
static triplets_t *new_triplet()
{
triplets_t *t=malloc(sizeof(triplets_t));
if (t) {
t->count = 0;
t->pool = 0;
t->triplets = NULL;
}
return t;
}
static triplets_t *add_triplet(triplets_t *t, const uint16_t a, const uint16_t b,
const uint16_t c)
{
/* we may directly call add_triplet() without new_triplet. Not used here,
* but could be useful if triplets_with_sum() would return NULL when no
* solution found.
*/
if (! (t || (t = new_triplet())))
return NULL;
if (t->count == t->pool) {
t->pool += POOL_SIZE;
if (!(t->triplets = realloc(t->triplets, sizeof(triplets_t) +
t->pool * sizeof(triplet_t)))) {
free(t);
return NULL;
}
}
t->triplets[t->count] = (triplet_t) {a, b, c};
t->count++;
return t;
}
/* algorithm from : https://stackoverflow.com/a/2818750/3079831
*/
triplets_t *triplets_with_sum(uint16_t sum)
{
int a, b, c;
triplets_t *t;
if (!(t = new_triplet()))
return NULL;
if (sum%2)
return t;
for (a = 1; a <= sum/3; a++) {
for (b = a + 1; b <= sum/2; b++) {
c = sum - a - b;
if (a*a + b*b == c*c)
if (!(t = add_triplet(t, a, b, c)))
return NULL;
}
}
return t;
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
int main(int ac, char **av)
{
int arg=1;
resistor_band_t i[2];
for (; arg<ac-1; ++arg, ++arg) {
*i=atoi(av[arg]);
*(i+1)=atoi(av[arg+1]);
printf("color(%d, %d)=%d\n", i[0], i[1], color_code(i));
}
}
#endif

View File

@@ -0,0 +1,34 @@
#ifndef PYTHAGOREAN_TRIPLET
#define PYTHAGOREAN_TRIPLET
#include <stdlib.h>
#include <stdint.h>
typedef struct triplet {
uint16_t a;
uint16_t b;
uint16_t c;
} triplet_t;
typedef struct triplets {
size_t count;
size_t pool;
triplet_t *triplets;
} triplets_t;
triplets_t *triplets_with_sum(uint16_t sum);
void free_triplets(triplets_t *triplet);
/* 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

51
c/raindrops/GNUmakefile Normal file
View 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

54
c/raindrops/README.md Normal file
View File

@@ -0,0 +1,54 @@
# Raindrops
Your task is to convert a number into a string that contains raindrop sounds corresponding to certain potential factors. A factor is a number that evenly divides into another number, leaving no remainder. The simplest way to test if a one number is a factor of another is to use the [modulo operation](https://en.wikipedia.org/wiki/Modulo_operation).
The rules of `raindrops` are that if a given number:
- has 3 as a factor, add 'Pling' to the result.
- has 5 as a factor, add 'Plang' to the result.
- has 7 as a factor, add 'Plong' to the result.
- _does not_ have any of 3, 5, or 7 as a factor, the result should be the digits of the number.
## Examples
- 28 has 7 as a factor, but not 3 or 5, so the result would be "Plong".
- 30 has both 3 and 5 as factors, but not 7, so the result would be "PlingPlang".
- 34 is not factored by 3, 5, or 7, so the result would be "34".
## 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 FizzBuzz, a famous technical interview question that is intended to weed out potential candidates. That question is itself derived from Fizz Buzz, a popular children's game for teaching division. [https://en.wikipedia.org/wiki/Fizz_buzz](https://en.wikipedia.org/wiki/Fizz_buzz)
## 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/raindrops/makefile Normal file
View 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)

View File

@@ -0,0 +1,29 @@
#include "raindrops.h"
#include <stdio.h>
char *convert(char result[], int drops)
{
char *p=result;
if (!(drops%3)) p+=sprintf(p, "%s", "Pling");
if (!(drops%5)) p+=sprintf(p, "%s", "Plang");
if (!(drops%7)) p+=sprintf(p, "%s", "Plong");
if (p==result) sprintf(p, "%d", drops);
return result;
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
int main(int ac, char **av)
{
int arg=1, i;
char buffer[128];
for (; arg<ac; ++arg) {
i=atoi(av[arg]);
printf("raindrops(%d)=%s\n", i, convert(buffer, i));
}
}
#endif

View File

@@ -0,0 +1,18 @@
#ifndef RAINDROPS_H
#define RAINDROPS_H
char *convert(char result[], int drops);
/* 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

View 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 tests.out $(LIBS)

View File

@@ -0,0 +1,67 @@
# Rational Numbers
A rational number is defined as the quotient of two integers `a` and `b`, called the numerator and denominator, respectively, where `b != 0`.
The absolute value `|r|` of the rational number `r = a/b` is equal to `|a|/|b|`.
The sum of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ + r₂ = a₁/b₁ + a₂/b₂ = (a₁ * b₂ + a₂ * b₁) / (b₁ * b₂)`.
The difference of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ - r₂ = a₁/b₁ - a₂/b₂ = (a₁ * b₂ - a₂ * b₁) / (b₁ * b₂)`.
The product (multiplication) of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ * r₂ = (a₁ * a₂) / (b₁ * b₂)`.
Dividing a rational number `r₁ = a₁/b₁` by another `r₂ = a₂/b₂` is `r₁ / r₂ = (a₁ * b₂) / (a₂ * b₁)` if `a₂` is not zero.
Exponentiation of a rational number `r = a/b` to a non-negative integer power `n` is `r^n = (a^n)/(b^n)`.
Exponentiation of a rational number `r = a/b` to a negative integer power `n` is `r^n = (b^m)/(a^m)`, where `m = |n|`.
Exponentiation of a rational number `r = a/b` to a real (floating-point) number `x` is the quotient `(a^x)/(b^x)`, which is a real number.
Exponentiation of a real number `x` to a rational number `r = a/b` is `x^(a/b) = root(x^a, b)`, where `root(p, q)` is the `q`th root of `p`.
Implement the following operations:
- addition, subtraction, multiplication and division of two rational numbers,
- absolute value, exponentiation of a given rational number to an integer power, exponentiation of a given rational number to a real (floating-point) power, exponentiation of a real number to a rational number.
Your implementation of rational numbers should always be reduced to lowest terms. For example, `4/4` should reduce to `1/1`, `30/60` should reduce to `1/2`, `12/8` should reduce to `3/2`, etc. To reduce a rational number `r = a/b`, divide `a` and `b` by the greatest common divisor (gcd) of `a` and `b`. So, for example, `gcd(12, 8) = 4`, so `r = 12/8` can be reduced to `(12/4)/(8/4) = 3/2`.
Assume that the programming language you are using does not have an implementation of rational 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/Rational_number](https://en.wikipedia.org/wiki/Rational_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

View 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)

View File

@@ -0,0 +1,115 @@
#include "rational_numbers.h"
#include <stdlib.h>
#include <math.h>
#define N(r) ((r).numerator)
#define D(r) ((r).denominator)
/* Note. We should probably check for possible overflow in all
* functions below (not covered in exercise).
* To do this, a simple solution could be to make operations with
* long long (or some other method), and add a field in rational_t
* to express such overflow, division by zero, etc...
*/
/* Euclidean algorithm (by Donald Knuth) */
rational_t reduce(rational_t r)
{
int16_t a=abs(N(r)), b=abs(D(r)), t;
while (b != 0) {
t = b;
b = a % b;
a = t;
}
if (D(r) < 0)
a=-a;
return (rational_t) { N(r)/a, D(r)/a };
}
/* to avoid pow() for integers
* BUG: does not check for overflow
*/
static inline int power(int n, int p)
{
int res=n;
if (p==0)
return 1;
while (--p)
res*=n;
return res;
}
/* All formulas below come from https://en.wikipedia.org/wiki/Rational_number
*/
rational_t add(rational_t r1, rational_t r2)
{
return reduce((rational_t) {
N(r1) * D(r2) + N(r2) * D(r1),
D(r1) * D(r2)
});
}
rational_t subtract(rational_t r1, rational_t r2)
{
return reduce((rational_t) {
N(r1) * D(r2) - N(r2) * D(r1),
D(r1) * D(r2)
});
}
rational_t multiply(rational_t r1, rational_t r2)
{
return reduce((rational_t) {
N(r1) * N(r2),
D(r1) * D(r2)
});
}
rational_t divide(rational_t r1, rational_t r2)
{
return reduce((rational_t) {
N(r1) * D(r2),
D(r1) * N(r2)
});
}
rational_t absolute(rational_t r)
{
return (rational_t) {
abs(N(r)),
abs(D(r))
};
}
rational_t exp_rational(rational_t r, uint16_t n)
{
return reduce((rational_t) {
power(N(r), n),
power(D(r), n)
});
}
float exp_real(uint16_t x, rational_t r)
{
return powf((float)x, (float)N(r)/D(r));
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
int main(int ac, char **av)
{
int arg=1;
rational_t r1, r2;
for (; arg<ac-1; ++arg, ++arg) {
r1.numerator=atoi(av[arg]);;
r1.denominator=atoi(av[arg+1]);;
r2=reduce(r1);
printf("reduce(%d, %d)=(%d, %d)\n", N(r1), D(r1), N(r2), D(r2));
}
}
#endif

View File

@@ -0,0 +1,33 @@
#ifndef RATIONAL_NUMBERS
#define RATIONAL_NUMBERS
#include <stdint.h>
typedef struct {
int16_t numerator;
int16_t denominator;
} rational_t;
rational_t add(rational_t r1, rational_t r2);
rational_t subtract(rational_t r1, rational_t r2);
rational_t multiply(rational_t r1, rational_t r2);
rational_t divide(rational_t r1, rational_t r2);
rational_t absolute(rational_t r);
rational_t exp_rational(rational_t r, uint16_t n);
float exp_real(uint16_t x, rational_t r);
rational_t reduce(rational_t r);
/* 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

View File

@@ -4,10 +4,9 @@
#include <stdlib.h>
#endif
resistor_band_t color_code(resistor_band_t *colors)
resistor_band_t color_code(resistor_band_t colors[static 2])
{
resistor_band_t c1=*colors, c2=*(colors+1);
return c1>=BLACK && c1<=WHITE && c2>=BLACK && c2<=WHITE? c1*10+c2: ERROR;
}
@@ -20,7 +19,7 @@ int main(int ac, char **av)
for (; arg<ac-1; ++arg, ++arg) {
*i=atoi(av[arg]);
*(i+1)=atoi(av[arg+1]);
printf("color(%d, %d)=%d\n", i[0], i[1], color_code(i));
printf("color(%d, %d)=%d\n", *i, *(i+1), color_code(i));
}
}
#endif

View File

@@ -15,7 +15,7 @@ typedef enum {
ERROR=-1,
} resistor_band_t;
extern resistor_band_t color_code(resistor_band_t *);
extern resistor_band_t color_code(resistor_band_t [static 2]);
#ifdef TESTALL
#undef TEST_IGNORE

View 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

View File

@@ -0,0 +1,57 @@
# RNA Transcription
Given a DNA strand, return its RNA complement (per RNA transcription).
Both DNA and RNA strands are a sequence of nucleotides.
The four nucleotides found in DNA are adenine (**A**), cytosine (**C**),
guanine (**G**) and thymine (**T**).
The four nucleotides found in RNA are adenine (**A**), cytosine (**C**),
guanine (**G**) and uracil (**U**).
Given a DNA strand, its transcribed RNA strand is formed by replacing
each nucleotide with its complement:
* `G` -> `C`
* `C` -> `G`
* `T` -> `A`
* `A` -> `U`
## 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
Hyperphysics [http://hyperphysics.phy-astr.gsu.edu/hbase/Organic/transcription.html](http://hyperphysics.phy-astr.gsu.edu/hbase/Organic/transcription.html)
## 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

View 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)

View File

@@ -0,0 +1,37 @@
#include <malloc.h>
#include <string.h>
#include "rna_transcription.h"
static char C[256]={
['G']='C', ['C']='G', ['T']='A', ['A']='U',
};
char *to_rna(const char *dna)
{
char *rna=malloc(strlen(dna+1)), *p;
if (rna) {
for (p=rna; *dna; p++, dna++) {
if (!(*p=C[(int)*dna])) {
free(rna);
return NULL;
}
}
*p=0;
}
return rna;
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
int main(int ac, char **av)
{
int arg=1;
for (; arg<ac; ++arg) {
printf("rna(%s)=%s\n", av[arg], to_rna(av[arg]));
}
}
#endif

View File

@@ -0,0 +1,18 @@
#ifndef RNA_TRANSCRIPTION_H
#define RNA_TRANSCRIPTION_H
char *to_rna(const char *dna);
/* 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

View 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

View File

@@ -0,0 +1,81 @@
# Roman Numerals
Write a function to convert from normal numbers to Roman Numerals.
The Romans were a clever bunch. They conquered most of Europe and ruled
it for hundreds of years. They invented concrete and straight roads and
even bikinis. One thing they never discovered though was the number
zero. This made writing and dating extensive histories of their exploits
slightly more challenging, but the system of numbers they came up with
is still in use today. For example the BBC uses Roman numerals to date
their programmes.
The Romans wrote numbers using letters - I, V, X, L, C, D, M. (notice
these letters have lots of straight lines and are hence easy to hack
into stone tablets).
```text
1 => I
10 => X
7 => VII
```
There is no need to be able to convert numbers larger than about 3000.
(The Romans themselves didn't tend to go any higher)
Wikipedia says: Modern Roman numerals ... are written by expressing each
digit separately starting with the left most digit and skipping any
digit with a value of zero.
To see this in practice, consider the example of 1990.
In Roman numerals 1990 is MCMXC:
1000=M
900=CM
90=XC
2008 is written as MMVIII:
2000=MM
8=VIII
See also: http://www.novaroma.org/via_romana/numbers.html
## 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
The Roman Numeral Kata [http://codingdojo.org/cgi-bin/index.pl?KataRomanNumerals](http://codingdojo.org/cgi-bin/index.pl?KataRomanNumerals)
## 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/roman-numerals/makefile Normal file
View 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)

View File

@@ -0,0 +1,73 @@
#include "roman_numerals.h"
#include <stdio.h>
#include <string.h>
#include <malloc.h>
static struct conv_s {
unsigned char r;
unsigned d;
} conv[] = {
{ 'M', 1000 },
{ 'D', 500 },
{ 'C', 100 },
{ 'L', 50 },
{ 'X', 10 },
{ 'V', 5 },
{ 'I', 1 }
};
/* rules could differ (like IIII/VIIII instead of IV/IX), so it is better not
* to harcode values like 4, 9, 40, 90 etc...
* Example: the Colosseum gate 44 was written XLIIII, and not XLIV.
* we can therefore add a parameter in function below, and add a rule in
* the code to easily return a different notation.
*/
char *to_roman_numeral(unsigned int n /*, int notation */ )
{
unsigned cur=0, mult, pos=0, i;
char res[64]={0}, *to;
/* max number = 3999 = MMMCMXCIX */
if (n >= 4000) /* could be different if we */
return NULL; /* accept the 5000 sign */
while (n) {
/* we could : switch (notation) {
* case ROMAN_RULE:
*/
if ((mult=n/conv[cur].d)) { /* >= current multiplier */
if (mult%5==4) { /* 4 & 9 */
res[pos++]=conv[cur].r;
res[pos++]=conv[cur-mult/4].r; /* 4/4=1, 9/4=2 */
} else { /* 1-3 & 5-8 */
if (mult >= 5)
res[pos++]=conv[cur-1].r;
for (i=mult%5; i>0; --i)
res[pos++]=conv[cur].r;
}
n-=mult*conv[cur].d;
}
cur+=2;
}
if ((to=malloc(pos+1)))
memcpy(to, res, pos+1);
return to;
}
/* See GNUmakefile below for explanation
* https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile
*/
#ifdef UNIT_TEST
#include <stdlib.h>
int main(int ac, char **av)
{
int arg=1;
unsigned i;
for (; arg<ac; ++arg) {
i=atoi(av[arg]);
printf("roman(%d)=%s\n", i, to_roman_numeral(i));
}
}
#endif

View File

@@ -0,0 +1,20 @@
#ifndef ROMAN_NUMERALS_H
#define ROMAN_NUMERALS_H
#define ROMAN_RULE 0
char *to_roman_numeral(unsigned int number);
/* 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

View File

@@ -0,0 +1,56 @@
# 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):
# 1) copy it into exercise directory
# 2) add ex.h to exercise include file
# 3) add ex.c to exercise source code, and create a suitable main function
# 4) use make with one of the following targets :
# all: compile and run all predefined tests.
# nowarn: compile with no -Werror, and run all predefined tests
# debug: compile with -DDEBUG and run all predefined tests
# mem: perform memcheck with all tests enabled
# unit: build standalone (unit) bimary
# unitnowarn: build standalone (unit) binary with -Werror disabled
# unitdebug: build standalone binary with -DDEBUG
#
# Original 'makefile' targets can be used (test, memcheck, clean, ...)
.PHONY: default all nowarn debug mem unit unitnowarn unitdebug standalone
default: all
ALLSOURCES:=$(wildcard ./*.c)
TESTSOURCES:=$(wildcard ./test_*.c)
SRC:=$(filter-out $(TESTSOURCES),$(ALLSOURCES))
include makefile
all: CFLAGS+=-DTESTALL
all: clean test
nowarn: CFLAGS:=$(filter-out -Werror,$(CFLAGS))
nowarn: clean all
debug: CFLAGS+=-DDEBUG
debug: all
mem: CFLAGS+=-DTESTALL
mem: clean memcheck
unitnowarn: CFLAGS:=$(filter-out -Werror,$(CFLAGS))
unitnowarn: clean unit
unitdebug: CFLAGS+=-DDEBUG
unitdebug: clean unit
unit: CFLAGS+=-DUNIT_TEST
unit: *.c *.h
$(CC) $(CFLAGS) $(SRC) -o tests.out $(LIBS)

View File

@@ -0,0 +1,63 @@
# Help
## Running 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.
```console
$ 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.
[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
## Submitting your solution
You can submit your solution using the `exercism submit run_length_encoding.c run_length_encoding.h` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [C track's documentation](https://exercism.org/docs/tracks/c)
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
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.
## Submitting Incomplete Solutions
If you are struggling with a particular exercise, it is possible to submit an incomplete solution so you can see how others have completed the exercise.
## Resources
To get help if having trouble, you can use the following resources:
- [StackOverflow][] can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.
- [CPPReference][] can be used to look up information on C concepts, operators, types, standard library functions and more.
- [TutorialsPoint][] has similar content as CPPReference in its C programming section.
- [The C Programming][K&R] book by K&R is the original source of the language and is still useful today.
[c-track]: https://exercism.io/my/tracks/c
[stackoverflow]: http://stackoverflow.com/questions/tagged/c
[cppreference]: https://en.cppreference.com/w/c
[tutorialspoint]: https://www.tutorialspoint.com/cprogramming/
[K&R]: https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628/

Some files were not shown because too many files have changed in this diff Show More