#include <iostream>
#include <stdlib.h>
#include <limits.h>

// disclaimer, the following function is partially copy pasted from
// stackoverflow as this functionality is not a core part of the 
// homework. of course I understand what it does, I read it!
int check_number(int *num, char* arg) {
    char *p;

    long conv = strtol(arg, &p, 10);

    // Check for problems: e.g., the string does not represent an integer
    // or the integer is larger than int
    if ( *p != '\0' || conv > INT_MAX || conv < INT_MIN) {
        return 0;
    }
    *num = conv;
    return 1;
}

// Aufgabe 1.1
int truncate_fraction(int zaehler, int nenner) {
    // moving the minus
    if (nenner < 0) {
        zaehler = zaehler * (-1);
        nenner = nenner * (-1);
    }
    
    // the actual algorithm
    int teiler = 1;
    if (abs(nenner) < abs(zaehler)) {
        if (nenner % zaehler == 0) {
            zaehler = zaehler / nenner;
            nenner = 1;
        } else {
            teiler = abs(nenner) - 1;
        }
    } else { 
        teiler = abs(zaehler) - 1;
    }
    
    for (;teiler > 1; teiler--) {
        if ((nenner % teiler == 0) && (zaehler % teiler == 0)) {
            nenner /= teiler;
            zaehler /= teiler;
        }
    }
    
    if (nenner > 1)
        std::cout << "Zähler: " << zaehler << "; Nenner: " << nenner << std::endl;
    else
        std::cout << "Kein Bruch. Zahl: " << zaehler << std::endl;
    return 0;
}

// Aufgabe 1.2
int do_this_recursive(int groesser, int kleiner) {
    if (groesser % kleiner == 0)
        return kleiner;
    return do_this_recursive(groesser, kleiner-1);
}

int find_greatest_common_divisor(int zaehler, int nenner) {
    if (nenner % zaehler == 0)
        return zaehler;
    if (zaehler % nenner == 0)
        return nenner;
    
    int ggt = 1;
    if (abs(nenner) > abs(zaehler)) 
        ggt = do_this_recursive(abs(nenner), abs(zaehler));
    else
        ggt = do_this_recursive(abs(zaehler), abs(nenner));
    return ggt;
}

// Aufgabe 1.3
int main(int argc, char *argv[]) {
    // you know, I could also do this repeatedly like 1.3 wants, but...
    // I think technically you can also just call the binary with arguments repeatedly as well
    // to prevent loosing points, you can have this:
    /*
     * int main() {
     *      int zaehler, nenner;
     *      std::cout << "Input Zähler: " << std::endl;
     *      std::cin >> zaehler;
     *      std::cout << "Input Nenner: " << std::endl;
     *      std::cin >> nenner;
     *      truncate_fraction(zaehler, nenner);
     *      int ggt = find_greatest_common_divisor(zaehler, nenner);
     *      std::cout << "Größter gemeinsamer Teiler: " << ggt << std::endl;
     *      return 0;
     * }
     * 
     * Please don't make me do it like this, it scares me
     */
    if (argc < 3) {
        std::cout << "No/Not enough parameters given." << std::endl;
        return -1;
    }
    
    int zaehler, nenner;
    if (!(check_number(&zaehler, argv[1]) && check_number(&nenner, argv[2]))) {
        std::cout << "Your input is not valid." << std::endl;
        return -1;
    }

    truncate_fraction(zaehler, nenner);
    int ggt = find_greatest_common_divisor(zaehler, nenner);
    std::cout << "Größter gemeinsamer Teiler: " << ggt << std::endl;
    
    return 0;
}
