diff --git a/homework-02-rail-building/main.c b/homework-02-rail-building/main.c new file mode 100644 index 0000000..bae721f --- /dev/null +++ b/homework-02-rail-building/main.c @@ -0,0 +1,196 @@ +#include +#include +#include + +#ifdef __PROGTEST__ +#define debug(...) ((void)0) +#else +#define debug(fmt, ...) \ + fprintf(stdout, "[DEBUG %s:%d %s()] " fmt "\n", __FILE__, __LINE__, \ + __func__, ##__VA_ARGS__) +#endif + +typedef long long int lli; + +typedef struct rails_t { + lli rail_length_1; + lli *larger_length; + lli rail_length_2; + lli *shorter_length; + lli total_distance; +} 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) +// + +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; + } + + while ((a & 1) == 0) + a >>= 1; + + do { + while ((b & 1) == 0) + b >>= 1; + + if (a > b) { + a ^= b; + b ^= a; + a ^= b; + } + + b = (b - a); + } while (b != 0); + + return a << k; +} + +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 (pivot != -1) { + lli i; + for (i = pivot;; i += smallest_step) { + + if ((rails.total_distance - i * (*rails.shorter_length)) < 0) { + break; + } + + if (verbose) { + + 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); + } + } + + variants++; + } + } + + return variants; +} + +int main() { + printf("Delky koleji:\n"); + + 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 == rail_length_2)) { + return invalid_input(); + } + + printf("Vzdalenost:\n"); + + lli total_distance = 0; + char operand; + + if (scanf(" %c %lld", &operand, &total_distance) != 2 || + (operand != '+' && operand != '-')) { + 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; + + 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++; + } + + variants += find_solutions(rails, verbose); + } + + if (variants != 0) { + printf("Celkem variant: %lld\n", variants); + } else { + printf("Reseni neexistuje.\n"); + } +}