Schwierige Aufgabe :(?
-
Hallo Leute, ich bin zum ersten mal hier im Forum,
obwohl ich öfters hier war und als stiller Leser herumgeisterte
).
Ich habe folgendes Problem dem ich nicht gewachsen bin.
Also ich habe eine Liste mit Zahlenreihen erstellt (etwa 1 Million davon als .txt gespeichert..kann man aber aendern
).Jede davon besteht
aus 10 Zahlen(Jede der Zahlen liegt im Bereich 1-100 und werden durch Kommas getrennt) ...nennen wir diese Liste z.B Liste A ...dann habe ich noch eine zweite Liste(Liste
sie besteht aus 20 Zahlenrheien (Je 9+1 Zahlen von 1-100 wieder durch Kommas getrennt)die man beliebig verändern kann.
Nun soll man jede Zahl aus Liste B veraendern können(von mir aus mit Texteditor
)
Das Programm Soll nun die Zusatzzahl(die letzte Zahl in Jeder Reihe der Liste B nehmen) Es kann sich dabei nur um 1,2 oder 3 handeln ,handelt es sich dabei z.B um eine 3 Soll Jede Zahlenreihe aus Liste A gelöscht werden bei der 3 oder Mehr Zahlen mit der Zahlenrheie aus Liste B ist identisch sind.Ist die Zahl eine "2" sollen alle Reihen aus Liste A verschwinden die 2 gleiche Zahlen haben wie die Reihe aus Liste B
die Rheinen aus Liste B sollen nun so nacheinander gelesen werden und die Liste A sollte immer kleiner werden.
hmm...ich hoffe es hat Jemand verstanden was ich meine wenn nicht: fragt mich ruhig .Ich habe ein Programm entwickelt das diese Reihen schreibt aber ich habe keinen Plan was ich machen soll damit es die Liste nach dem oben genannten Verfahren aussortiert...(ich mach mir keine Sorgen um meine rechenleistung)
Sonstiges:
Ich programmiere seit kurzem mit VC++
Ich bedanke mich schon dafür das ihr soweit gelesen habt
hier noch ein Bild www.dftx.de/sys11.bmp damit ihr es besser euch vorstellen könnt...Hat jemand eine Idee wie man es realisieren könnte ?
Danke für Tipps, Lösungen oder Lösungsvorschläge im Vor-raus.
Und danach natürlich auch :D.
-
Hallo Misha,
Meinst Du sowas:
#include <iostream> #include <vector> #include <algorithm> // remove_if, find_if #include <utility> // std::pair typedef std::vector< int > Reihe; typedef std::pair< std::vector< int >, int > ReiheZ; struct Matched { explicit Matched( const Reihe& ra ) : m_ra( ra ) {} bool operator()( const ReiheZ& rb ) const { // Prüfen ob Reihe(Z) aus B mit Zusatzzahl zu 'm_ra' passt int cnt = 0; Reihe::const_iterator ia = m_ra.begin(); for( Reihe::const_iterator ib = rb.first.begin(); ib != rb.first.end(); ++ib, ++ia ) { if( *ia == *ib && ++cnt >= rb.second ) return true; // mindestens rb.second Zahlen aus m_ra sind gleich } return false; } private: Reihe m_ra; }; struct Entscheider { explicit Entscheider( const std::vector< ReiheZ >& b ) : m_b( &b ) {} bool operator()( const Reihe& r_aus_a ) const { // true; falls irgendeine Reihe aus B die aktuelle Reihe aus A löscht return find_if( m_b->begin(), m_b->end(), Matched( r_aus_a ) ) != m_b->end(); } private: const std::vector< ReiheZ >* m_b; }; int main() { using namespace std; std::vector< Reihe > a; std::vector< ReiheZ > b; // Listen a und b füllen a.erase( remove_if( a.begin(), a.end(), Entscheider( b ) ), a.end() ); return 0; }Wann eine Reihe aus B zu einer aus A passt, habe ich nicht ganz verstanden. Deine Beschreibung scheint sich mit der aus dem Bild zu widersprechen? Ich habe mal angenommen wenn Ne{1,2,3} Zahlen aus beiden Reihen übereinstimmen, die auch an der selben Position stehen (s. Matched::operator()).
Gruß
Werner
-
Danke für die schnelle Antwort zur solch später Stunde.
Nein,Die Position ist egal nur die Reihe nicht...
-
Misha schrieb:
Danke für die schnelle Antwort zur solch später Stunde.
Nein,Die Position ist egal nur die Reihe nicht...ja, dann musst Du Matched::operator() noch anpassen. Ich geh' jetzt in's Bett!
Gute Nacht :xmas1:
-
Werner Salomon schrieb:
Misha schrieb:
Danke für die schnelle Antwort zur solch später Stunde.
Nein,Die Position ist egal nur die Reihe nicht...ja, dann musst Du Matched::operator() noch anpassen. Ich geh' jetzt in's Bett!
Gute Nacht :xmas1:
Edit:
Das heist :Wenn X oder mehr Zahlen aus Liste B Reihe 1 zur Liste A reihe 1 passen soll diese Reihe(Liste A Reihe 1) gelöscht werden, dann wird mit Liste B reihe 1 bei Liste A reihe 2 weiter gemacht, ist die Liste A durch ,so wird Liste B reihe 2 vorgenommen...
-
...hmm eh länger ich dies angucke desto weniger verstehe ich das Pragramm, könntest du vielleicht es so kommentieren das auch ein Misha das versteht?
Ich habe bisschen gegoogelt und nachgeschlagen aber mein Kopf ist zu klein für so viele neue Funktionen...hab kein plan wie ich jetzt die Listen in a und b reinbekommen kann
meine textdateien sind so geschrieben worden
12,15,11,83,26,83,44,18,58,54,
51,64,1,35,67,21,83,77,11,56,
.....(also immer 10 Zahlen von einem Komma getrennt)
Ich dachte mir man könnte Irgendwie immer 10 Zahlen nehmen und den Umbruch weglassen ...
habs in BASIC erstellt falls ein anderes Verfahren zur Speicherung von Zahlen für das obig genannte Beispiel sich besser eignet...höre ich zu.
Danke nochmal, ihr seid echt Freaks um Mitternacht noch in Foren zu sitzen
...also meine Frage:Wie kann mann 2 Listen voller Zahlen (in .txt) die nur Durch Kommas getrennt sind in den obigen Lösungsvorschlag von Werner Solomon reinbringen,
Es ist so das eine Reihe immer aus 10 Zahlen Besteht
Danke im Vor-raus
-
Misha schrieb:
...hmm eh länger ich dies angucke desto weniger verstehe ich das Pragramm, könntest du vielleicht es so kommentieren das auch ein Misha das versteht?
Da wir Misha nicht kennen, weiß auch niemand wo man mit dem Erklären anfangen soll. Es wäre extrem hilfreich, wenn Du konkrete Fragen stellst.
Misha schrieb:
.. hab kein plan wie ich jetzt die Listen in a und b reinbekommen kann

meine textdateien sind so geschrieben worden
12,15,11,83,26,83,44,18,58,54,
51,64,1,35,67,21,83,77,11,56,
.....(also immer 10 Zahlen von einem Komma getrennt)Ok, das ist 'ne einigermaßen konkrete Frage.
Erstmal vorneweg eine Bemerkung. Diese Kommas machen immer nur Arbeit. Ich weiß nicht wer sich sowas ausdenkt; es wäre sehr viel einfacher die Zahlen einfach durch Leerzeichen und/oder Zeilenumbruch zu trennen.
Einlesen geht so
#include <iostream> #include <fstream> #include <vector> #include <algorithm> // remove_if, find_if #include <utility> // std::pair typedef std::vector< int > Reihe; typedef std::pair< std::vector< int >, int > ReiheZ; // -- folgendes Graffi ist nur für das trennende Komma const int KOMMA_FLAG = std::ios_base::xalloc(); std::istream& komma( std::istream& in ) { if( in.iword( KOMMA_FLAG ) ) { char k; if( in >> k && k != ',' ) in.setstate( std::ios_base::failbit ); } else { in.iword( KOMMA_FLAG ) = 1; } return in; } std::istream& start_reading( std::istream& in ) { in.iword( KOMMA_FLAG ) = 0; return in; } // -- jetzt kommt das Einlesen einer Reihe mit 10 Zahlen namespace std // das ist beim VC-Compiler notwendig, da er den namespace lookup nicht korrekt beherrscht { std::istream& operator>>( std::istream& in, Reihe& r_ ) { Reihe r( 10 ); for( Reihe::iterator i = r.begin(); i != r.end(); ++i ) { in >> komma >> *i; } if( in ) r.swap( r_ ); return in; } // -- und hier das Einlesen der Reihe mit Zusatzzahl std::istream& operator>>( std::istream& in, ReiheZ& rz ) { Reihe r( 10 ); for( Reihe::iterator i = r.begin(); i != r.end(); ++i ) { in >> komma >> *i; } if( in >> komma >> rz.second ) r.swap( rz.first ); return in; } } int main() { using namespace std; std::vector< Reihe > a; std::vector< ReiheZ > b; { ifstream datei( "A.txt" ); copy( istream_iterator< Reihe >( datei ), istream_iterator< Reihe >(), back_inserter( a ) ); } { ifstream datei( "B.txt" ); copy( istream_iterator< ReiheZ >( datei ), istream_iterator< ReiheZ >(), back_inserter( b ) ); } // usw. return 0; }Misha schrieb:
Danke nochmal, ihr seid echt Freaks um Mitternacht noch in Foren zu sitzen

.. sonst habe ich ja keine Zeit für sowas

Gruß
Werner
-
Danke,Danke, Danke das du mich nicht vergessen hast.(hab sogar versucht den Thread zu Pushen ^^,geht leider nicht,er ist festgewachsen)
So und jetzt kommt die traurige Wahrheit:
Ich hab nicht den geringsten Peil
Wenn ich deinen Code lese macht es einfach keinen *Klick* im meinem Kopf
und die Suche nach den einzelnen Begriffen(was sie bringen usw.)hat mir nur noch mehr Kopfschmerzen bereitet.
Ich habe deine beide Codeteile irgendwie zusammengebaut(besser gesagt : "geschändet" )
Aber ich bin mir 100% sicher das ich das falsch gemacht hab:
Ich schätze deine Bemühungen sehr, aber dein C++ ist zu hoch für meinen Kopf,
(eigentlich C++ im allgemeinem,ader das wird mir erst jetzt klar)
Darum meine Bitte: Könntest du mir bitte,bitte den GANZEN Code aufschreiben?
Folgende Änderungen wurden an den Listen vorgenommen:
Die Zahlen sind jezt durch Leerzeichen getrennt und die Reihen durch Umbrüche
so etwa:
1 2 3 4 5 6 7 8 9 0
1 2 3 4 5 6 7 8 9 0
Es sind immernoch immer 10 Zahlen pro Reihe
Sorry nochmal für die Umstände aber ich bin mehr ein Plankton als ein Homo Sapiens Sapiens.
Ich will jetz blos das ganze hinter mich bringen und wieder mit dem Thema anfangen wenn ich C++ einigermaßen beherrsche.~absolute ultra low skilled beginner alias: Misha
-
Hallo Misha,
ich hab' im Augenblick kein Zeit. Ich werde versuchen Dir innerhalb der nächsten Woche zu antworten.
Gruß
Werner
-
OK,danke, kein Problem, ich warte.
-
Misha schrieb:
Ich hab nicht den geringsten Peil

Wenn ich deinen Code lese macht es einfach keinen *Klick* im meinem Kopf
und die Suche nach den einzelnen Begriffen(was sie bringen usw.)hat mir nur noch mehr Kopfschmerzen bereitet.Hallo Misha,
ich kann mich nur wiederholen: Stelle konkrete Fragen; meinetwegen auch zu einzelnen Programmzeilen. Abgesehen davon; wenn Du nicht 'den geringsten Peil' hast, wie kommst Du dann zu so einem - keineswegs trivialen - Programmier-Problem? Du solltest Dich mindestens mit der Anwendung des Containers vector<> aus der STL und rudimentärem IO in C++ auskennen, um das zu lösen.
Misha schrieb:
Ich habe deine beide Codeteile irgendwie zusammengebaut(besser gesagt : "geschändet" )
Aber ich bin mir 100% sicher das ich das falsch gemacht hab:Funktioniert es denn? Falls nicht, wo liegt das Problem? Auch hier würden Dich konkrete Angaben von Deiner Seite weiterbringen. In welcher Programmier-Umgebung arbeitest Du?
Misha schrieb:
Darum meine Bitte: Könntest du mir bitte,bitte den GANZEN Code aufschreiben?
Kommt hier:
#include <iostream> #include <fstream> #include <vector> #include <algorithm> // remove_if, copy, find_if #include <iterator> // std::o/istream_iterator<> class Reihe // dass ist eine Reihe mit 10 Zahlen { public: static const int ANZ = 10; // falls das nicht compiliert nehme: enum { ANZ = 10 }; typedef const int* const_iterator; const_iterator begin() const { return m_zahlen; } const_iterator end() const { return m_zahlen + ANZ; } friend std::istream& operator>>( std::istream& in, Reihe& r ) { // lese ANZ Zahlen nach r.m_zahlen[] for( int i = 0; i < ANZ; ++i ) in >> r.m_zahlen[i]; return in; } friend std::ostream& operator<<( std::ostream& out, const Reihe& r ) { // Ausgabe aller Zahlen der Reihe nach 'out' mit " " getrennt std::copy( r.begin(), r.end(), std::ostream_iterator< int >( out, " " ) ); return out; } private: int m_zahlen[ANZ]; }; class ReiheZ // das ist eine Reihe mit Zusatzzahl { public: typedef Reihe::const_iterator const_iterator; const_iterator begin() const { return m_reihe.begin(); } const_iterator end() const { return m_reihe.end(); } int N() const { return m_n; } friend std::istream& operator>>( std::istream& in, ReiheZ& rz ) { // Einlesen einer Reihe 'rz.m_reihe' und Zusatzzahl 'rz.m_n' return in >> rz.m_reihe >> rz.m_n; } private: Reihe m_reihe; int m_n; // Mindestanzahl der Zahlen, die in der zu prüfenden Reihe vorkommen müssen, um sie zu löschen }; struct Matched { explicit Matched( const Reihe& ra ) : m_ra( ra ) {} bool operator()( const ReiheZ& rb ) const { // Hier findet jetzt die Überprüfung statt, ob die Reihe, deren Kopie sich // in 'm_ra' befindet, gelöscht werden soll. // Das ist genau dann der Fall, wenn mindestens 'rb.N()' Zahlen aus 'm_ra' // auch in 'rb' vorkommen. // In diesem Fall wird 'true' zurückgeliefert. int cnt = 0; for( Reihe::const_iterator ia = m_ra.begin(); ia != m_ra.end(); ++ia ) // alle Zahlen in m_ra { // kommt die Zahl '*ia' aus 'm_ra' in 'rb' vor? if( std::find( rb.begin(), rb.end(), *ia ) != rb.end() ) { // .. ja, die Zahl '*ia' wurde in 'rb' gefunden if( ++cnt >= rb.N() ) { // es wurden 'rb.N()' Zahlen aus 'm_ra' in 'rb' gefunden return true; } } } return false; } private: Reihe m_ra; }; struct Entscheider { explicit Entscheider( const std::vector< ReiheZ >& b ) : m_b( &b ) {} bool operator()( const Reihe& r_aus_a ) const { // true; falls irgendeine Reihe aus B die aktuelle Reihe 'r_aus_a' aus A löscht return std::find_if( m_b->begin(), m_b->end(), Matched( r_aus_a ) ) != m_b->end(); } private: const std::vector< ReiheZ >* m_b; }; int main() { using namespace std; const char* aName = "A.txt"; const char* bName = "B.txt"; const char* ergName = "Aneu.txt"; std::vector< Reihe > a; // alle Reihen std::vector< ReiheZ > b; // alle Reihen mit Zusatzzahl { ifstream datei( aName ); // Reihen einlesen und in Container 'a' speichern copy( istream_iterator< Reihe >( datei ), istream_iterator< Reihe >(), back_inserter( a ) ); cout << a.size() << " Reihen aus '" << aName << "' gelesen " << endl; } { ifstream datei( bName ); // Reihen mit Zusatzzahl einlesen und in Container 'b' speichern copy( istream_iterator< ReiheZ >( datei ), istream_iterator< ReiheZ >(), back_inserter( b ) ); cout << b.size() << " Reihen mit Zusatzzahl aus '" << bName << "' gelesen " << endl; } // alle Reihen aus 'a' entfernen, die dem Kriterium entsprechen a.erase( remove_if( a.begin(), a.end(), Entscheider( b ) ), a.end() ); ofstream erg( ergName ); // Ergebnis nach 'erg' schreiben; nach jeder Reihe ein 'newline' "\n" copy( a.begin(), a.end(), ostream_iterator< Reihe >( erg, "\n" ) ); cout << a.size() << " Reihen nach '" << ergName << "' geschrieben " << endl; return 0; }Wobei noch zu erwähnen ist, dass ich den Algorithmus dahingehend geändert habe, dass ich nur einmal über alle Reihen aus A laufe; das geschieht in
remove_if( a.begin(), a.end(), ...und dann für eine bestimmte Reihe aus A in allen Reihen aus B nachsehen ob eine passt. das geschieht hier
bool Entscheider::operator()( const Reihe& r_aus_a ) const { // true; falls irgendeine Reihe aus B die aktuelle Reihe 'r_aus_a' aus A löscht return find_if( m_b->begin(), m_b->end(), Matched( r_aus_a ) ) != m_b->end();Und ob eine Reihe passt (matched) oder nicht entscheidet sich in Matched (s.Code)
Weiter habe ich Reihe und ReiheZ als eigenständige Klassen definiert; das ist sauberer als die erste Lösung mit den typedefs.
Sei der Inhalt der Datei A.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60und von B.txt
1 2 3 11 12 13 99 99 99 99 3 51 62 99 99 99 99 99 99 99 99 1Dann erzeugt das Programm eine Datei Aneu.txt mit diesem Inhalt
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50Gruß
Werner
-
Es gibt noch eine Optimierungsmöglichkeit bei der main-Funktion. Misha wird's wohl nix nützen, aber vielleicht interessiert sich jemand dafür.
main() optimiert:
int main() { using namespace std; const char* aName = "A.txt"; const char* bName = "B.txt"; const char* ergName = "Aneu.txt"; vector< ReiheZ > b; // alle Reihen mit Zusatzzahl { ifstream datei( bName ); // Reihen mit Zusatzzahl einlesen und in Container 'b' speichern copy( istream_iterator< ReiheZ >( datei ), istream_iterator< ReiheZ >(), back_inserter( b ) ); cout << b.size() << " Reihen mit Zusatzzahl aus '" << bName << "' gelesen " << endl; } ifstream a( aName ); ofstream erg( ergName ); // alle Reihen aus 'a' entfernen, die dem Kriterium entsprechen, und Rest nach 'erg' abspeichern remove_copy_if( istream_iterator< Reihe >( a ), istream_iterator< Reihe >(), ostream_iterator< Reihe >( erg, "\n" ), Entscheider( b ) ); return 0; }Gruß
Werner
-
@Werner
In diesem Fall spielt es keine Rolle, aber wenn möglich sollte man die range-insert Methoden eines Containers dem copy-Algo vorziehen. In diesem Fall muss man dann noch auf "c++'s most vexing parse" achten:ifstream datei( bName ); // man beachte die Extraklammern vector< ReiheZ > b( (istream_iterator< ReiheZ >( datei )), istream_iterator< ReiheZ >()); // oder besser: istream_iterator< ReiheZ > beg( datei ); vector< ReiheZ > b( beg, istream_iterator< ReiheZ >());
-
HumeSikkins schrieb:
In diesem Fall spielt es keine Rolle, aber wenn möglich sollte man die range-insert Methoden eines Containers dem copy-Algo vorziehen.
Hallo Hume,
Wohl dem, der eine Umgebung hat, wo das auch kompiliert.

Ich bin immer noch etwas MS-VC6-verseucht. Aber Du hast völlig recht.Gruß
Werner
-
Werner Salomon schrieb:
Wohl dem, der eine Umgebung hat, wo das auch kompiliert.

Ich bin immer noch etwas MS-VC6-verseucht. Aber Du hast völlig recht.Ah, fehlende Member-Templates in der Standardlib-Impl. Gute alte Zeiten

Hier ist ausnahmsweise mal nicht die schwache Template-Unterstützung des VC6 schuld (der VC6 unerstützt Member-Templates, sofern sie innerhalb der Klassendefinition definiert werden), sondern die Tatsache, dass für den VC6 keine neue Version der Dinkumware-Library lizenziert wurde. Stattdessen wurde eine alte Version (bereits seit dem VC4 dabei???), ohne solche "fancy features", mitgeliefert.Hm, aber warum langweile ich dich eigentlich damit...

-
Danke Werner!vielen dank!