#include<stdio.h>

// Ein Listenelement
struct IntListElem {
    IntListElem* next;  // Zeiger auf nächstes Element
    int value;          // Daten zu diesem Element  
} ;

// Eine Liste
struct IntList {
    int count;          // Anzahl Elemente in der Liste
    IntListElem* first; // Zeiger auf erstes Element der Liste
} ;


// Initialisiere eine Listenstruktur
void empty_list (IntList* l)
{
    l->first = 0;   // 0 ist keine gueltige Adresse: Liste ist leer
    l->count = 0;
}

// Fuege ein Element nach einem gegebenem ein
void insert_in_list (IntList* list, IntListElem* where, IntListElem* ins)
{
    if (where==0) // fuege am Anfang ein
    {
        ins->next = list->first;
        list->first = ins;
        list->count = list->count + 1;
    }
    else         // fuege nach where ein
    {
        ins->next = where->next;
        where->next = ins;
        list->count = list->count + 1;
    }
}

// Entferne ein Element nach einem gegebenem
// Liefere das entfernte Element zurueck
IntListElem* remove_from_list (IntList* list, IntListElem* where)
{
    IntListElem* p;  // das entfernte Element

    // where==0 dann entferne erstes Element
    if (where==0) 
    {
        p = list->first;
        if (p!=0)
        {
            list->first = p->next;
            list->count = list->count - 1;
        }
        return p;
    }

    // entferne Element nach where
    p = where->next;
    if (p!=0)
    {
        where->next = p->next;
        list->count = list->count - 1;
    }
    return p;
}

// creates a cyclic list with a linear part of k elements
// and a cyclic part of n elements
IntList* make_cyclic_list(int k, int n) {
    IntList* list = new IntList();
    empty_list(list);

    // create cyclic list of length n
    if (n > 0) {
        // create last element of list (its inserted first)
        IntListElem* last = new IntListElem();
        last->value = n+k;
        // insert the (now first, but later) last element into the list
        insert_in_list(list, 0, last);
            // now iterate over every other number
            for (int i = n+k-1; i > k; i--) {
            // and create a new list element
            IntListElem* elem = new IntListElem();
            // with the given number
            elem->value = i;
            // and add it to the list in the very beginning
            insert_in_list(list, 0, elem);
        }
        // make the last element reference the first one
        last->next = list->first;
    }
    IntListElem* firstCyclic = list->first;
    // add a linear part
    for (int i = k; i > 0; i--) {
        // create new list element
        IntListElem* elem = new IntListElem();
        // with given value
        elem->value = i;
        // and insert in the very beginning
        insert_in_list(list, 0, elem);
        // if it is the (first inserted, but later) last element of the linear
        // part, make it point to the first cyclic element
        if (i == k) {
            elem->next = firstCyclic;
        }
    }
    return list;
}

// Hase-Igel Algorithmus zum Finden eines Zyklus in einer Liste
int hase_igel(IntList* list) {
    // create igel, that goes on by one
    IntListElem* igel = list->first;
    // create hase that always skips one element
    IntListElem* hase = list->first;
    // count the number of steps needed
    int n = 0;
    // this is the first occurence of a cycle
    int first = 0;
    // move forward with igel and hase until we hit the end of the list
    while (igel != 0 && hase != 0) {
        // increment igel and hase
        igel = igel->next;
        hase = hase->next->next;
        // increment the step counter
        n++;
        // if igel and hase point to the same element, there
        // has to be a cycle
        if (igel == hase) {
            // save the first occurence
            if (first == 0) {
                first = n;
            // if we find the second one, return the difference
            } else {
                return n - first;
            }
        }
    }
    // if there is an end, there can't be a cycle
    return 0;
}

int main() {
    IntList* list = make_cyclic_list(10, 0);
    printf("Laenge des Zyklus: %d\n", hase_igel(list));
}
