Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » Rätselecke » 20. Virtualrästel (anfänger - Fortgeschrittene)

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] > 2 < [ 3 ] [ 4 ]
010
02.05.2003, 12:28 Uhr
~0xdeadbeef
Gast


Du vergisst, den seed für den Zufallszahlengenerator zu setzen. Ansonsten ist der Ansatz aber sehr schön, es auszunutzen, dass die Mengen eine maximale Größe haben.

Ich hab allerdings noch eine Idee, wie man das ganze optimieren könnte:

C++:
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>

int main(int argc, char* argv[]){
    int i,j,anzahl1,anzahl2;
    char menge1[26],menge2[26],schnittmenge[26], vereinigungsmenge[26];

    srand(time(0)); //seed setzen

    printf("Mächtigkeit Menge1(max26): "); scanf("%d",&anzahl1);
    printf("Mächtigkeit Menge2(max26): "); scanf("%d",&anzahl2);

    for(i=0;i<26;i++){
        menge1[ i ]=0;
        menge2[ i ]=0;
        schnittmenge[ i ]=0;
        vereinigungsmenge[ i ]=0;
    }

    for(i=0;i<anzahl1;i++){
        do {
            j = rand() % 26;
        } while (menge1[j]);
        menge1[j] = 'A' + j;
    }

    for(i=0;i<anzahl2;i++){
        do {
            j = rand() % 26;
        } while(menge2[j]);
        menge2[j] = 'A' + j;
    }

    for(i=0;i<26;i++){ //Hier wird optimiert.
        schnittmenge[i] = menge1[i] & menge2[i];
        vereinigungsmenge[i] = menge1[i] | menge2[i];
    }
    
    printf("\nMenge 1n");
    for(i=0;i<26;i++) printf("%c",menge1[ i ]);
    printf("\n\nMenge 2n");
    for(i=0;i<26;i++) printf("%c",menge2[ i ]);
    printf("\n\nSchnittn");
    for(i=0;i<26;i++) printf("%c",schnittmenge[ i ]);
    printf("\n\nVereinigungn");
    for(i=0;i<26;i++) printf("%c",vereinigungsmenge[ i ]);
    printf("\n\n");

    
    return 0;
}


Der Algorithmus nutzt aus, dass an einer bestimmten Position in menge1 und menge2 nur entweder 0 oder 'A' + index stehen kann. Ein Beispiel: Für x = 2 können folgende Kombinationen von menge1[x] und menge2[x] auftreten:

1. menge1[x] = 0, menge2[x] = 0.
Das führt dazu, dass menge1[x] & menge2[x] = 0 und menge1[x] | menge2[x] = 0

2. menge1[x] = 'C', menge2[x] = 0
Das führt dazu, dass menge1[x] & menge2[x] = 0 ist, weil 0 bitweise mit etwas anderem geundet immer 0 gibt, und menge1[x] | menge2[x] = 'C' ist, weil 0 bitweise geodert mit etwas anderem immer das andere gibt

3. menge1[x] = 0, menge2[x] = 'C'
siehe 2.

4. menge1[x] = menge2[x] = 'C'
Das führt dazu, dass menge1[x] & menge2[x] = 'C' und menge1[x] | menge2[x] = 'C' ist.

Das ist genau das, was wir für Schnitt und Vereinigung der mengen brauchen - und es spart uns ne ganze Reihe Vergleiche.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
011
02.05.2003, 12:32 Uhr
~0xdeadbeef
Gast


Das sind allerdings Feinheiten, an der grundsätzlichen Struktur des Algorithmus ändert sich dadurch nichts. Einschätzung meinerseits: Schönes Programm, das du da fabriziert hast. Alles, was man daran noch verbessern könnte, ist im Grunde Kosmetik und nicht weiter wichtig.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
012
02.05.2003, 12:43 Uhr
virtual
Sexiest Bit alive
(Operator)


Also was ich vielleicht noch erwähnenswert finde: Bei dieser speziellen Aufgabe (nur 26 Elemente möglich) macht es nicht viel aus, wenn man so vorgeht, wie Heiko oder beefy. Wenn allerdings 1000000 Elemente die max. Obergrenze sind, dann ist:

C++:
   for(i=0;i<anzahl1;i++){
        do {
            j = rand() % 26;
        } while (menge1[j]);
        menge1[j] = 'A' + j;
    }


Bei einer großen anzahl1 (sagen wir mal anzahl1 = 999999) deutlich langsamer als die Lösung mit dem Random-Shuffle. Bei kleinen Zahlen hingegen ist die Geschwindigkeit wahrscheinlich bei Heikos und beefies besser - das hängt vom ZUfall ab (Die Laufzeit ist beim random-shuffle vorhersagbar, bei dem oben zitierten Ansatz jedoch nicht).
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
013
02.05.2003, 12:47 Uhr
~Heiko
Gast


@beefy
Ok danke, das mit der Optimierung gefällt mir gut.
Auch das mit dem 'A' ist viel übersichtlicher und man weiss dann noch wenn man sich das mal später anguckt was der algo überhaupt macht
Da wär ich mal wieder nicht von alleine drauf gekommen das Bitweise zu verunden (bzw zu verodern).

Eine Frage bleibt da allerdings noch für mich:
Warum ist das so wichtig den seed zu setzten?
Wird nicht sonst einfach ein defaultwert genommen oder kann das zu üblen Fehlern führen?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
014
02.05.2003, 13:00 Uhr
~Heiko
Gast


@virtual
Warum ist bei meiner Version die Laufzeit nicht vorhersagbar.
Wenn ich mich nicht irre werden die sogenanten "Zufallszahlen" doch auch nur durch ein Modulo-Algo errechnet.
Zum einem kommt ein dabei zu Gute, dass es eigentlich nicht vorkommt das die selber Zahl mehrmals hintereinander "gewürfelt" wird. (was ja auch nicht wahrscheinlich ist aber in der Realität durchaus vorkommen kann). sollter also tendenziell schneller das Feld füllen als ein "echter" zufi.

Da die "sogenanten Zufallszahlen" also durch einen festen Algo berechnet werden muss doch auch vorhersagbar sein wie lange die Laufzeit ist.
Oder bin ich da auf dem falschen Dampfer?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
015
02.05.2003, 13:19 Uhr
~0xdeadbeef
Gast


Naja, im Grunde hast du recht. Es kann ziemlich Laufzeit fressen, wenn jemand eine fast volle Menge haben will. Von daher wäre folgende Optimierung zu überlegen:

C++:
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>

#define SCHNITT     (2)
#define VEREINIGUNG (3)

#define MIN (1)
#define MAX (26)

const char* const MENGENNAMEN[] = {"Menge 1", "Menge 2", "Schnittmenge", "Vereinigungsmenge"};

int main(int argc, char* argv[]){
    int i,j,tmp,anzahl[2] = {0};
    char menge[4][MAX] = {{0}, {0}, {0}, {0}};
  
    srand(time(0)); //seed setzen

    for(i = 0; i < 2; ++i) {
        do {
            printf("Mächtigkeit %s (%d - %d): ", MENGENNAMEN[i], MIN, MAX);
            scanf("%d", &anzahl[i]);
        } while(anzahl[i] < MIN || anzahl[i] > MAX);

        /* OPTIMIERUNG - ANFANG */
        if(anzahl[i] <= MAX/2) {
            for(j = 0; j < anzahl[i]; ++j) {
                do {
                    tmp = rand() % MAX;
                } while (menge[i][tmp]);
                menge[i][tmp] = 'A' + tmp;
            }
        } else {
            for(j = 0; j < MAX; ++j) menge[i][j] = 'A' + j;
            for(j = 0; j < MAX - anzahl[i]; ++j) {
            do {
                    tmp = rand() % MAX;
                } while(!menge[i][tmp]);
                menge[i][tmp] = 0;
            }
        }
        /* OPTIMIERUNG - ENDE */
    }
    
  for(i = 0; i < MAX; i++){
    menge[SCHNITT][i] = menge[0][i] & menge[1][i];
    menge[VEREINIGUNG][i] = menge[0][i] | menge[1][i];
  }
    
    for(i = 0; i < 4; ++i) {
        printf("\n%s: ", MENGENNAMEN[i]);
        for(j = 0; j < MAX; ++j)
            printf("%c", menge[i][j]);
    }
    printf("\n\n");

    return 0;
}

 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
016
02.05.2003, 13:22 Uhr
virtual
Sexiest Bit alive
(Operator)


@heiko
Naja, bleiben wir mal bei dem Beispiel mit den 26 Elementen als Maximum. Du hast für die erste Menge als Mächtigkeit 26 Angegeben und bereits 25 Elemente erfolgreich über Zufall bestimmt (alle Müssen verschieden sein!). Eigentlich muß jetzt Dein Programm nur noch darauf warten, bis der letzte fehlende Buchstabe vom Zufallsgenerator zurückgegeben wird. Wie lange das Dauert, hängt vom Zufall ab. In dieser Situation ist die Wahrscheinlichkeit dafür, daß die Fehlende Zahl im nächsten Durchlauf gezogen wird ca. 3.8%. Bei einer großen Menge (1000000 Elemente, 999999 bereits gezogen) beträgt die Wahrscheinlichkeit sogar nur noch 0.0001%).

Theoretisch ist die Laufzeit vorhersagbar, aber dazu müßtest Du wirklich genaue Kenntnis des Algos haben und - wenn srand mit der aktuellen Zeit initialisiert wurde (was üblich ist) - die genaue Urzeit kennen. Da also die laufzeit sogar von der Uhrzeit abhängt würde ich vereinfacht sagen: nicht in der Praxis vorhersagbar.

Und was die Frage angeht, ob zwei Zahlen hintereinader mehrfach vorkommen: Wenn Du Modulo X rechnest, dann beträgt die Wahrscheinlichkeit dafür eben (1/X)^2 * 100%. bei 26 sind das immerhin 0.14%.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 02.05.2003 um 13:23 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
017
02.05.2003, 13:34 Uhr
~0xdeadbeef
Gast


Damit kriegst du zwar genaugenommen auch keine berechenbare Laufzeit, aber die mittlere O-Zeit dürfte dadurch deutlich geringer werden.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
018
02.05.2003, 13:39 Uhr
~Heiko
Gast


Was zum Henker ist eine O-Zeit?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
019
02.05.2003, 13:40 Uhr
virtual
Sexiest Bit alive
(Operator)


Laufzeit
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] > 2 < [ 3 ] [ 4 ]     [ Rätselecke ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: