C++ Wortsuche



  • @hustbaer sagte in C++ Wortsuche:

    Genau so wie die "restartable" Suchfunktion nicht gefordert wurde und den Code unnötig kompliziert macht.

    Wie vermeidest Du doppelt und dreifach dasselbe zu finden?



  • @hustbaer sagte in C++ Wortsuche:

    Und die Optimierung ist nichtmal sinnvoll implementiert. Sinnvoller wäre es gleich die Start- und Endwerte der Schleifen anzupassen.

    ???



  • @Jockelx sagte in C++ Wortsuche:

    @hustbaer sagte in C++ Wortsuche:

    Das ist aber eine Optimierung

    Ja und? Darf ja auch eine sein. Die Optimierung ist aber nicht der Grund für die Änderung, sondern weil ich das anschaulicher finde. Ist das so schwer zu verstehen?

    Ja 🙂
    Also auf die Idee dass man das anschaulicher finden könnte wäre ich nicht gekommen. Und es sollte mMn. kein Grund sein es einzubauen. Wenn man es als Optimierung haben möchte, OK. Aber wenn einem die Optimierung egal ist, dann ist es ein Stück Code das genau keinen Sinn macht. Und Code der Teile enthält die keinen Sinn machen, finde ich persönlich nicht anschaulicher.



  • @Swordfish sagte in C++ Wortsuche:

    @hustbaer sagte in C++ Wortsuche:

    Genau so wie die "restartable" Suchfunktion nicht gefordert wurde und den Code unnötig kompliziert macht.

    Wie vermeidest Du doppelt und dreifach dasselbe zu finden?

    So:

    for each X
        for each Y
            for each word
                for each direction
                    if word starts here
                        print out word, pos, direction
    

    Wie soll da was doppelt oder dreifach gefunden werden?



  • @hustbaer Ok. 1:0. Darf mir meine Lösung trotzdem gefallen?



  • @Swordfish sagte in C++ Wortsuche:

    @hustbaer sagte in C++ Wortsuche:

    Und die Optimierung ist nichtmal sinnvoll implementiert. Sinnvoller wäre es gleich die Start- und Endwerte der Schleifen anzupassen.

    ???

    Wenn...

    • Meine Zeile 20 Zeichen lang ist
    • Das gesuchte Wort 10 Zeichen lang ist
    • Ich von Links nach Rechts suche

    Wieso sollte ich dann die Schleife von X=0 bis X=19 laufen lassen, und dann in der Schleife immer prüfen ob X <= 10 ist? Das macht doch keinen Sinn. Dann lass ich gleich die Schleife nur von 0...10 laufen.



  • @hustbaer Ist eben die Frage ob man vorher anhand der Suchrichtung entscheidet oder nachher.



  • @Swordfish sagte in C++ Wortsuche:

    @hustbaer Ok. 1:0. Darf mir meine Lösung trotzdem gefallen?

    Sicher. Ich hab doch nicht behauptet dass deine Lösung irgendwie besonders schlecht wäre. Also bis auf den Range-Check den man eben effizienter machen kann -- wenn man ihn schon unbedingt optimieren will.

    Ich sage nur man kann es viel einfacher machen wenn man einfach nur die Aufgabe machen möchte.



  • @hustbaer sagte in C++ Wortsuche:

    Also bis auf den Range-Check den man eben effizienter machen kann -- wenn man ihn schon unbedingt optimieren will.

    Kannst Du das bei mir mal einbauen, weil ehrlichgesagt stehe ich auf der Leitung.



  • @Swordfish sagte in C++ Wortsuche:

    @hustbaer Ist eben die Frage ob man vorher anhand der Suchrichtung entscheidet oder nachher.

    Richtig. OK, kann man so oder so machen. Was wirklich schneller ist müsste man vermutlich Benchmarken. Bei kleinen Matrizen die in den L1 passen vermutlich "meine" Variante. Bei grösseren ... keine Ahnung. Und wenn man wirklich optimieren will, muss man das sowieso nochmal ganz anders angehen.



  • @hustbaer sagte in C++ Wortsuche:

    Und wenn man wirklich optimieren will, muss man das sowieso nochmal ganz anders angehen.

    Optimal wäre wahrscheinlich "im Kreis" zu suchen:

        4
      3 X 1
        2
    


  • @Swordfish sagte in C++ Wortsuche:

    @hustbaer sagte in C++ Wortsuche:

    Also bis auf den Range-Check den man eben effizienter machen kann -- wenn man ihn schon unbedingt optimieren will.

    Kannst Du das bei mir mal einbauen, weil ehrlichgesagt stehe ich auf der Leitung.

    Ich könnte, aber ich bin grad zu faul. Aber falls es darum geht: Es stimmt schon dass man dazu die Verschachtelung ändern müsste. Also du machst Word->Pos->Direction und das funktioniert natürlich nur mit Word->Direction->Pos.



  • @hustbaer sagte in C++ Wortsuche:

    Ich könnte, aber ich bin grad zu faul.

    Den merk' ich mir. 😏



  • @Swordfish sagte in C++ Wortsuche:

    @hustbaer sagte in C++ Wortsuche:

    Und wenn man wirklich optimieren will, muss man das sowieso nochmal ganz anders angehen.

    Optimal wäre wahrscheinlich "im Kreis" zu suchen:

        4
      3 X 1
        2
    

    Glaub ich nicht. Ich denke eher sowas in der Art:

    check_h:
        for all rows
            for all possible start offsets
                for all words
                    check
    
    extend word list by adding all words > 1 character in reserve
    check_h
    transpose matrix
    check_h
    


  • @hustbaer Da sind mir zu viele Fremdwörter die ich nicht verstehe. Ich glaube aber auch daß Du nicht verstanden hast was ich mit

    @Swordfish sagte in C++ Wortsuche:

        4
      3 X 1
        2
    

    meinte.



  • @hustbaer sagte in C++ Wortsuche:

    transpose matrix

    Also den Input rumdrehen anstatt die Suchrichtung zu ändern?



  • @Swordfish
    Möglich dass ich es nicht genau verstanden habe. Aber ich bin mir trotzdem ziemlich sicher dass es langsamer sein wird als mein Vorschlag.

    Da sind mir zu viele Fremdwörter die ich nicht verstehe.

    1. Alle Wörter die länger als 1 Buchstabe sind nochmal rückwärts in die Wort-Liste aufnehmen. Dadurch können wir immer vorwärts suchen.
    2. Wir suchen immer horizontal, vorwärts. Also aus Speicher-Sicht immer in "+1" Richtung.
    3. Um dann vertikal suchen zu können spiegeln wir die Matrix an der Diagonale und suchen dann wieder horizontal.
      Alternativ kann man auch nur jeweils eine Spalte in einen kompakten Zwischenspeicher kopieren und dann in diesem suchen.

    Das ist viel günstiger was die Cache-Nutzung angeht. Wenn man nur nach einem Wort sucht, gewinnt man nichts damit. Aber wenn man nach mehr als einem Wort sucht, und die Matrix nicht mehr in den L1 Cache passt, dann gewinnt man dadurch einiges.

    Also den Input rumdrehen anstatt die Suchrichtung zu ändern?

    Ja, genau.

    ps:

    Alternativ kann man auch nur jeweils eine Spalte in einen kompakten Zwischenspeicher kopieren und dann in diesem suchen.

    Es würde mich aber nicht wundern wenn es effizienter wäre wirklich die ganze Matrix zu transponieren. Das kann man nämlich effizienter machen als wenn man Spalte für Spalte aus dem Speicher in einen Zwischenpuffer liest.



  • @hustbaer ja, das klingt schneller.



  • So richtig verstehe ich die Kritik an @Jockelx s Vorschlag nicht. Die Daten müssen nur einmal durchlaufen werden, daher ist das doch naheliegend.

    Nach den Vorschlägen hier habe ich mal ein wenig rumgespielt.
    Gesucht werden immer drei Wörter, die immer an der gleichen Position sind:
    https://i.imgur.com/kXg2tKe.png
    0, 0 →
    width-1, height/2 ←
    width/2, height-1 ↑

    Die MT-Varianten laufen in 4 Threads (auf meinem betagten i7 mit 4 physischen Kernen). Die erste Variante sucht parallel in jeweils einer Richtung, die zweite teilt die Daten in 4 gleich große Bereiche auf.

    50x50
    ---------------------------
    Nacheinander:
    0.000059
    alle Richtungen:
    0.000033
    MT:
    0.000235
    MT (alle Richtungen):
    0.000320
    
    100x100
    ---------------------------
    Nacheinander:
    0.000244
    alle Richtungen:
    0.000128
    MT:
    0.000349
    MT (alle Richtungen):
    0.000259
    
    500x500
    ---------------------------
    Nacheinander:
    0.006062
    alle Richtungen:
    0.003105
    MT:
    0.002605
    MT (alle Richtungen):
    0.001615
    
    1000x1000
    ---------------------------
    Nacheinander:
    0.026402
    alle Richtungen:
    0.012442
    MT:
    0.010958
    MT (alle Richtungen):
    0.005402
    
    10000x10000
    ---------------------------
    Nacheinander:
    6.184115
    alle Richtungen:
    1.142791
    MT:
    2.801702
    MT (alle Richtungen):
    0.439780
    
    20000x20000
    ---------------------------
    Nacheinander:
    24.657569
    alle Richtungen:
    4.531628
    MT:
    12.044550
    MT (alle Richtungen):
    1.557231
    
    30000x30000
    ---------------------------
    Nacheinander:
    61.878514
    alle Richtungen:
    10.184429
    MT:
    30.797580
    MT (alle Richtungen):
    3.935168
    

    50000x50000 habe ich abgebrochen.
    Und die Rotation habe ich zwar probiert, aber mögliche Vorteile wurden anscheinend durch die Rotation selber zunichte gemacht. Eine sinnvolle (eben auch einfache) MT-Lösung ist mir da leider nicht eingefallen.



  • Ich würde eher ersteinmal verschiedene Such-Funktionen je Dimension (horizontal, vertikal) erstellen.
    Und darauf aufbauend eine allgemeine (mit direction als Parameter), welche diese dann entsprechend aufruft.

    Wenn man eure Suchfunktion dann auch noch um diagonale Suche erweitern würde (wie man es von den "Wortsuche"-Rätseln in Kreuzworträtselheften kennt), würde der Code noch komplexer werden.


Anmelden zum Antworten