Miniprog: Wer liefert schnellstes snippet :) -> anzahl gleicher zahlen in folge


  • Mod

    KasF schrieb:

    Die Methode von mir hatte ich mal von hier aufgeschnappt: http://www.cppreference.com/cppmap/all.html , nur bissl unsauber, da meine Indizes die Zahlen aus dem Array sind und somit jede Menge Stellen in der map leer sind, also 0 ausgegeben werde würde, wenn man durchiteriert. Aber die könnte man ja alle einfach noch entfernen, weiß aber im moment nicht wie ...

    Es soll ja ein Ergebnisarray werden, dann können wir kopieren und die Nullen gleichzeitig entfernen:

    std::vector<int> ergebnis;
    remove_copy(mappo.begin(),mappo.end(),back_inserter(ergebnis),0);
    


  • camper schrieb:

    std::vector<int> ergebnis;
    remove_copy(mappo.begin(),mappo.end(),back_inserter(ergebnis),0);
    

    Mit remove etc. bin ich mich ja die ganze Zeit am rumschlagen. Wenn remove den Iterator dereferenziert kommt ja ein pair<> dabei raus und der kann nicht einfach mit 0 verglichen werden. Man könnte das mit Funktionsobjekten etc. ausbauen, damit es funkitoniert, aber wäre keine EinZeilenLösung, so wie es sonst funktioniert: ( Kann sein das ich mich mit dem geschriebenen irren könnte ).

    Komischerweise werden die 0'en nur bei normalen indiziertem iterieren angezeigt nicht wenn ich über Iteratoren gehe:

    for(map<int,int>::iterator it = mappo.begin(); it != mappo.end(); ++it)
        cout << it->second;
    //2325
    
    for(int i=0; i<mappo.size(); ++i)
            cout <<mappo[i];
    //023205
    

    Ein neues Phänomen für mich 🙂


  • Mod

    KasF schrieb:

    Wenn remove den Iterator dereferenziert kommt ja ein pair<> dabei raus und der kann nicht einfach mit 0 verglichen werden.

    Stimmt - hab ich geschlafen.

    KasF schrieb:

    Komischerweise werden die 0'en nur bei normalen indiziertem iterieren angezeigt nicht wenn ich über Iteratoren gehe:

    Ein neues Phänomen für mich 🙂

    Weil mappo[0] erst in deiner Schleife angelegt wird 😉



  • KasF schrieb:

    nur bissl unsauber, da meine Indizes die Zahlen aus dem Array sind und somit jede Menge Stellen in der map leer sind, also 0 ausgegeben werde würde, wenn man durchiteriert.

    Äh, nein. Du musst einfach nur mit den Map-Iteratoren durchgehen, nicht mappo[index] .



  • camper schrieb:

    Weil mappo[0] erst in deiner Schleife angelegt wird 😉

    Ahhhhhhhhh 🙂 (oh man)

    Wieso funktioniert das denn nicht:

    pair<int,int> eraser(0,0);
    remove_copy(mappo.begin(),mappo.end(),back_inserter(ergebnis),eraser);
    

    Macht zwar keinen Sinn, da ja beide Paar-Objekte gleich sein müssen, aber trotzdem.

    stl_algo:remove_copy(...)
    if (!(*__first == __value))
    /*
    error: no match for 'operator==' in '(&__first)->std::_Rb_tree_iterator<_Tp>::operator* [with _Tp = std::pair<const int, int>]() == __value'
    */
    

    😕
    Liefert *__first kein pair<int,int> zurück ?

    Edit: Ja finix, der Groschen ist soeben gefallen.



  • camper schrieb:

    Es soll ja ein Ergebnisarray werden, dann können wir kopieren und die Nullen gleichzeitig entfernen:

    std::vector<int> ergebnis;
    remove_copy(mappo.begin(),mappo.end(),back_inserter(ergebnis),0);
    

    Wie wär's mit

    std::vector<int> result(result_size); // result_size laut Aufgabenstellung bekannt
    transform(mappo.begin(),
              mappo.end(),
              result.begin(), // edit: statt c&p-Fehler "back_inserter(result)",
              select2nd<map<int, int>::value_type>());
    

    Edit:

    KasF schrieb:

    Edit: Ja finix, der Groschen ist soeben gefallen.

    Hehe, ja ich seh's. Sollte mir echt angewöhnen meine Tabs hin und wieder zu refreshen 😞



  • Die Anzahl gleicher Zahlen (Thread Text) oder gleicher Zahlen in Folge (Thread Titel)?
    Die Anzahl gleicher Zahlen in Folge ist trivial und geht ungefähr so:

    void lala(int const* in, size_t size, int* out)
    {
        for (size_t i = 1; i < size; i++)
        {
            (*out)++;
            if (in[i] != in[i-1])
                out++;
        }
    }
    


  • @hustbaer: da stimmt noch was mim letzten index nicht....also bei der berechnung der letzten gleichen zahlen....ich schau gerade...



  • hustbaer hat halt vorher nicht sortiert 🤡



  • 😕 WAS?

    dann gehts doch erste recht nicht ...oder bin ich jetzt shcon ganz blind vor bäumen



  • achso.....er meint die anzahl gleicher zahlen in FOLGE....
    also sowas: 223322244 wäre 2232

    ich aber brauche halt: 522 weil 5 2er auftauchen 🙂



  • Das kürzeste was ich vom Code her hinbekomme, sieht so aus:

    void lala(int const* in, size_t size, int* out)
    {
        std::map<int,int> vals;
        for ( size_t i=0; i<size; i++ )
            ++ vals[ in[i] ];
        for ( map<int,int>::iterator iter=vals.begin(); iter!=vals.end(); iter++ )
            *(out++) = iter->second;
    }
    


  • also die version von hustbaer hat halt am ende des arrays ein problem weil er ja dann zu wenig zählt...ohne jetzt vorlaut sein zu wollen...

    Ich danke euch allen - aber ich wollte eigentlich nicht die Kürzeste version - sonder die schnellste 🙂

    aber scheint wohl einher zu gehen....



  • @badestrand...du sortierst vorher nicht nicht wahr?

    ich revidiere gerade die aussage von vorhin dass das von hustbaer nicht stimmt....mein hirn nimmts als korrekt an - nur mein eingabe array zählt am ende zu wenig....ich muss noch mal drüberschauen 🙄 🙄



  • gast_xy schrieb:

    @badestrand...du sortierst vorher nicht nicht wahr?

    std::map sortiert automatisch, hab ich mir einfach zu eigen gemacht ...

    btw, hier meine "schnelle, aber lange" Version:

    void lala( int const* in, size_t in_size, int* out, size_t out_size )
    {
    	struct Duo
    	{
    		int key;
    		int value;
    
    		static void SwapElements( Duo* list, int first, int second )
    		{
    			Duo tmp = list[first];
    			list[first] = list[second];
    			list[second] = tmp;
    		}
    
    		static void Quicksort( int low, int high, Duo* list )
    		{
    			int top = low;
    			int bottom = high - 1;
    			int iPartitionIndex = 0;
    			int iPartitionValue = 0;
    			if ( low < high )
    			{
    				if ( high == (low+1) )
    				{
    					if ( list[low].key >= list[high].key )
    						SwapElements( list, high, low );
    				}
    				else
    				{
    					iPartitionIndex = static_cast<int>((low + high) / 2);
    					iPartitionValue = list[iPartitionIndex].key;
    					SwapElements( list, high, iPartitionIndex );
    					do
    					{
    						while ( (list[top].key<iPartitionValue) && (top<=bottom) )
    							++top;
    						while ( (list[bottom].key>=iPartitionValue) && (top <= bottom))
    							--bottom;
    						if ( top < bottom )
    							SwapElements( list, top, bottom );
    					} while ( top < bottom );
    					SwapElements( list, top, high );
    					Quicksort( low, top-1, list );
    					Quicksort( top+1, high, list );
    				}
    			}
    		}
    	};
    
    	int n = 0;
    	Duo* m = new Duo [ out_size ];
    
    	for ( size_t i=0; i<in_size; ++i )
    	{
    		bool found = false;
    		for ( int j=0; j<n; j++ )
    		{
    			if ( m[j].key == in[i] )
    			{
    				++m[j].value;
    				found = true;
    				break;
    			}
    		}
    		if ( ! found )
    		{
    			m[n].key = in[i];
    			m[n].value = 1;
    			++n;
    		}
    	}
    
    	Duo::Quicksort( 0, n-1, m );
    
    	for ( int i=0; i<n; ++i )
    		out[i] = m[i].value;
    
    	delete[] m;
    }
    


  • KasF schrieb:

    Liefert *__first kein pair<int,int> zurück ?

    Nein, ein pair<const int,int> 😉

    So funktioniert das dann aber auch nicht:

    map<int, int> mappo;
    std::vector< pair<const int,int> > ergebnis;
    
    mappo.insert(make_pair(4,5));
    
    pair<const int,int> eraser(4,5);
    remove_copy(mappo.begin(),mappo.end(),ergebnis.begin(),eraser);
    

    Kann jemand mit remove und ner map ein funkionierendes Beispiel posten.



  • @finix: Ich habs mal mit deinem select2nd probiert.

    template<class T>
    struct select2nd
    {
        typename T::second_type operator()( const T& val )
        {
            return val.second;
        }
    };
    
    int main()
    {
    
        map<int, int> mappo;
    
        mappo.insert(make_pair(4,5));
    
        std::vector<int> result;
        transform(mappo.begin(), mappo.end(), result.begin(), select2nd<map<int, int>::value_type>() );
    
        copy(result.begin(),result.end(),ostream_iterator<int>(cout));
    
    }
    

    "..hat ein Problem festgestellt und muss beendet werden" ???
    Wo ist mein Fehler ?

    Edit: Oh man, ich schreibe in irgendeinen Speicher.

    back_inserter(result);
    //oder
    std::vector<int> result(mappo.size());
    

    schafft natürlich Abhilfe.



  • int main(int argc, char* argv[])
    {
       int a[] = { 1,1,2,2,2,3,3,5,5,5,5,5 };
       const int num = sizeof(a)/sizeof(int);
       set <int> nr;
       for(int i=0;i<num;i++) nr.insert(a[i]);
       for(set <int>::iterator it=nr.begin();it!=nr.end();it++) cout << count(a,a+num,*it);
       return 0;
    }
    


  • Normales remove sollte also überhaupt nicht funktionieren mit ner map:

    http://www.sgi.com/tech/stl/Map.html schrieb:

    [1] Map::iterator is not a mutable iterator, because map::value_type is not Assignable. That is, if i is of type map::iterator and p is of type map::value_type, then *i = p is not a valid expression. However, map::iterator isn't a constant iterator either, because it can be used to modify the object that it points to. Using the same notation as above, (*i).second = p.second is a valid expression. The same point applies to map::reverse_iterator.

    Eine remove_copy müsste dennoch irgendwie funktionieren, da die map ( bzw. dessen Iterator ) ja nicht modifiziert wird.



  • gast_xy schrieb:

    also die version von hustbaer hat halt am ende des arrays ein problem weil er ja dann zu wenig zählt...ohne jetzt vorlaut sein zu wollen...

    Ja, du hast Recht. Doofer Fehler aber auch. So müsste passen:

    void lala(int const* in, size_t size, int* out) 
    { 
        (*out)++; 
        for (size_t i = 1; i < size; i++) 
        { 
            if (in[i] != in[i-1]) 
                out++; 
            (*out)++; 
        } 
    }
    

    Die schnellste Version von "dem Anderen" (-> 522 statt 2232) wäre IMHO über eine hash-map zu erreichen. Damit kommst du auch auf O(N), vorausgesetzt die Map ist gross genug. Wenn die hash-map allerdings ZU gross wird wird das Anlegen/Auslesen/Freigeben wieder grob aufwändig, womit sich der tolle O(N) Vorteil wieder atomisiert. Könnte also leicht sein dass eine O(N log N) Lösung absolut gesehen (für realistische N) besser ist als die O(N) Lösung namens "hash-map".

    Macht übrigens denke ich auch einen Unterschied ob du für 992299333 als Output 423 (erstes Vorkommen zuerst) oder 234 (niedrigstes Element zuerst) brauchst (oder ob beides akzeptabel ist).


Anmelden zum Antworten