diff --git a/2017-03-28/Makefile b/2017-03-28/Makefile new file mode 100644 index 0000000..26afcda --- /dev/null +++ b/2017-03-28/Makefile @@ -0,0 +1,11 @@ +#!/usr/bin/make -f + +CFLAGS=-g -O2 -fPIC -fPIE -Wall -Wextra -Wformat=2 -Wunused -Wlogical-op -Wundef \ + -Wswitch-enum -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings \ + -Wconversion -D_FORTIFY_SOURCE=2 -fstack-protector -Wshadow -Wnested-externs + +LDFLAGS=-lm + +.PHONY: all + +all: jo-so_euler87 diff --git a/2017-03-28/jo-so_euler87.c b/2017-03-28/jo-so_euler87.c new file mode 100644 index 0000000..b0245ec --- /dev/null +++ b/2017-03-28/jo-so_euler87.c @@ -0,0 +1,108 @@ +#include +#include +#include + +static int cmp_uint(const void* p1, const void* p2) +{ + const uint a = *(const uint*)p1; + const uint b = *(const uint*)p2; + if (a < b) + return -1; + if (a == b) + return 0; + return 1; +} + +int main(void) +{ + const uint LIMIT = 50000000; + uint* const prime_numbers = malloc(4096); + if (prime_numbers == NULL) + { + perror("Failed to allocate memory for prime numbers"); + return EXIT_FAILURE; + } + uint* const prime_numbers_end = prime_numbers + 4096 / sizeof(*prime_numbers); + + uint max_pn = (uint)sqrt(LIMIT); + prime_numbers[0] = 2u; + prime_numbers[1] = 3u; + uint* next_pn = &prime_numbers[2]; + + for (uint num = *(next_pn - 1) + 2; num <= max_pn; num += 2) + { + for (uint i = (uint)sqrt(num); i >= 3; --i) + { + if (num % i == 0) + goto next; + } + if (next_pn >= prime_numbers_end) + { + fprintf(stderr, "Memory for prime numbers exceeded, but more needed.\n"); + return EXIT_FAILURE; + } + + *next_pn++ = num; + next: + ; + } + + printf("There are %ld numbers below sqrt(50.000.000)\n", next_pn - prime_numbers); + + uint* nums = NULL; + uint* nums_end = nums; + uint* next_num = nums; + + for (uint* pn2 = prime_numbers; pn2 < next_pn; ++pn2) + { + uint pow2 = *pn2 * *pn2; + + for (uint* pn3 = prime_numbers; pn3 < next_pn; ++pn3) + { + uint pow3 = *pn3 * *pn3 * *pn3; + + uint sum = pow2 + pow3; + if (sum >= LIMIT) + break; + + for (uint* pn4 = prime_numbers; pn4 < next_pn; ++pn4) + { + uint pow4 = *pn4 * *pn4; + pow4 *= pow4; + + uint sum2 = sum + pow4; + if (sum2 >= LIMIT) + break; + + if (next_num >= nums_end) + { + long next_num_idx = next_num - nums; + size_t new_size = (uint)(nums_end - nums) * sizeof(*nums) + (1 << 20); + nums = realloc(nums, new_size); + if (nums == NULL) + { + perror("Failed to increase memory for result numbers"); + return EXIT_FAILURE; + } + + nums_end = nums + new_size / sizeof(*nums); + next_num = &nums[next_num_idx]; + } + + *next_num++ = sum2; + } + } + } + nums_end = next_num; + + qsort(nums, (size_t)(nums_end - nums), sizeof(*nums), cmp_uint); + + uint count = 1; + for (const uint* n = nums + 1; n < nums_end; ++n) + if (*(n - 1) != *n) + ++count; + + printf("Answer: %d\n", count); + + return EXIT_SUCCESS; +}