Algorithmus gesucht ...



  • Furble Wurble schrieb:

    std::map::upper_bound() brauch ich eigentlich gar nicht.

    Kommt drauf an wie "Wertebereich von 10 bis 20" zu verstehen ist. Wenn die 20 nicht mehr mit drin ist dann ja. Wenn die 20 mit drin sein soll würde man

    auto last  = m.upper_bound(20);
    

    schreiben.



  • [code="cpp"] auto is_foo[code="cpp"]

    das versteh ich nicht!



  • Sonne55 schrieb:

    auto is_foo
    

    das versteh ich nicht!

    Das würde jetzt ein wenig weit führen, auto und Lambdas zu erklären, die seit C++11 (also ca vier Jahre) im Standard sind.

    Lies Dich in beides ein.

    Bis dahin:
    mach eine Funktion draus:

    bool is_foo(const map_t::value_type& p){
      return p.second==foo;
    }
    


  • Ich hab Dein Skript ma angepastt und er sagt bei "auto is_2" "expect a Class oder namespace"

    // erstes Element:
            auto first = prufzahlen.lower_bound(10); // "eins hinter das letzte Element"
            auto last  = prufzahlen.lower_bound(20); // ob es 2 sind?
            auto is_2 = [](const prufzahlen::value_type& p){return p.second=2; };
    
            // das eigentliche zaehlen:
            auto n = count_if(last= 2);
            cout << n << endl;
    


  • Sonne55 schrieb:

    Ich hab Dein Skript ma angepastt und er sagt bei "auto is_2" "expect a Class oder namespace"

    // erstes Element:
            auto first = prufzahlen.lower_bound(10); // "eins hinter das letzte Element"
            auto last  = prufzahlen.lower_bound(20); // ob es 2 sind?
            auto is_2 = [](const prufzahlen::value_type& p){return p.second=2; };
            
            // das eigentliche zaehlen:
            auto n = count_if(last= 2);
            cout << n << endl;
    

    Ich habe mitlerweile Deinen anderen Thread gesehen und gehe davon aus, dass prufzahlen in Z. 4 oben eine variable und kein Typ ist.
    Der Typ ist std::map<int,int> .

    Also wäre korrekt:

    auto is_2 = [](const std::map<int,int>::value_type& p){return p.second==2; }; // noch ein Typo gefixt...
    

    In meinem Beispiel hatte ich mit

    using map_t = std::map<int,int>;
    

    einen eigenen Namen für Diesen Typ eingeführt.

    Wir sprechen übrigens nicht von "Skript" sondern einfach von Programm oder Quellcode.



  • Furble Wurble schrieb:

    Ich habe mitlerweile Deinen anderen Thread gesehen und gehe davon aus, dass prufzahlen in Z. 4 oben eine variable und kein Typ ist.
    Der Typ ist std::map<int,int> .

    Danke

    Furble Wurble schrieb:

    Also wäre korrekt:

    auto is_2 = [](const std::map<int,int>::value_type& p){return p.second==2; }; // noch ein Typo gefixt...
    

    In meinem Beispiel hatte ich mit

    using map_t = std::map<int,int>;
    

    einen eigenen Namen für Diesen Typ eingeführt.

    Aha ...

    bei mir sagt er jetze: "Unused variable "is_2" " Ist wirklich ungewöhnlich ...

    Ich hätte ja auch bei Deiner foo-bar-Lösung bleiben können und mit Pz Vf ersetzen, aber mit denen kann man nicht rechnen, denn ich habe doch als Typ nicht umsonst int genommen.



  • Furble Wurble schrieb:

    Also wäre korrekt:

    auto is_2 = [](const std::map<int,int>::value_type& p){return p.second==2; }; // noch ein Typo gefixt...
    

    Oder wenn dein Compiler schon C++14 (generic lambdas) unterstützt kannst du dort auch auto nutzen:

    auto is_2 = [](const auto& p){return p.second==2; };
    

    Sonne55 schrieb:

    bei mir sagt er jetze: "Unused variable "is_2" " Ist wirklich ungewöhnlich ...

    Das heißt dann das du is_2 (noch) nicht benutzt hast und ist natürlich nur eine Warnung. Das is_2 Objekt brauchst du ja dann für die count_if Funktion und dann sollte auch die Warnung weg sein. Der Code

    auto n = count_if(last= 2);
    

    ist auch falsch. Mache es so wie im Beispiel von Furble Wurble nur mit is_2 , statt is_foo .



  • okay ... jetzt gibt er einen 0 aus ...

    Was ich nicht versteh:

    auto n = count_if(first, last, is_2);
    

    Er soll doch nur in "last" suchen, wieviele 2-en er dort findet. Warum kommt in die Klammer das first rein? In "first" stehen doch nur die PZ drin, und nicht eine einzige 2.

    Sind die Klammerangaben denn nicht,
    a - wo er suchen soll
    b - was er suchen soll?



  • sebi707 schrieb:

    Oder wenn dein Compiler schon C++14 (generic lambdas) unterstützt kannst du dort auch auto nutzen:

    auto is_2 = [](const auto& p){return p.second==2; };
    

    ... habe übrigens yosemite Xcode 6.1.1 ist das schon 14, oder noch 11?



  • Die Variable last ist nur ein Iterator auf ein Element (oder auch gar keins) und nicht mehrere. Du willst aber mehrere Elemente testen und genau das macht count_if . Es durchsucht alle Elemente zwischen first und last ( last nicht mit eingeschlossen). Der dritte Parameter ist dann was überhaupt gesucht wird. In deinem Fall ist das eine Lambda Funktion die prüft ob der Wert gleich 2 ist und den Key unberücksichtigt lässt.

    Sonne55 schrieb:

    ... habe übrigens yosemite Xcode 6.1.1 ist das schon 14, oder noch 11?

    Keine Ahnung. Probier doch einfach aus obs compiliert.



  • Danke, ich dachte fälschlicherweise first und last sind die beiden einanderzugeordnteten int von map.

    Jetzt müssten wir nur noch klären, warum er nicht zählt sondern imer eine Null ausgibt.... ich will nämlich in einem weiteren Schritt first und last noch dynamisieren. Kann ich mit denen rechnen? Drinne sein in map tut ja was, denn er druckt es ja aus ....

    #include <iostream>
    #include <stdio.h>
    #include <cmath>
    #include <map>
    using namespace std;
    
    int pzz=1; //Primzahlzähler
    int vfz=1; //Vielfachenzähler
    int ruz=1; //Rundenzähler
    
    int main()
    {
        map <int,int> prufzahlen;
        map<int,int>::iterator iter;
        int x, i;
        for (x = 31; x <= 1200; x=x+30)
        {
            ruz++;
            for (i = 2; i < x; i++)
            {
                if (x%i == 0)
                    break;
                //cout<<i<<"= i \n";
            }
    
            if (i == x)
            {
                cout<<"Nr. "<<ruz<<" "<<x<<" = "<<pzz<<". Pz. \n";
                pzz++;
                 prufzahlen.insert(pair<int, int>(x, 1));
            }
            else
            {
                cout<<"Nr. "<<ruz<<" "<<x<<" = "<<vfz<<". uVf. \n";
                vfz++;
                prufzahlen.insert(pair<int, int>(x, 2));
            }
    
            for (iter = prufzahlen.begin(); iter != prufzahlen.end(); iter++)
                    {
                    cout << iter->first << " ";
                    cout << iter->second << " ";
                    cout << endl;
    
                    }
            std::cout << "Kette hat " << prufzahlen.size() << " Zahlen"<<'\n';
    
            auto first = prufzahlen.lower_bound(1);// erstes Element:
            auto last  = prufzahlen.lower_bound(20); // "eins hinter das letzte Element"
            auto is_2 = [](const map<int,int>::value_type& p){return p.second==2; };// ob es 2 sind?
    
            // das eigentliche zaehlen:
            auto n = count_if(first, last, is_2);
            cout << n << endl;
    
        }
        return 0;
    }
    


  • Sonne55 schrieb:

    Jetzt müssten wir nur noch klären, warum er nicht zählt sondern imer eine Null ausgibt.... ich will nämlich in einem weiteren Schritt first und last noch dynamisieren. Kann ich mit denen rechnen?

    Du durchsuchst nur Werte mit Key zwischen 1 und 20. Dein kleinster Key ist aber 31 also zählt er natürlich auch nichts. Mit first und last kannst du nicht rechnen. Du kannst aber mit den Zahlen rechnen die du in lower_bound einsetzt.

    Noch eine Anmerkung zum Code: Sollte deine for (x = 31; x <= 1200; x=x+30) Schleife nicht nach dem else enden? Jetzt kommt die komplette Ausgabe nach jedem Element das hinzugefügt wird.



  • sebi707 schrieb:

    Du durchsuchst nur Werte mit Key zwischen 1 und 20. Dein kleinster Key ist aber 31 also zählt er natürlich auch nichts. Mit first und last kannst du nicht rechnen. Du kannst aber mit den Zahlen rechnen die du in lower_bound einsetzt.

    aha ... ich dachte 1 und 20 sind vom 1. bis zum 20. Wertepaar. .... Kann man in Maps die Wertepaare nicht einzeln ansteuern?

    sebi707 schrieb:

    Noch eine Anmerkung zum Code: Sollte deine for (x = 31; x <= 1200; x=x+30) Schleife nicht nach dem else enden? Jetzt kommt die komplette Ausgabe nach jedem Element das hinzugefügt wird.

    Ja, das ist zur Prüfung. Wenn ich nachher richtige Zahlen einsetzte, wird das wegkommentiert.



  • Vielleicht erklärst du nochmal was du überhaupt willst. In deiner ersten Frage redest du von "Wertebereich von 10 bis 20". Darunter habe ich verstanden, dass du den Bereich der Keys einschränken willst auf den Bereich von 10 bis 20. Jetzt willst du aber das 10. bis 20. Wertepaar, egal welchen Key Bereich das abdeckt? Das ist mit einer std::map leider nicht wirklich effizient zu machen. Warum hast du dich überhaupt für eine map entschieden? Im bisher gezeigten Code hätte auch ein vector gereicht.



  • Wat ik will is...

    Er soll jetzt von der ersten Häfte der Zahlenkette mir die Abzagl der PZ ausgeben und von der zweiten Hälfte die Anzahl der Vielfachen.

    Er soll also von 1 - X/2 die Einsen Zählen und von X/2 bis X+1 die Zweien.

    Leider macht er das nicht, weil man den count if Befehl wohl nicht zwei mal hintereinander anwenden kann...

    #include <iostream>
    #include <stdio.h>
    #include <cmath>
    #include <map>
    using namespace std;
    
    int pzz=1; //Primzahlzähler
    int vfz=1; //Vielfachenzähler
    int ruz=1; //Rundenzähler
    
    int main()
    {
        map <int,int> prufzahlen;
        map<int,int>::iterator iter;
        int x, i;
        for (x = 31; x <= 1200; x=x+30)
        {
            ruz++;
            for (i = 2; i < x; i++)
            {
                if (x%i == 0)
                    break;
                //cout<<i<<"= i \n";
            }
    
            if (i == x)
            {
                cout<<"Nr. "<<ruz<<" "<<x<<" = "<<pzz<<". Pz. \n";
                pzz++;
                 prufzahlen.insert(pair<int, int>(x, 1));
            }
            else
            {
                cout<<"Nr. "<<ruz<<" "<<x<<" = "<<vfz<<". uVf. \n";
                vfz++;
                prufzahlen.insert(pair<int, int>(x, 2));
            }
    
            for (iter = prufzahlen.begin(); iter != prufzahlen.end(); iter++)
                    {
                    cout << iter->first << " ";
                    cout << iter->second << " ";
                    cout << endl;
    
                    }
            std::cout << "Kette hat " << prufzahlen.size()+1 << " Glieder"<<'\n';
    
            auto first = prufzahlen.lower_bound(1);// erstes Element:
            auto last  = prufzahlen.lower_bound((x/2)+1); // "eins hinter das letzte Element"
            auto is_1 = [](const map<int,int>::value_type& p){return p.first==1; };// ob es 1 sind?
            // das eigentliche zaehlen:
            auto n = count_if(first, last, is_1);
            cout<<"davon unten "<< n <<" PZ"<< endl;
    
            auto first = prufzahlen.lower_bound(x/2);
            auto last  = prufzahlen.lower_bound(x+1);
            auto is_2 = [](const map<int,int>::value_type& p){return p.second==2; };
            auto nx = count_if(first, last, is_2);
            cout<<"davon "<< nx <<" Vf"<< endl;
    
        }
        return 0;
    }
    

    Er sagt immer Redefinition of last and first, naja mussick ja, wenn ich was andret will, dat er zehlen soll...

    Also bei map kann man 2 Zahlen miteinander verkoppeln. Gibt es auch einen Contener, wo man 3 Zahlen miteinander verkoppeln kann?



  • Sonne55 schrieb:

    Leider macht er das nicht, weil man den count if Befehl wohl nicht zwei mal hintereinander anwenden kann...

    Wie kommst du auf solche Schlussfolgerungen? Eine Funktion die man nur einmal aufrufen kann ist reichlich sinnlos. Les doch lieber mal die Fehlermeldungen und versuche diese zu verstehen! Die Fehlermeldung wegen Redefinition von first und last liegt daran, dass du beide Variablen zweimal definierst. Nach der ersten Definition darfst du diese nicht erneut definieren. Du kannst aber den bereits vorhandenen Variablen einfach einen neuen Wert zuweisen:

    first = prufzahlen.lower_bound(x/2);
    last  = prufzahlen.lower_bound(x+1);
    

    Das geht natürlich nur wenn die Typen übereinstimmen aber hier speichern wir ja in beiden Fällen Iteratoren in eine std::map<int, int> also passt das.

    Sonne55 schrieb:

    Also bei map kann man 2 Zahlen miteinander verkoppeln. Gibt es auch einen Contener, wo man 3 Zahlen miteinander verkoppeln kann?

    Wie verstehst du verkoppeln? Verkoppeln heißt hier, dass es einen Schlüssel/Key und Werte gibt und man eine feste Zuordnung von einem Key zu einem Wert hat. In deinem Code nutzt du aber das bisher noch nicht. Wenn du einfach nur zwei oder mehr Werte speichern willst geht das auch in einem vector :

    std::vector<std::pair<int, int>> x; // vector von int Paaren
    std::vector<std::tuple<int, int, float>> y; // vector von 2 ints und einem float
    

    Bei pair kann man immer zwei Werte kombinieren und bei tuple beliebig viele. Aber jetzt gibts natürlich keinen Zusammenhang zwischen den einzelnen Werten wie bei einer map .



  • sebi707 schrieb:

    In deinem Code nutzt du aber das bisher noch nicht.

    Doch doch, sebi707, 1 repräsentiert PZ und 2 Vf, die dürfen nicht verrücken. Das ist eine feste Zuordnung.

    Ich hätte die beiden, also PZ und VF noch gern numeriert.

    Vielen Dank für die Ausführungen ....



  • Ich habs jetzt so gemacht, einfach neuen Variablen creiert. Elegant ist das nicht, und er zählt unten auch nicht. Mir ist auch nicht deutlich, warum das nach dem Weglassen der beiden "auto" funktioniert.

    #include <iostream>
    #include <stdio.h>
    #include <cmath>
    #include <map>
    using namespace std;
    
    int pzz=1; //Primzahlzähler
    int vfz=1; //Vielfachenzähler
    int ruz=1; //Rundenzähler
    
    int main()
    {
        map <int,int> prufzahlen;
        map<int,int>::iterator iter;
        int x, i;
        for (x = 31; x <= 1200; x=x+30)
        {
            ruz++;
            for (i = 2; i < x; i++)
            {
                if (x%i == 0)
                    break;
                //cout<<i<<"= i \n";
            }
    
            if (i == x)
            {
                cout<<"Nr. "<<ruz<<" "<<x<<" = "<<pzz<<". Pz. \n";
                pzz++;
                 prufzahlen.insert(pair<int, int>(x, 1));
            }
            else
            {
                cout<<"Nr. "<<ruz<<" "<<x<<" = "<<vfz<<". uVf. \n";
                vfz++;
                prufzahlen.insert(pair<int, int>(x, 2));
            }
    
           for (iter = prufzahlen.begin(); iter != prufzahlen.end(); iter++)
                    {
               //     cout << iter->first << " ";
                 //   cout << iter->second << " ";
                   // cout << endl;
    
                    }
            std::cout << "Kettelänge= " << prufzahlen.size()+1 << " "<<'\n';
            double helfte=x/2;
            cout<<"Hälfte "<<helfte<<"\n";
            int a=1;
            int b=helfte;
            auto first = prufzahlen.lower_bound(a);// erstes Element:
            auto last  = prufzahlen.lower_bound(b); // "eins hinter das letzte Element"
            auto is_1 = [](const map<int,int>::value_type& p){return p.first==1; };
            // das eigentliche zaehlen:
            auto n = count_if(first, last, is_1);
            cout<<"davon unten "<< n <<" PZ"<< endl;
    
            a=helfte;
            b=x+1;
    
            first = prufzahlen.lower_bound(a);
            last  = prufzahlen.lower_bound(b);
            auto is_2 = [](const map<int,int>::value_type& p){return p.second==2; };
            auto nx = count_if(first, last, is_2);
            cout<<"davon oben "<< nx <<" Vf und "<<((ruz/2)- nx)<<" PZ"<< endl;      
        }
        return 0;
    }
    


  • Sonne55 schrieb:

    Mir ist auch nicht deutlich, warum das nach dem Weglassen der beiden "auto" funktioniert.

    Dort wo bei der Variablendefinition das auto steht, da steht ja normalerweise der Typ der Variable. Wenn ich das ganze mit ints schreibe wird es dir vielleicht klarer:

    int a = 1;
    int a = 2; // compiliert nicht, Neudefinition von a
    

    Wenn du schon eine int Variable mit dem Namen 'a' angelegt hast darfst du keine weitere anlegen wie dir vielleicht bekannt ist. Bei auto ist das nichts anderes außer, dass du den Typ der Variable nicht selbst hinschreibst.

    Sonne55 schrieb:

    Doch doch, sebi707, 1 repräsentiert PZ und 2 Vf, die dürfen nicht verrücken. Das ist eine feste Zuordnung.

    Die Paare bleiben auch beim vector zusammen. Der Vorteil bei einer map ist aber, dass man von dem Key (welcher einzigartig sein muss) schnell den dazugehörigen Wert erhalten kann. In deinem Fall könntest du also nachschauen ob eine Zahl y eine Primzahl oder ein Vielfaches ist indem du prüfst ob prufzahlen[y] gleich 1 oder 2 ist. Genau das machst du bisher aber noch nicht.



  • sebi707 schrieb:

    Wenn du schon eine int Variable mit dem Namen 'a' angelegt hast darfst du keine weitere anlegen wie dir vielleicht bekannt ist.

    Deshalb habe ich ja zuerst

    double helfte=x/2;
            cout<<"Hälfte "<<helfte<<"\n";
            int a=3;
            int b=helfte;
    

    geschrieben und dann nochmal ohne int

    a=helfte;
            b=x+1;
    

    um den Start und Stopwert zu ändern.

    Kann das sein, daß er die untere Reihe nicht zählt (es ist der erste Block), weil Helfte Double ist, map aber mit int int angelegt ist?

    Sonne55 schrieb:

    In deinem Fall könntest du also nachschauen ob eine Zahl y eine Primzahl oder ein Vielfaches ist indem du prüfst ob prufzahlen[y] gleich 1 oder 2 ist. Genau das machst du bisher aber noch nicht.

    Das kenn ich nicht, wie geht das?


Anmelden zum Antworten