From 3565364e12a2f8c4d0a6373bf6a1b81f3579890a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kl=C3=A9ger?= Date: Wed, 22 Oct 2025 08:44:14 +0200 Subject: [PATCH] hw-02: Final implementation --- homework-02-rail-building/main.c | 197 +++++++++++++------------------ 1 file changed, 80 insertions(+), 117 deletions(-) diff --git a/homework-02-rail-building/main.c b/homework-02-rail-building/main.c index bae721f..a848a66 100644 --- a/homework-02-rail-building/main.c +++ b/homework-02-rail-building/main.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,117 +7,107 @@ #define debug(...) ((void)0) #else #define debug(fmt, ...) \ - fprintf(stdout, "[DEBUG %s:%d %s()] " fmt "\n", __FILE__, __LINE__, \ + printf("[DEBUG %s:%d %s()] " fmt "\n", __FILE__, __LINE__, \ __func__, ##__VA_ARGS__) #endif typedef long long int lli; +typedef long double ld; typedef struct rails_t { - lli rail_length_1; - lli *larger_length; - lli rail_length_2; - lli *shorter_length; - lli total_distance; + lli r1; + lli r2; + lli d; } rails_t; -// find the pivot using the smaller of the rail lengths -// once pivot is found, the smallest step that will be used is -// gcd(rail length 1, rail length 2) -// +typedef struct eea_gcd_t { + lli g; + lli x; + lli y; +} eea_gcd_t; int invalid_input() { printf("Nespravny vstup.\n"); return EXIT_FAILURE; } -// https://www.geeksforgeeks.org/dsa/steins-algorithm-for-finding-gcd/ -int gcd(int a, int b) { - if (a == 0) - return b; - if (b == 0) - return a; - - int k; - for (k = 0; ((a | b) & 1) == 0; ++k) { - a >>= 1; - b >>= 1; +eea_gcd_t extended_euclidian_gcd(lli a, lli b) { + if (a == 0) { + eea_gcd_t res; + res.g = b; + res.x = 0; + res.y = 1; + return res; } - while ((a & 1) == 0) - a >>= 1; + eea_gcd_t res = extended_euclidian_gcd(b % a, a); - do { - while ((b & 1) == 0) - b >>= 1; + lli x = res.y - (b / a) * res.x; + lli y = res.x; - if (a > b) { - a ^= b; - b ^= a; - a ^= b; - } + res.x = x; + res.y = y; - b = (b - a); - } while (b != 0); - - return a << k; + return res; } -lli find_pivot(rails_t rails) { - lli pivot = -1; - - lli current_step; - - lli ratio = (rails.total_distance / *rails.shorter_length); - - for (lli i = 1; i < ratio; i++) { - current_step = rails.total_distance - i * (*rails.shorter_length); - - if (current_step % (*rails.larger_length) == 0) { - debug("Found pivot %lld\n", i); - pivot = i; - break; - } - } - - return pivot; -} - -lli find_smallest_step(rails_t rails) { - return *rails.larger_length / gcd(rails.rail_length_1, rails.rail_length_2); -} lli find_solutions(rails_t rails, bool verbose) { lli variants = 0; - lli pivot = find_pivot(rails); - lli smallest_step = find_smallest_step(rails); - debug("Smallest step = %lld", smallest_step); + if (rails.d == 0) { + debug("Zero total distance"); + if (verbose) { + printf("= %lld * 0 + %lld * 0\n", rails.r1, rails.r2); + } + return 1; + } - if (pivot != -1) { - lli i; - for (i = pivot;; i += smallest_step) { + if (rails.r1 == 0 && rails.d % rails.r2 == 0) { + if (verbose) { + printf("= %lld * %lld + %lld * 0\n", rails.r1, rails.d / rails.r2, + rails.r2); + } + return 1; + } - if ((rails.total_distance - i * (*rails.shorter_length)) < 0) { - break; - } + if (rails.r2 == 0 && rails.d % rails.r1 == 0) { + if (verbose) { + printf("= %lld * 0 + %lld * %lld\n", rails.r1, rails.r2, + rails.d / rails.r1); + } + return 1; + } - if (verbose) { + eea_gcd_t eea = extended_euclidian_gcd(rails.r1, rails.r2); + lli g = eea.g; - if (*rails.shorter_length == rails.rail_length_1) { - printf("= %lld * %lld + %lld * %lld\n", rails.rail_length_1, i, - rails.rail_length_2, - (rails.total_distance - i * rails.rail_length_1) / - rails.rail_length_2); - } else { - printf("= %lld * %lld + %lld * %lld\n", rails.rail_length_1, - (rails.total_distance - i * rails.rail_length_2) / - rails.rail_length_1, - rails.rail_length_2, i); - } - } + if (rails.d % g != 0) { + return 0; + } - variants++; + ld d_g = (ld)rails.d / (ld)g; + ld x0 = (ld)eea.x * d_g; + ld y0 = (ld)eea.y * d_g; + + + lli a_g = rails.r1 / g; + lli b_g = rails.r2 / g; + + lli n_min = (lli)ceil(-x0 / (ld)b_g); + lli n_max = (lli)floor(y0 / (ld)a_g); + + if (n_max < n_min) { + return 0; + } + + variants += n_max - n_min + 1; + + if (verbose) { + for (lli n = n_min; n <= n_max; n++) { + lli x = x0 + n * b_g; + lli y = y0 - n * a_g; + printf("= %lld * %lld + %lld * %lld\n", rails.r1, x, rails.r2, y); } } @@ -128,7 +119,7 @@ int main() { lli rail_length_1 = -1, rail_length_2 = -1; if (scanf(" %lld %lld", &rail_length_1, &rail_length_2) != 2 || - (rail_length_1 <= 0 && rail_length_2 <= 0) || + (rail_length_1 <= 0 || rail_length_2 <= 0) || (rail_length_1 == rail_length_2)) { return invalid_input(); } @@ -143,47 +134,19 @@ int main() { return invalid_input(); } - lli variants = 0; - bool verbose = operand == '+'; if (total_distance < 0) { return invalid_input(); } - if (total_distance == 0) { - if (verbose) { - printf("= %lld * 0 + %lld * 0\n", rail_length_1, rail_length_2); - } - variants++; - } else if (rail_length_1 == 0 && total_distance % rail_length_2 == 0) { - if (verbose) { - printf("= %lld * %lld + %lld * 0\n", rail_length_1, - total_distance / rail_length_2, rail_length_2); - } - } else if (rail_length_2 == 0 && total_distance % rail_length_1 == 0) { - if (verbose) { - printf("= %lld * 0 + %lld * %lld\n", rail_length_1, rail_length_2, - total_distance / rail_length_1); - } - } else if (rail_length_1 > 0 && rail_length_2 > 0) { - lli *smaller = - rail_length_1 > rail_length_2 ? &rail_length_2 : &rail_length_1; - lli *larger = - rail_length_1 > rail_length_2 ? &rail_length_1 : &rail_length_2; + lli variants = 0; + bool verbose = operand == '+'; + + if (rail_length_1 > 0 && rail_length_2 > 0) { rails_t rails; - rails.rail_length_1 = rail_length_1; - rails.rail_length_2 = rail_length_2; - rails.total_distance = total_distance; - rails.shorter_length = smaller; - rails.larger_length = larger; - - if (total_distance % rail_length_1 == 0) { - if (verbose) { - printf("= %lld * %lld + %lld * 0\n", rail_length_1, - total_distance / rail_length_1, rail_length_2); - } - variants++; - } + rails.r1 = rail_length_1; + rails.r2 = rail_length_2; + rails.d = total_distance; variants += find_solutions(rails, verbose); }