diff --git a/Makefile b/Makefile index ac17fcf..5a18895 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,13 @@ TWOS_COMPLEMENT = -fno-strict-overflow -fwrapv LM = -lm LGMP = -lgmp +LEULER = -leuler $(LM) + +RECURSE = $(foreach d,$(wildcard $(1:=/*)),$(call RECURSE,$d,$2) $(filter $(subst *,%,$2),$d)) +LEETCODE = $(wildcard src/lc*.c) + all: \ + libeuler$(A) libleetcode$(A) \ id0001$(E) id0002$(E) id0003$(E) id0004$(E) id0005$(E) id0006$(E) \ id0007$(E) id0008$(E) id0009$(E) id0010$(E) id0011$(E) id0012$(E) \ id0013$(E) id0014$(E) id0015$(E) id0016$(E) id0017$(E) id0018$(E) \ @@ -28,231 +34,234 @@ all: \ id0068$(E) id0069$(E) id0070$(E) id0071$(E) id0072$(E) id0073$(E) \ id0074$(E) #id0075$(E) id0076$(E) id0077$(E) id0078$(E) id0079$(E) -libeuler$(A): - $(CC) $(CFLAGS) -c lib/**/*.c +libeuler$(A): $(call RECURSE,lib,*.c) + $(CC) $(CFLAGS) -c $(call RECURSE,lib,*.c) ar -r $@ *$(O) +libleetcode$(A): $(LEETCODE) + $(CC) $(CFLAGS) -c $(LEETCODE) + id0001$(E): src/id0001.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0002$(E): src/id0002.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0003$(E): src/id0003.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0004$(E): src/id0004.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0005$(E): src/id0005.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0006$(E): src/id0006.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0007$(E): src/id0007.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0008$(E): src/id0008.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0009$(E): src/id0009.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0010$(E): src/id0010.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0011$(E): src/id0011.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0012$(E): src/id0012.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0013$(E): src/id0013.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0014$(E): src/id0014.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0015$(E): src/id0015.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0016$(E): src/id0016.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LGMP) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) $(LGMP) id0017$(E): src/id0017.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0018$(E): src/id0018.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0019$(E): src/id0019.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0020$(E): src/id0020.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LGMP) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) $(LGMP) id0021$(E): src/id0021.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0022$(E): src/id0022.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0023$(E): src/id0023.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0024$(E): src/id0024.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0025$(E): src/id0025.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LGMP) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) $(LGMP) id0026$(E): src/id0026.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0027$(E): src/id0027.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0028$(E): src/id0028.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0029$(E): src/id0029.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0030$(E): src/id0030.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0031$(E): src/id0031.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0032$(E): src/id0032.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0033$(E): src/id0033.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0034$(E): src/id0034.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0035$(E): src/id0035.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0036$(E): src/id0036.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0037$(E): src/id0037.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0038$(E): src/id0038.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0039$(E): src/id0039.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0040$(E): src/id0040.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0041$(E): src/id0041.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0042$(E): src/id0042.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0043$(E): src/id0043.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0044$(E): src/id0044.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0045$(E): src/id0045.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0046$(E): src/id0046.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0047$(E): src/id0047.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0048$(E): src/id0048.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LGMP) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) $(LGMP) id0049$(E): src/id0049.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0050$(E): src/id0050.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0051$(E): src/id0051.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0052$(E): src/id0052.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0053$(E): src/id0053.c libeuler$(A) - $(CC) $(CFLAGS) $(TWOS_COMPLEMENT) $< -o $@ -leuler + $(CC) $(CFLAGS) $(TWOS_COMPLEMENT) $< -o $@ $(LEULER) id0054$(E): src/id0054.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0055$(E): src/id0055.c libeuler$(A) - $(CC) $(CFLAGS) $(TWOS_COMPLEMENT) $< -o $@ -leuler + $(CC) $(CFLAGS) $(TWOS_COMPLEMENT) $< -o $@ $(LEULER) id0056$(E): src/id0056.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LGMP) $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) $(LGMP) id0057$(E): src/id0057.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LGMP) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) $(LGMP) id0058$(E): src/id0058.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0059$(E): src/id0059.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0060$(E): src/id0060.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0061$(E): src/id0061.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0062$(E): src/id0062.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0063$(E): src/id0063.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0064$(E): src/id0064.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0065$(E): src/id0065.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LGMP) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) $(LGMP) id0066$(E): src/id0066.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LGMP) $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) $(LGMP) id0068$(E): src/id0068.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0069$(E): src/id0069.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0070$(E): src/id0070.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0071$(E): src/id0071.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0072$(E): src/id0072.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0073$(E): src/id0073.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0074$(E): src/id0074.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler + $(CC) $(CFLAGS) $< -o $@ $(LEULER) id0075$(E): src/id0075.c libeuler$(A) - $(CC) $(CFLAGS) $< -o $@ -leuler $(LM) + $(CC) $(CFLAGS) $< -o $@ $(LEULER) clean: $(RM) *$(A) *$(O) diff --git a/README.md b/README.md index 1e07a7e..1cc3816 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ Efficient Project Euler solutions in C language Thanks to the depth and breadth of the Project Euler problem set, this repository has become home to a [diverse library](lib/) including mathematical -functions as well as data structures and algorithms. +functions as well as data structures and algorithms. Some of these solutions can +also be used to solve [LeetCode](#leetcode) problems as well. ## Constraints @@ -129,3 +130,26 @@ which is licensed under the GNU Lesser General Public License v3.0 (`LGPL-3.0`). | 73 | [Counting Fractions in a Range](src/id0073.c) | Sequences | Count | | | 74 | [Digit Factorial Chains](src/id0074.c) | Combinatorics | Count | | | 75 | [Singular Integer Right Triangles](src/id0075.c) | Geometry | Count | | + +# LeetCode + +## Summary + +| Id | Problem | Domain | Result | Implementation | +| :--: | :----------------------------------------------------------------------: | :-----------: | :------------------: | --------------------- | +| 7 | [Reverse Integer](src/lc0007.c) | Mathematics | Integer | `math_reverse` | +| 8 | [String to Integer](src/lc0008.c) | Strings | Integer | `atoll` | +| 9 | [Palindrome Number](src/lc0009.c) | Mathematics | Boolean | `math_is_palindrome` | +| 28 | [Find the Index of the First Occurrence in a String](src/lc0028.c) | Strings | Index | `strstr` | +| 29 | [Divide Two Integers](src/lc0029.c) | Mathematics | Quotient | | +| 31 | [Next Permutation](src/lc0031.c) | Array | Permutation | `PermutationIterator` | +| 46 | [Permutations](src/lc0046.c) | Array | Permutation | `PermutationIterator` | +| 50 | [Pow(x, n)](src/lc0050.c) | Mathematics | Power | `pow` | +| 60 | [Permutation Sequence](src/lc0060.c) | Mathematics | Permutation | `PermutationIterator` | +| 62 | [Unique Paths](src/lc0062.c) | Combinatorics | Binomial coefficient | `binomial` | +| 69 | [Sqrt(x)](src/lc0069.c) | Mathematics | Square root | `sqrt` | +| 75 | [Sort Colors](src/lc0075.c) | Sorting | Sort | `qsort` | +| 367 | [Valid Perfect Square](src/lc0367.c) | Mathematics | Boolean | `is_polygonal` | +| 2119 | [A Number After a Double Reversal](src/lc2119.c) | Mathematics | Boolean | `math_reverse` | +| 2400 | [Number of Ways to Reach a Position After Exactly k Steps](src/lc2400.c) | Combinatorics | Binomial coefficient | `binomial` | +| 2550 | [Monkey Move](src/lc2550.c) | Combinatorics | Power | `mod_pow` | diff --git a/lib/_/dummy.h b/lib/_/dummy.h deleted file mode 100644 index 384c168..0000000 --- a/lib/_/dummy.h +++ /dev/null @@ -1 +0,0 @@ -// Licensed under the MIT License. diff --git a/lib/binomial.c b/lib/binomial.c index 8d57d33..1895bf7 100644 --- a/lib/binomial.c +++ b/lib/binomial.c @@ -1,5 +1,7 @@ // Licensed under the MIT License. +#include +#include #include "binomial.h" long long binomial(int n, int k) @@ -18,3 +20,25 @@ long long binomial(int n, int k) return result; } + +long long* binomial_mod_range(int n, long long mod) +{ + if (!mod) + { + mod = 1000000007l; + } + + long long* result = calloc(n + 1, sizeof * result); + + result[0] = 1; + + for (int i = 1; i <= n; i++) + { + for (int j = n; j > 0; j--) + { + result[j] = ((result[j] % mod) + (result[j - 1] % mod)) % mod; + } + } + + return result; +} diff --git a/lib/binomial.h b/lib/binomial.h index fbd7967..b8688bd 100644 --- a/lib/binomial.h +++ b/lib/binomial.h @@ -9,3 +9,14 @@ * from an `n`-element set. */ long long binomial(int n, int k); + +/** + * Generates values of the binomial coefficient `n` "choose" `k` mod `mod` for + * all `k` in the interval [0, `n`]. + * + * @param n the cardinality of the superset. + * @param mod the modulus, or `0` for the default modulus. + * @return A (`n` + 1)-element array, or `NULL` if the process is out of + * memory. The caller is responsible. +*/ +long long* binomial_mod_range(int n, long long mod); diff --git a/lib/comparer.h b/lib/comparer.h index e9722fb..7f428f3 100644 --- a/lib/comparer.h +++ b/lib/comparer.h @@ -3,7 +3,6 @@ #ifndef COMPARER_05e673bfc1d2477a8b652e51bb55e547 #define COMPARER_05e673bfc1d2477a8b652e51bb55e547 #include -#include "object.h" /** Defines a method that a type implements to compare two objects. */ typedef int (*Comparer)(const void* left, const void* right); diff --git a/lib/euclidean.c b/lib/euclidean.c index 3e6e74e..70a78f1 100644 --- a/lib/euclidean.c +++ b/lib/euclidean.c @@ -1,5 +1,7 @@ // Licensed under the MIT License. +#include "euclidean.h" + long gcd(long a, long b) { while (b > 0) @@ -12,3 +14,8 @@ long gcd(long a, long b) return a; } + +long lcm(long a, long b) +{ + return (a / gcd(a, b)) * b; +} diff --git a/lib/euclidean.h b/lib/euclidean.h index d4dec8c..8ee9eda 100644 --- a/lib/euclidean.h +++ b/lib/euclidean.h @@ -8,3 +8,12 @@ * @return The greatest common divisor of `a` and `b`. */ long gcd(long a, long b); + +/** + * Computes the least common multiple using Euclid's algorithm. + * + * @param a a natural number. + * @param b a natural number. + * @return The least common multiple of `a` and `b`. +*/ +long lcm(long a, long b); diff --git a/lib/euler.h b/lib/euler.h index 03589fb..f2faf3d 100644 --- a/lib/euler.h +++ b/lib/euler.h @@ -1,5 +1,7 @@ // Licensed under the MIT License. +#ifndef EULER_2363b2bd9868485c9651b89fbe7082ba +#define EULER_2363b2bd9868485c9651b89fbe7082ba #include #include #include @@ -27,6 +29,40 @@ */ Exception euler_submit(int id, long long result, clock_t start); +/** Represents text as a zero-terminated sequence of characters. */ +typedef char* String; + +/** + * Initializes a new `String` instance with the given length. + * + * @param length the string length. + * @return A new string with the given length, or `NULL` if the process is out + * of memory. The caller is responsible. +*/ +String string(size_t length); + +/** + * Creates a new instance of `String` with the same value as a specified + * `String`. + * + * @param instance the `String` instance to copy. + * @return A new string with the same value, or `NULL` if the process is out of + * memory. The caller is responsible. + */ +String string_clone(String instance); + +/** + * Compares `left` with `right` and returns an integer that indicates whether + * `left` precedes, follows, or appears in the same position in the sort order + * as `right`. + * + * @param left a string to compare to `right`. + * @param right a string to compare to `left`. + * @return A signed integer that indicates the relative values of `left` and + * `right`. +*/ +int string_comparer(const void* left, const void* right); + /** * Computes a partial summation of the natural numbers. This is equivalent to * computing the `n`-th triangular number. @@ -84,3 +120,5 @@ bool math_is_palindrome(long long n); * @return `true` if `x` is a `s`-gonal number; otherwise, `false`. */ bool math_is_polygonal(int s, long x, long* approxN); + +#endif diff --git a/lib/exception.h b/lib/exception.h index 6f4dfe4..ecbbdb3 100644 --- a/lib/exception.h +++ b/lib/exception.h @@ -9,7 +9,7 @@ enum Exception /** There is not enough memory to continue the program. */ EXCEPTION_OUT_OF_MEMORY = -1, - /** */ + /** A composite format string is not well formed. */ EXCEPTION_FORMAT = -2 }; diff --git a/lib/factorial.c b/lib/factorial.c index 9b2a474..a0fd1c8 100644 --- a/lib/factorial.c +++ b/lib/factorial.c @@ -1,6 +1,6 @@ // Licensed under the MIT License. -#include +#include #include "factorial.h" long long* factorial_range(int max) diff --git a/lib/permutation_iterator.c b/lib/permutation_iterator.c index 09b622f..4947011 100644 --- a/lib/permutation_iterator.c +++ b/lib/permutation_iterator.c @@ -7,8 +7,8 @@ void permutation_begin( PermutationIterator iterator, Array items, - size_t itemSize, size_t length, + size_t itemSize, Comparer itemComparer) { iterator->items = items; diff --git a/lib/permutation_iterator.h b/lib/permutation_iterator.h index 612a789..4124967 100644 --- a/lib/permutation_iterator.h +++ b/lib/permutation_iterator.h @@ -12,8 +12,8 @@ struct PermutationIterator int (*itemComparer)(const void* left, const void* right); void* items; - size_t itemSize; size_t length; + size_t itemSize; bool end; }; @@ -30,8 +30,8 @@ typedef struct PermutationIterator* PermutationIterator; void permutation_begin( PermutationIterator iterator, Array items, - size_t itemSize, size_t length, + size_t itemSize, Comparer itemComparer); /** diff --git a/lib/pow.c b/lib/pow.c new file mode 100644 index 0000000..d026300 --- /dev/null +++ b/lib/pow.c @@ -0,0 +1,27 @@ +// Licensed under the MIT License. + +#include "pow.h" + +long long mod_pow(long long b, long long a, long long mod) +{ + if (!mod) + { + mod = 1000000007l; + } + + long long exponent = b; + long long result = 1; + + while (a) + { + if (a % 2 == 1) + { + result = (result * exponent) % mod; + } + + exponent = (exponent * exponent) % mod; + a /= 2; + } + + return result; +} diff --git a/lib/pow.h b/lib/pow.h new file mode 100644 index 0000000..da126b9 --- /dev/null +++ b/lib/pow.h @@ -0,0 +1,11 @@ +// Licensed under the MIT License. + +/** + * Performs modulus division on a number raised to the power of another number. + * + * @param b the base. + * @param a the exponent. + * @param mod the modulus, or `0` for the default modulus. + * @return The result of the expression `b` ^ `a` mod `mod`. +*/ +long long mod_pow(long long b, long long a, long long mod); diff --git a/lib/primality_tests/miller_rabin_primality_test.c b/lib/primality_tests/miller_rabin_primality_test.c index 7d2cd83..21c8283 100644 --- a/lib/primality_tests/miller_rabin_primality_test.c +++ b/lib/primality_tests/miller_rabin_primality_test.c @@ -2,34 +2,16 @@ #include #include +#include "../pow.h" #include "../primality_test.h" -static long long miller_rabin_mod_pow(long long a, long long n, long long mod) -{ - long long exponent = a; - long long result = 1; - - while (n) - { - if (n % 2 == 1) - { - result = (result * exponent) % mod; - } - - exponent = (exponent * exponent) % mod; - n /= 2; - } - - return result; -} - static bool miller_rabin_witness( long long n, long long s, long long d, long long a) { - long long x = miller_rabin_mod_pow(a, d, n); + long long x = mod_pow(a, d, n); long long y = 1; while (s) diff --git a/lib/series.h b/lib/series.h index 2aa93f5..4c86a33 100644 --- a/lib/series.h +++ b/lib/series.h @@ -1,6 +1,6 @@ // Licensed under the MIT License. -#include "_/../string.h" +#include "euler.h" /** Represents a series of decimal digits. */ struct Series diff --git a/lib/sort.h b/lib/sort.h index ffd0ab0..82b5222 100644 --- a/lib/sort.h +++ b/lib/sort.h @@ -50,20 +50,6 @@ void insertion_sort( size_t itemSize, Comparer itemComparer); -/** - * - * - * @param items - * @param count - * @param itemSize - * @param itemComparer -*/ -void quick_sort( - Array items, - size_t count, - size_t itemSize, - Comparer itemComparer); - /** * * @param items diff --git a/lib/sorts/merge_sort.c b/lib/sorts/merge_sort.c index 5ce99b3..b104c4e 100644 --- a/lib/sorts/merge_sort.c +++ b/lib/sorts/merge_sort.c @@ -16,7 +16,7 @@ void merge_sort( if (!buffer) { - quick_sort(items, count, itemSize, itemComparer); + qsort(items, count, itemSize, itemComparer); return; } diff --git a/lib/string.c b/lib/string.c index 32ce2a7..5ce7ba3 100644 --- a/lib/string.c +++ b/lib/string.c @@ -2,7 +2,7 @@ #include #include -#include "_/../string.h" +#include "euler.h" String string(size_t length) { diff --git a/lib/string.h b/lib/string.h deleted file mode 100644 index 19d3420..0000000 --- a/lib/string.h +++ /dev/null @@ -1,42 +0,0 @@ -// Licensed under the MIT License. - -#ifndef STRING_554c4c38a6694dd599b5d6e01dedb42d -#define STRING_554c4c38a6694dd599b5d6e01dedb42d -#include "object.h" -#include - -/** Represents text as a zero-terminated sequence of characters. */ -typedef char* String; - -/** - * Initializes a new `String` instance with the given length. - * - * @param length the string length. - * @return A new string with the given length, or `NULL` if the process is out - * of memory. The caller is responsible. -*/ -String string(size_t length); - -/** - * Creates a new instance of `String` with the same value as a specified - * `String`. - * - * @param instance the `String` instance to copy. - * @return A new string with the same value, or `NULL` if the process is out of - * memory. The caller is responsible. - */ -String string_clone(String instance); - -/** - * Compares `left` with `right` and returns an integer that indicates whether - * `left` precedes, follows, or appears in the same position in the sort order - * as `right`. - * - * @param left a string to compare to `right`. - * @param right a string to compare to `left`. - * @return A signed integer that indicates the relative values of `left` and - * `right`. -*/ -int string_comparer(const void* left, const void* right); - -#endif diff --git a/lib/string_builder.h b/lib/string_builder.h index 6449ccf..7e25806 100644 --- a/lib/string_builder.h +++ b/lib/string_builder.h @@ -2,8 +2,7 @@ #include #include -#include "_/../string.h" -#include "exception.h" +#include "euler.h" /** Represents a mutable string of characters. */ struct StringBuilder diff --git a/lib/string_collection.h b/lib/string_collection.h index e1a2e5c..ab8e0b7 100644 --- a/lib/string_collection.h +++ b/lib/string_collection.h @@ -1,6 +1,5 @@ // Licensed under the MIT License. -#include "_/../string.h" #include "list.h" #include "stream.h" diff --git a/lib/swaps/swap.c b/lib/swap.c similarity index 93% rename from lib/swaps/swap.c rename to lib/swap.c index 9cd62a9..6af1f07 100644 --- a/lib/swaps/swap.c +++ b/lib/swap.c @@ -1,6 +1,6 @@ // Licensed under the MIT License. -#include "../swap.h" +#include "swap.h" void swap(Object left, Object right, size_t size) { diff --git a/src/id0005.c b/src/id0005.c index 929c6d2..fd9e8cf 100644 --- a/src/id0005.c +++ b/src/id0005.c @@ -5,20 +5,15 @@ #include "../lib/euclidean.h" #include "../lib/euler.h" -static long math_lcm(long a, long b) -{ - return (a / gcd(a, b)) * b; -} - int main(void) { - long lcm = 2; + long result = 2; clock_t start = clock(); for (int i = 3; i <= 20; i++) { - lcm = math_lcm(lcm, i); + result = lcm(result, i); } - return euler_submit(5, lcm, start); + return euler_submit(5, result, start); } diff --git a/src/id0016.c b/src/id0016.c index b3494b7..046109d 100644 --- a/src/id0016.c +++ b/src/id0016.c @@ -6,7 +6,6 @@ #include "../lib/euler.h" #include "../lib/exception.h" #include "../lib/series.h" -#include "../lib/string.h" int main(void) { diff --git a/src/id0018.c b/src/id0018.c index b0da9fa..d58528a 100644 --- a/src/id0018.c +++ b/src/id0018.c @@ -4,7 +4,6 @@ // Maximum Path Sum II #include "../lib/euler.h" -#include "../lib/string.h" #define BUFFER_SIZE 512 #define MAX_HEIGHT 100 diff --git a/src/id0020.c b/src/id0020.c index 41499e9..3e4a810 100644 --- a/src/id0020.c +++ b/src/id0020.c @@ -6,7 +6,6 @@ #include "../lib/euler.h" #include "../lib/exception.h" #include "../lib/series.h" -#include "../lib/string.h" int main(void) { diff --git a/src/id0024.c b/src/id0024.c index b3c0724..4d89d8b 100644 --- a/src/id0024.c +++ b/src/id0024.c @@ -11,7 +11,7 @@ int main(void) int digits[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; clock_t start = clock(); - permutation_begin(&it, digits, sizeof * digits, 10, int_comparer); + permutation_begin(&it, digits, 10, sizeof * digits, int_comparer); for (long i = 0; i < 999999l; i++) { diff --git a/src/id0032.c b/src/id0032.c index d1f9006..3a23725 100644 --- a/src/id0032.c +++ b/src/id0032.c @@ -15,7 +15,7 @@ int main(void) euler_ok(list(&set, sizeof(long), 0)); - for (permutation_begin(&it, digits, sizeof * digits, 9, int_comparer); + for (permutation_begin(&it, digits, 9, sizeof * digits, int_comparer); !it.end; permutation_next(&it)) { diff --git a/src/id0034.c b/src/id0034.c index b9a5317..f80d27f 100644 --- a/src/id0034.c +++ b/src/id0034.c @@ -10,11 +10,11 @@ int main(void) { long sum = 0; clock_t start = clock(); - long long* factorial = factorial_range(10); + long long* factorials = factorial_range(10); - euler_assert(factorial); + euler_assert(factorials); - long end = 7 * factorial[9]; + long end = 7 * factorials[9]; for (long n = 10; n <= end; n++) { @@ -22,7 +22,7 @@ int main(void) for (long k = n; k; k /= 10) { - factorialSum += factorial[k % 10]; + factorialSum += factorials[k % 10]; } if (n == factorialSum) @@ -31,7 +31,7 @@ int main(void) } } - free(factorial); + free(factorials); return euler_submit(34, sum, start); } diff --git a/src/id0041.c b/src/id0041.c index b5606d9..9fc14e2 100644 --- a/src/id0041.c +++ b/src/id0041.c @@ -30,8 +30,8 @@ int main(void) for (permutation_begin( &it, digits.items, - digits.itemSize, digits.count, + digits.itemSize, int_comparer); !it.end; permutation_next(&it)) diff --git a/src/id0043.c b/src/id0043.c index f235e80..5519576 100644 --- a/src/id0043.c +++ b/src/id0043.c @@ -38,7 +38,12 @@ int main(void) string_builder(&digits, 0); string_builder_append_string(&digits, "0123456789"); - for (permutation_begin(&it, digits.buffer, 1, digits.length, char_comparer); + for (permutation_begin( + &it, + digits.buffer, + digits.length, + sizeof * digits.buffer, + char_comparer); !it.end; permutation_next(&it)) { diff --git a/src/id0053.c b/src/id0053.c index 383da7d..7fa4e91 100644 --- a/src/id0053.c +++ b/src/id0053.c @@ -12,24 +12,26 @@ int main(void) for (int n = 1; n <= 100; n++) { - bool last = false; + long long* binomials = binomial_mod_range(n, 0); + + euler_assert(binomials); - for (int r = 1; r <= n / 2; r++) + for (int r = 1; r <= n; r++) { - long long c = binomial(n, r); + int k = r; - last = c > 1000000l || c < 0; + if (k > n - k) + { + k = n - k; + } - if (last) + if (binomials[k] > 1000000l) { - count += 2; + count++; } } - if (n % 2 == 1 && last) - { - count--; - } + free(binomials); } return euler_submit(53, count, start); diff --git a/src/id0054.c b/src/id0054.c index 0dfafcc..36cdb29 100644 --- a/src/id0054.c +++ b/src/id0054.c @@ -3,7 +3,6 @@ // Poker Hands #include "../lib/euler.h" -#include "../lib/string.h" enum HandType { diff --git a/src/id0056.c b/src/id0056.c index bc39462..323d713 100644 --- a/src/id0056.c +++ b/src/id0056.c @@ -5,7 +5,6 @@ #include #include #include "../lib/euler.h" -#include "../lib/string.h" int main(void) { diff --git a/src/id0062.c b/src/id0062.c index 75bb13a..4ac486f 100644 --- a/src/id0062.c +++ b/src/id0062.c @@ -3,6 +3,7 @@ // Cubic Permutations #include +#include "../lib/comparer.h" #include "../lib/euler.h" #include "../lib/hash.h" #include "../lib/list.h" diff --git a/src/id0065.c b/src/id0065.c index c0771c4..2460f5b 100644 --- a/src/id0065.c +++ b/src/id0065.c @@ -4,7 +4,6 @@ #include #include "../lib/euler.h" -#include "../lib/string.h" int main(void) { diff --git a/src/id0068.c b/src/id0068.c index 3229306..2c4b5d7 100644 --- a/src/id0068.c +++ b/src/id0068.c @@ -13,7 +13,7 @@ int main(void) struct PermutationIterator it; clock_t start = clock(); - for (permutation_begin(&it, l, sizeof * l, 10, int_comparer); + for (permutation_begin(&it, l, 10, sizeof * l, int_comparer); !it.end; permutation_next(&it)) { diff --git a/src/id0074.c b/src/id0074.c index c6170a2..fa385c0 100644 --- a/src/id0074.c +++ b/src/id0074.c @@ -14,9 +14,9 @@ int main(void) euler_assert(visited); - long long* factorial = factorial_range(10); + long long* factorials = factorial_range(10); - euler_assert(factorial); + euler_assert(factorials); euler_ok(list(&terms, sizeof(long), 60)); int count = 0; @@ -35,7 +35,7 @@ int main(void) for (long k = n; k; k /= 10) { - sum += factorial[k % 10]; + sum += factorials[k % 10]; } if (sum >= 1000000l) @@ -66,7 +66,7 @@ int main(void) } free(visited); - free(factorial); + free(factorials); finalize_list(&terms); return euler_submit(74, count, start); diff --git a/src/lc0007.c b/src/lc0007.c new file mode 100644 index 0000000..7489d8e --- /dev/null +++ b/src/lc0007.c @@ -0,0 +1,18 @@ +// Licensed under the MIT License. + +// Reverse Integer + +#include +#include "../lib/euler.h" + +int reverse(int value) +{ + long long result = math_reverse(value); + + if (result < INT_MIN || result > INT_MAX) + { + return 0; + } + + return result; +} diff --git a/src/lc0008.c b/src/lc0008.c new file mode 100644 index 0000000..473bd95 --- /dev/null +++ b/src/lc0008.c @@ -0,0 +1,24 @@ +// Licensed under the MIT License. + +// String to Integer + +#include +#include +#include "../lib/euler.h" + +int myAtoi(String value) +{ + long long result = atoll(value); + + if (result > INT_MAX) + { + return INT_MAX; + } + + if (result < INT_MIN) + { + return INT_MIN; + } + + return result; +} diff --git a/src/lc0009.c b/src/lc0009.c new file mode 100644 index 0000000..c83d82a --- /dev/null +++ b/src/lc0009.c @@ -0,0 +1,10 @@ +// Licensed under the MIT License. + +// Palindrome Number + +#include "../lib/euler.h" + +bool isPalindrome(int value) +{ + return value >= 0 && math_is_palindrome(value); +} diff --git a/src/lc0028.c b/src/lc0028.c new file mode 100644 index 0000000..bceaeb6 --- /dev/null +++ b/src/lc0028.c @@ -0,0 +1,18 @@ +// Licensed under the MIT License. + +// Find the Index of the First Occurrence in a String + +#include +#include "../lib/euler.h" + +int strStr(String value, String substring) +{ + char* p = strstr(value, substring); + + if (!p) + { + return -1; + } + + return p - value; +} diff --git a/src/lc0029.c b/src/lc0029.c new file mode 100644 index 0000000..388d9a0 --- /dev/null +++ b/src/lc0029.c @@ -0,0 +1,22 @@ +// Licensed under the MIT License. + +// Divide Two Integers + +#include + +int divide(int dividend, int divisor) +{ + long long quotient = (long long)dividend / divisor; + + if (quotient > INT_MAX) + { + return INT_MAX; + } + + if (quotient < INT_MIN) + { + return INT_MIN; + } + + return quotient; +} diff --git a/src/lc0031.c b/src/lc0031.c new file mode 100644 index 0000000..b2f08d7 --- /dev/null +++ b/src/lc0031.c @@ -0,0 +1,21 @@ +// Licensed under the MIT License. + +// Next Permutation + +#include +#include "../lib/permutation_iterator.h" + +void nextPermutation(int items[], int length) +{ + struct PermutationIterator it; + + permutation_begin(&it, items, length, sizeof * items, int_comparer); + permutation_next(&it); + + if (it.end) + { + qsort(items, length, sizeof * items, int_comparer); + + return; + } +} diff --git a/src/lc0046.c b/src/lc0046.c new file mode 100644 index 0000000..60cb368 --- /dev/null +++ b/src/lc0046.c @@ -0,0 +1,39 @@ +// Licensed under the MIT License. + +// Permutations + +#include +#include "../lib/list.h" +#include "../lib/permutation_iterator.h" +#include "../lib/euler.h" + +int** permute(int items[], int length, int* returnSize, int** returnColumnSizes) +{ + struct List results; + struct PermutationIterator it; + + euler_ok(list(&results, sizeof(int*), 0)); + qsort(items, length, sizeof * items, int_comparer); + + for (permutation_begin(&it, items, length, sizeof * items, int_comparer); + !it.end; + permutation_next(&it)) + { + size_t size = length * sizeof * items; + int* item = malloc(size); + + euler_assert(item); + memcpy(item, items, size); + euler_ok(list_add(&results, &item)); + } + + *returnSize = results.count; + *returnColumnSizes = malloc(results.count * sizeof ** returnColumnSizes); + + for (size_t i = 0; i < results.count; i++) + { + returnColumnSizes[0][i] = length; + } + + return results.items; +} diff --git a/src/lc0050.c b/src/lc0050.c new file mode 100644 index 0000000..9feff81 --- /dev/null +++ b/src/lc0050.c @@ -0,0 +1,10 @@ +// Licensed under the MIT License. + +// Pow(x, n) + +#include + +double myPow(double x, int n) +{ + return pow(x, n); +} diff --git a/src/lc0060.c b/src/lc0060.c new file mode 100644 index 0000000..7616819 --- /dev/null +++ b/src/lc0060.c @@ -0,0 +1,33 @@ +// Licensed under the MIT License. + +// Permutation Sequence + +#include "../lib/euler.h" +#include "../lib/permutation_iterator.h" + +String getPermutation(int n, int k) +{ + struct PermutationIterator it; + String sequence = string(n); + + euler_assert(sequence); + + for (int i = 0; i < n; i++) + { + sequence[i] = (i + 1) + '0'; + } + + sequence[n] = '\0'; + k--; + + qsort(sequence, n, sizeof * sequence, char_comparer); + + for (permutation_begin(&it, sequence, sizeof * sequence, n, char_comparer); + k > 0; + permutation_next(&it)) + { + k--; + } + + return sequence; +} diff --git a/src/lc0062.c b/src/lc0062.c new file mode 100644 index 0000000..992d7f8 --- /dev/null +++ b/src/lc0062.c @@ -0,0 +1,10 @@ +// Licensed under the MIT License. + +// Unique Paths + +#include "../lib/binomial.h" + +int uniquePaths(int m, int n) +{ + return binomial(m + n - 2, n - 1); +} diff --git a/src/lc0069.c b/src/lc0069.c new file mode 100644 index 0000000..93ee8b9 --- /dev/null +++ b/src/lc0069.c @@ -0,0 +1,10 @@ +// Licensed under the MIT License. + +// Sqrt(x) + +#include + +int mySqrt(int x) +{ + return sqrt(x); +} diff --git a/src/lc0075.c b/src/lc0075.c new file mode 100644 index 0000000..5a87fa0 --- /dev/null +++ b/src/lc0075.c @@ -0,0 +1,10 @@ +// Licensed under the MIT License. + +// Sort Colors + +#include "../lib/comparer.h" + +void sortColors(int items[], int length) +{ + qsort(items, length, sizeof * items, int_comparer); +} diff --git a/src/lc0367.c b/src/lc0367.c new file mode 100644 index 0000000..69b37ac --- /dev/null +++ b/src/lc0367.c @@ -0,0 +1,10 @@ +// Licensed under the MIT License. + +// Valid Perfect Square + +#include "../lib/euler.h" + +bool isPerfectSquare(int value) +{ + return math_is_polygonal(4, value, NULL); +} diff --git a/src/lc2119.c b/src/lc2119.c new file mode 100644 index 0000000..006affb --- /dev/null +++ b/src/lc2119.c @@ -0,0 +1,10 @@ +// Licensed under the MIT License. + +// A Number After a Double Reversal + +#include "../lib/euler.h" + +bool isSameAfterReversals(int value) +{ + return math_reverse(math_reverse(value)) == value; +} diff --git a/src/lc2400.c b/src/lc2400.c new file mode 100644 index 0000000..dc185f1 --- /dev/null +++ b/src/lc2400.c @@ -0,0 +1,26 @@ +// Licensed under the MIT License. + +// Number of Ways to Reach a Position After Exactly k Steps + +#include "../lib/binomial.h" +#include "../lib/euler.h" + +int numberOfWays(int start, int end, int k) +{ + int difference = abs(end - start); + + if (difference > k || (difference + k) % 2 == 1) + { + return 0; + } + + long long* binomials = binomial_mod_range(k, 0); + + euler_assert(binomials); + + long long result = binomials[(difference + k) / 2]; + + free(binomials); + + return result; +} diff --git a/src/lc2550.c b/src/lc2550.c new file mode 100644 index 0000000..d53d6c5 --- /dev/null +++ b/src/lc2550.c @@ -0,0 +1,10 @@ +// Licensed under the MIT License. + +// Monkey Move + +#include "../lib/pow.h" + +int monkeyMove(int n) +{ + return (mod_pow(2, n, 1000000007l) - 2 + 1000000007l) % 1000000007l; +} diff --git a/tools/test.sh b/tools/test.sh index fc91a4d..c3bb775 100644 --- a/tools/test.sh +++ b/tools/test.sh @@ -1,7 +1,7 @@ # Licensed under the MIT License. -run="valgrind -q" -#run="" +#run="valgrind -q" +run="" for i in {0001..0007}; do