aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbigail <abigail@abigail.be>2021-02-10 19:18:58 +0100
committerAbigail <abigail@abigail.be>2021-02-10 19:20:37 +0100
commitdeda23c261ee75dab3b3713ad21e7e4aa4205a3e (patch)
treea96cfba4a23028392e1e263f7f8c0c99b39ef12e
parent7104bcff280dafd9dce7551e2ed7d7468b943003 (diff)
downloadperlweeklychallenge-club-deda23c261ee75dab3b3713ad21e7e4aa4205a3e.tar.gz
perlweeklychallenge-club-deda23c261ee75dab3b3713ad21e7e4aa4205a3e.tar.bz2
perlweeklychallenge-club-deda23c261ee75dab3b3713ad21e7e4aa4205a3e.zip
C solution for week 99, part 2
-rw-r--r--challenge-099/abigail/README.md1
-rw-r--r--challenge-099/abigail/c/ch-2.c93
2 files changed, 94 insertions, 0 deletions
diff --git a/challenge-099/abigail/README.md b/challenge-099/abigail/README.md
index 2cf96b11c4..3e98f336de 100644
--- a/challenge-099/abigail/README.md
+++ b/challenge-099/abigail/README.md
@@ -81,6 +81,7 @@ Output: 3
### Solutions
* [AWK](awk/ch-2.awk)
+* [C](c/ch-2.c)
* Perl
* [Using regular expressions](perl/ch-2.pl)
* [Recursive counting](perl/ch-2a.pl)
diff --git a/challenge-099/abigail/c/ch-2.c b/challenge-099/abigail/c/ch-2.c
new file mode 100644
index 0000000000..9553f698ba
--- /dev/null
+++ b/challenge-099/abigail/c/ch-2.c
@@ -0,0 +1,93 @@
+# include <stdlib.h>
+# include <stdio.h>
+# include <string.h>
+
+/*
+ * See ../README.md
+ */
+
+/*
+ * Run as: cc -o ch-2.o ch-2.c; ./ch-2.o < input-file
+ */
+
+
+/*
+ * Helper method to allocate memory for a string.
+ */
+char * malloc_char (size_t size) {
+ char * string = (char *) malloc (size * sizeof (char));
+ if (string == NULL) {
+ perror (NULL);
+ exit (1);
+ }
+ return (string);
+}
+
+/*
+ * Recursively count matches:
+ * - If either the string or the pattern is empty, there are no matches.
+ * - Else, + count the matches if we don't match at the first character
+ * if the string.
+ * + if the first character of the string equals the first
+ * character of the pattern:
+ * o add 1 if the pattern is just one character long
+ * o else, add the number of matches starting from the
+ * then next character in the string, and the next
+ * character in the pattern.
+ */
+int matches (char * string, size_t string_len,
+ char * pattern, size_t pattern_len) {
+ if (string_len == 0 || pattern_len == 0) {
+ return 0;
+ }
+
+ /*
+ * Don't match at the beginning
+ */
+ int count = matches (string + 1, string_len - 1,
+ pattern, pattern_len);
+ if (string [0] == pattern [0]) {
+ if (pattern_len == 1) {
+ count ++;
+ }
+ else {
+ count += matches (string + 1, string_len - 1,
+ pattern + 1, pattern_len - 1);
+ }
+ }
+ return count;
+}
+
+
+/*
+ * Read input from standard input, assuming one exercise per line.
+ * Each line consists of a string $S, and a pattern $T, separated
+ * by whitespace.
+ */
+int main (void) {
+ char * line = NULL;
+ size_t len = 0;
+ size_t str_len;
+
+ while ((str_len = getline (&line, &len, stdin)) != -1) {
+ char * string;
+ char * pattern;
+
+ string = malloc_char (str_len);
+ pattern = malloc_char (str_len);
+
+ if (sscanf (line, "%s %s", string, pattern) != 2) {
+ fprintf (stderr, "Could not parse input\n");
+ exit (1);
+ }
+
+ printf ("%d\n", matches (string, strnlen (string, str_len),
+ pattern, strnlen (pattern, str_len)));
+
+ free (pattern);
+ free (string);
+ }
+ free (line);
+
+ return (0);
+}