Feststellen ob Zeichenvorkommen übereinstimmen

Die Frage ist als "gelöst" markiert. Den entsprechend Beitrag findest du hier.

Getting started ... Alles für einen gelungenen Start.
22 Beiträge • Vorherige Seite 2 von 2 (current)
22 Beiträge Vorherige Seite 2 von 2 (current)

Re: Feststellen ob Zeichenvorkommen übereinstimmen

Beitrag von Nion (ForumUser / 17 / 20 / 1 ) »
So, ich habe es jetzt (nach längerer Zeit als ich zugeben möchte) mit DO, MOVE und REPLACE so gelöst bekommen :)

Code: Alles auswählen.

DATA:
  lv_laenge1 TYPE string,
  lv_laenge2 TYPE string,
  lv_schritt TYPE i,
  lv_dump    TYPE string,
  start      TYPE i.

PARAMETERS:
  Wort1 TYPE text,
  Wort2 TYPE text.

lv_laenge1 = strlen( wort1 ).
lv_laenge2 = strlen( wort2 ).
lv_schritt = start + 1.

IF lv_laenge1 = lv_laenge2.
  DO lv_laenge1 TIMES.
    lv_schritt = start + 1.
    IF lv_schritt < lv_laenge1.
      MOVE wort1+start(1) TO lv_dump.
      start = start + 1.
      FIND lv_dump IN wort2 IGNORING CASE.
      IF sy-subrc = 0.
        REPLACE lv_dump IN wort2 WITH '.'.
      ELSE.
        WRITE:/ 'Kein Anagramm'.
        RETURN.
      ENDIF.
    ELSE.
      EXIT.
    ENDIF.
  ENDDO.
  WRITE:/ 'Es ist ein Anagramm.'.
ELSE.
  WRITE:/ 'Eingaben müssen die gleiche Länge haben.'.
ENDIF.
Vielen Dank für die Tipps und ein schönes Wochenende,
Nion
Man muss nicht alles wissen. Man muss nur wissen, wo es steht oder wen man fragen kann.

gesponsert
Stellenangebote auf ABAPforum.com schalten
kostenfrei für Ausbildungsberufe und Werksstudenten


Re: Feststellen ob Zeichenvorkommen übereinstimmen

Beitrag von PeterPaletti (Specialist / 348 / 32 / 97 ) »
Hallo Nion,
ist schon ganz gut, aber leider nur ganz gut, denn es funktioniert noch nicht sauber. Deine Variable lv_schritt und die zugehörige IF-Abfrage führt dazu, dass das letzte Zeichen nicht überpüft wird: ROSE und ROST werden als Anagramm identifiziert.

Wenn du die ganze Logik mit lv_schritt auskommentierst funktioniert es wunderbar.

Code: Alles auswählen.

DATA:
  lv_laenge1 TYPE string,
  lv_laenge2 TYPE string,
*  lv_schritt TYPE i,
  lv_dump    TYPE string,
  start      TYPE i.

PARAMETERS:
  wort1 TYPE text,
  wort2 TYPE text.

lv_laenge1 = strlen( wort1 ).
lv_laenge2 = strlen( wort2 ).
*lv_schritt = start + 1.

IF lv_laenge1 = lv_laenge2.
  DO lv_laenge1 TIMES.
*   lv_schritt = start + 1.
*   IF lv_schritt < lv_laenge1.
      MOVE wort1+start(1) TO lv_dump.
      start = start + 1.
      FIND   lv_dump IN wort2 IGNORING CASE.
      IF sy-subrc = 0.
        REPLACE lv_dump IN wort2 WITH '.'.
      ELSE.
        WRITE:/ 'Kein Anagramm'.
        RETURN.
      ENDIF.
*    ELSE.
*     EXIT.
*    ENDIF.
  ENDDO.
  WRITE:/ 'Es ist ein Anagramm.'.
ELSE.
  WRITE:/ 'Eingaben müssen die gleiche Länge haben.'.
ENDIF.
Wenn du es noch hübscher machen willst, das ist aber Geschmackssache, kannst du die Felder lv_laenge1, lv_laenge2 und lv_dump streichen und durch die Ausdrücke ersetzen. Dann brauchst du nicht mal das MOVE

Dann sieht es so aus:

Code: Alles auswählen.

DATA:
*  lv_laenge1 TYPE string,
*  lv_laenge2 TYPE string,
*  lv_schritt TYPE i,
*  lv_dump    TYPE string,
  start      TYPE i.

PARAMETERS:
  wort1 TYPE text,
  wort2 TYPE text.

*lv_laenge1 = strlen( wort1 ).
*lv_laenge2 = strlen( wort2 ).
*lv_schritt = start + 1.

IF strlen( wort1 ) = strlen( wort2 ).
  DO strlen( wort1 ) TIMES.
*   lv_schritt = start + 1.
*   IF lv_schritt < lv_laenge1.
*      MOVE wort1+start(1) TO lv_dump.     
      FIND   wort1+start(1) IN wort2 IGNORING CASE.
      IF sy-subrc EQ 0. 
        REPLACE wort1+start(1) IN wort2 WITH '.'.
        start = start + 1.
      ELSE.
        WRITE:/ 'Kein Anagramm'.
        RETURN.
      ENDIF.
*    ELSE.
*     EXIT.
*    ENDIF.
  ENDDO.
  WRITE:/ 'Es ist ein Anagramm.'.
ELSE.
  WRITE:/ 'Eingaben müssen die gleiche Länge haben.'.
ENDIF.

Meine Lösung mit der Funktion count( ) sieht so übrigens so aus.

Code: Alles auswählen.

DATA: offset   TYPE i,
      anagramm TYPE xfeld.

PARAMETERS: word1 TYPE text OBLIGATORY,
            word2 TYPE text OBLIGATORY.

START-OF-SELECTION.
  IF strlen( word1 ) NE strlen( word2 ).
    WRITE: / 'kein Anagramm'.
    RETURN.
  ENDIF.

  anagramm = abap_true.
  DO strlen( word1 ) TIMES.
    IF count( val = word1 sub = word1+offset(1) case = abap_false )
    NE count( val = word2 sub = word1+offset(1) case = abap_false ).
      anagramm = abap_false.
      EXIT.
    ENDIF.
  offset = offset + 1.
  ENDDO.

  CASE anagramm.
    WHEN abap_true.
      WRITE: / 'Anagramm'.
    WHEN OTHERS.
      WRITE: / 'kein Anagramm'.
  ENDCASE.
Ein schönes Wochenende

Folgende Benutzer bedankten sich beim Autor PeterPaletti für den Beitrag:
Nion


Re: Feststellen ob Zeichenvorkommen übereinstimmen

Beitrag von LeMinion (ForumUser / 20 / 1 / 6 ) »
rob_abc hat geschrieben:
15.02.2023 13:27
Wenn du solche Codingübungen machst, dann melde mich mal auf exercism an. Dort gibt es unter anderem auch eine Aufgabe zu Anagrammen. https://exercism.org/tracks/abap/exercises/anagram
Ich liebe solche Aufgaben und Rätsel ja, und da kam mir diese Frage hier und Dein Link, rob_abc, nach meinem Urlaub gerade recht, um wieder "rein" zu kommen. 😊
Meine Lösung auf Exercism sieht so aus:

Code: Alles auswählen.

CLASS zcl_anagram DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS anagram
      IMPORTING input         TYPE string
                candidates    TYPE string_table
      RETURNING VALUE(result) TYPE string_table.

  PROTECTED SECTION.
    TYPES sorted_characters TYPE SORTED TABLE OF c WITH NON-UNIQUE KEY table_line.

    METHODS characters_of
      IMPORTING string TYPE string
      RETURNING VALUE(result) TYPE sorted_characters.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_anagram IMPLEMENTATION.
  METHOD anagram.
    DATA(input_characters) = characters_of( input ).
    DATA(lowercase_input) = to_lower( input ).
    LOOP AT candidates INTO DATA(candidate).
      CHECK to_lower( candidate ) <> lowercase_input
      AND characters_of( candidate ) = input_characters.
      INSERT candidate INTO TABLE result.
    ENDLOOP.
  ENDMETHOD.

  METHOD characters_of.
    DATA(characters) = replace( val = to_lower( string )  sub = ` `  with = ``  occ = 0 ).
    WHILE characters IS NOT INITIAL.
      INSERT characters+0(1) INTO TABLE result.
      SHIFT characters.
    ENDWHILE.
  ENDMETHOD.
ENDCLASS.
https://exercism.org/tracks/abap/exerci ... s/LeMinion

Re: Feststellen ob Zeichenvorkommen übereinstimmen

Beitrag von Nion (ForumUser / 17 / 20 / 1 ) »
PeterPaletti hat geschrieben:
18.02.2023 06:37
Hallo Nion,
ist schon ganz gut, aber leider nur ganz gut, denn es funktioniert noch nicht sauber. Deine Variable lv_schritt und die zugehörige IF-Abfrage führt dazu, dass das letzte Zeichen nicht überpüft wird: ROSE und ROST werden als Anagramm identifiziert.

Wenn du die ganze Logik mit lv_schritt auskommentierst funktioniert es wunderbar.

Code: Alles auswählen.

DATA:
  lv_laenge1 TYPE string,
  lv_laenge2 TYPE string,
*  lv_schritt TYPE i,
  lv_dump    TYPE string,
  start      TYPE i.

PARAMETERS:
  wort1 TYPE text,
  wort2 TYPE text.

lv_laenge1 = strlen( wort1 ).
lv_laenge2 = strlen( wort2 ).
*lv_schritt = start + 1.

IF lv_laenge1 = lv_laenge2.
  DO lv_laenge1 TIMES.
*   lv_schritt = start + 1.
*   IF lv_schritt < lv_laenge1.
      MOVE wort1+start(1) TO lv_dump.
      start = start + 1.
      FIND   lv_dump IN wort2 IGNORING CASE.
      IF sy-subrc = 0.
        REPLACE lv_dump IN wort2 WITH '.'.
      ELSE.
        WRITE:/ 'Kein Anagramm'.
        RETURN.
      ENDIF.
*    ELSE.
*     EXIT.
*    ENDIF.
  ENDDO.
  WRITE:/ 'Es ist ein Anagramm.'.
ELSE.
  WRITE:/ 'Eingaben müssen die gleiche Länge haben.'.
ENDIF.
Wenn du es noch hübscher machen willst, das ist aber Geschmackssache, kannst du die Felder lv_laenge1, lv_laenge2 und lv_dump streichen und durch die Ausdrücke ersetzen. Dann brauchst du nicht mal das MOVE

Dann sieht es so aus:

Code: Alles auswählen.

DATA:
*  lv_laenge1 TYPE string,
*  lv_laenge2 TYPE string,
*  lv_schritt TYPE i,
*  lv_dump    TYPE string,
  start      TYPE i.

PARAMETERS:
  wort1 TYPE text,
  wort2 TYPE text.

*lv_laenge1 = strlen( wort1 ).
*lv_laenge2 = strlen( wort2 ).
*lv_schritt = start + 1.

IF strlen( wort1 ) = strlen( wort2 ).
  DO strlen( wort1 ) TIMES.
*   lv_schritt = start + 1.
*   IF lv_schritt < lv_laenge1.
*      MOVE wort1+start(1) TO lv_dump.     
      FIND   wort1+start(1) IN wort2 IGNORING CASE.
      IF sy-subrc EQ 0. 
        REPLACE wort1+start(1) IN wort2 WITH '.'.
        start = start + 1.
      ELSE.
        WRITE:/ 'Kein Anagramm'.
        RETURN.
      ENDIF.
*    ELSE.
*     EXIT.
*    ENDIF.
  ENDDO.
  WRITE:/ 'Es ist ein Anagramm.'.
ELSE.
  WRITE:/ 'Eingaben müssen die gleiche Länge haben.'.
ENDIF.

Meine Lösung mit der Funktion count( ) sieht so übrigens so aus.

Code: Alles auswählen.

DATA: offset   TYPE i,
      anagramm TYPE xfeld.

PARAMETERS: word1 TYPE text OBLIGATORY,
            word2 TYPE text OBLIGATORY.

START-OF-SELECTION.
  IF strlen( word1 ) NE strlen( word2 ).
    WRITE: / 'kein Anagramm'.
    RETURN.
  ENDIF.

  anagramm = abap_true.
  DO strlen( word1 ) TIMES.
    IF count( val = word1 sub = word1+offset(1) case = abap_false )
    NE count( val = word2 sub = word1+offset(1) case = abap_false ).
      anagramm = abap_false.
      EXIT.
    ENDIF.
  offset = offset + 1.
  ENDDO.

  CASE anagramm.
    WHEN abap_true.
      WRITE: / 'Anagramm'.
    WHEN OTHERS.
      WRITE: / 'kein Anagramm'.
  ENDCASE.
Ein schönes Wochenende
Hoppla, so soll das natürlich nicht. Wenn ich die lv_schritt-Teile auskommentiere, hängt er sich wieder an sowas wie "Aal" und "All" auf, aber wenn ich statt
"IF lv_schritt < lv_laenge1." sage "IF lv_schritt <= lv_laenge1.", nimmt er den letzten Buchstaben auch mit und alles ist bestens.
Vielen Dank für die anschauliche Count-Variante, die ist definitiv eleganter :)

Viele Grüße,
Nion
Man muss nicht alles wissen. Man muss nur wissen, wo es steht oder wen man fragen kann.

Re: Feststellen ob Zeichenvorkommen übereinstimmen

Beitrag von PeterPaletti (Specialist / 348 / 32 / 97 ) »
Merkwürdig, also bei mir funktioniert dein Quellcode ohne lv_schritt auch bei Aal und All.

Du definierst doch schon durch lv_laenge1 die Anzahl der Schleifendurchläufe. lv_schritt ist ein zusätzlicher Zähler und die Abfrage IF lv_schritt <= lv_laenge1 ist bei jedem Schleifendurchlauf wahr. Der Zähler macht eigentlich nur in einer reinen DO..ENDDO Schleife Sinn.

Code: Alles auswählen.

DATA:
  lv_laenge1 TYPE string,
  lv_laenge2 TYPE string,
*  lv_schritt TYPE i,
  lv_dump    TYPE string,
  start      TYPE i.

PARAMETERS:
  wort1 TYPE text,
  wort2 TYPE text.

lv_laenge1 = strlen( wort1 ).
lv_laenge2 = strlen( wort2 ).
*lv_schritt = start + 1.

IF lv_laenge1 = lv_laenge2.
  DO lv_laenge1 TIMES.
*   lv_schritt = start + 1.
*   IF lv_schritt < lv_laenge1.
    MOVE wort1+start(1) TO lv_dump.
    start = start + 1.
    FIND   lv_dump IN wort2 IGNORING CASE.
    IF sy-subrc = 0.
      REPLACE lv_dump IN wort2 WITH '.'.
    ELSE.
      WRITE:/ 'Kein Anagramm'.
      RETURN.
    ENDIF.
*    ELSE.
*     EXIT.
*    ENDIF.
  ENDDO.
  WRITE:/ 'Es ist ein Anagramm.'.
ELSE.
  WRITE:/ 'Eingaben müssen die gleiche Länge haben.'.
ENDIF.

Folgende Benutzer bedankten sich beim Autor PeterPaletti für den Beitrag:
Nion


Re: Feststellen ob Zeichenvorkommen übereinstimmen

Beitrag von Nion (ForumUser / 17 / 20 / 1 ) »
PeterPaletti hat geschrieben:
20.02.2023 09:50
Merkwürdig, also bei mir funktioniert dein Quellcode ohne lv_schritt auch bei Aal und All.

Du definierst doch schon durch lv_laenge1 die Anzahl der Schleifendurchläufe. lv_schritt ist ein zusätzlicher Zähler und die Abfrage IF lv_schritt <= lv_laenge1 ist bei jedem Schleifendurchlauf wahr. Der Zähler macht eigentlich nur in einer reinen DO..ENDDO Schleife Sinn.
Ergibt Sinn.
Hm, dann hab ich vermutlich irgendwas übersehen bzw versehentlich mit auskommentiert. Aber so geht's ja auch und für die Zukunft weiß ich's dann jetzt besser :)
Man muss nicht alles wissen. Man muss nur wissen, wo es steht oder wen man fragen kann.

Re: Feststellen ob Zeichenvorkommen übereinstimmen

Beitrag von LeMinion (ForumUser / 20 / 1 / 6 ) »
Ui, sehe gerade, daß meine Antwort unvollständig ist - mein Urlaub war wohl zu lange. 😉 Beim Abschicken der Antwort habe ich wohl was falsch gemacht, sorry dafür. Ich werde meine Lösung nun aber etwas ausführlicher erläutern:
Ich wollte vor allem darauf hindeuten, daß Ennos Ansatz mit den Listen der vorkommenden Buchstaben zusätzlich den Vorteil bietet, daß man sogar Anagramme analysieren kann, die zwar die gleichen Buchstaben und auch die gleiche Anzahl davon verwenden, aber aus einzelnen Worten bestehen. So etwas wie "Tom Marvolo Riddle" und "I am Lord Voldemort". Ein gültiges Anagramm, aber eben in der Eingabe von unterschiedlicher Länge und mit unterschiedlichen vielen Wörtern.
Für den Ansatz der Liste von Buchstaben also braucht es zunächst mal einen passenden Tabellentyp, der eine sortierte Tabelle von Einzelzeichen deklariert, sowas wie

Code: Alles auswählen.

TYPES sorted_characters TYPE SORTED TABLE OF c WITH NON-UNIQUE KEY table_line.
Wichtig dabei ist, daß der Schlüssel der sortierten Tabelle als mehrdeutig (non-unique) definiert sein muß, damit mehrere gleiche Buchstaben erlaubt sind und gleichzeitig die Anzahl der gleichen Buchstaben erhalten bleibt.
Das Füllen einer solchen Tabelle geschieht dann in meinem Beispiel von oben so:

Code: Alles auswählen.

DATA(characters) = VALUE sorted_characters( ).
DATA(anagram) = replace( val = input  sub = ` `  with = ``  occ = 0 ).
WHILE anagram IS NOT INITIAL.
  INSERT CONV #( anagram+0(1) ) INTO TABLE characters.
  SHIFT anagram.
ENDWHILE.
Der Reihe nach geschieht das folgende:
1. Deklaration einer Variablen namens characters, die vom genannten Typ einer sortierten Tabelle ist.
2. Deklaration einer Variablen namens anagram, die aus einer anderen Variablen namens input entsteht, indem deren Inhalt mittels Funktion replace übernommen, aber Leerzeichen durch "nichts" ersetzt werden. Dadurch verschwinden Wortabstände, so daß in anagram das gleiche wie in input steht, nur eben ohne die Leerzeichen.
3. Solange in anagram etwas steht, wird nun die While-Schleife durchlaufen.
4. Zunächst wird der erste Buchstabe (offset 0, Länge 1, also anagram+0(1)) ermittelt, der mit der Funktion conv in den richtigen Typ umgewandelt und anschließend in die sortierte Tabelle der Buchstaben characters eingefügt.
5. Mittles shift verschiebt sich abschließend der Inhalt in anagram um ein Zeichen nach links, wobei das bisher erste Zeichen gelöscht wird. Wenn nun noch etwas in anagram an Zeichen übrig ist, dann geht's auf in die nächste Runde der While-Schleife.

Da ich nun das gleiche auch für die zweite Eingabe machen muß, bietet sich an, das Coding zur Ermittlung der sortierten Buchstabenliste in eine Form-Routine (oder wie in meinem Ansatz von oben in einer Methode) auszulagen, damit man das gleiche Coding nicht mehrmals im Programm stehen hat. In einem Report könnte das Coding dann so aussehen:

Code: Alles auswählen.

TYPES sorted_characters TYPE SORTED TABLE OF c WITH NON-UNIQUE KEY table_line.

PARAMETERS:
  string1 TYPE string LOWER CASE OBLIGATORY DEFAULT `Tom Marvolo Riddle`,
  string2 TYPE string LOWER CASE OBLIGATORY DEFAULT `I am Lord Voldemort`.

START-OF-SELECTION.
  DATA(string1_characters) = VALUE sorted_characters( ).
  DATA(string2_characters) = VALUE sorted_characters( ).
  PERFORM characters USING string1 CHANGING string1_characters.
  PERFORM characters USING string2 CHANGING string2_characters.
  WRITE: / 'Is an anagram:', COND #( WHEN string1_characters = string2_characters THEN `Yes` ELSE `No` ).


FORM characters USING string TYPE string CHANGING result TYPE sorted_characters.
  DATA(characters) = replace( val = to_upper( string )  sub = ` `  with = ``  occ = 0 ).
  WHILE characters IS NOT INITIAL.
    INSERT CONV #( characters+0(1) ) INTO TABLE result.
    SHIFT characters.
  ENDWHILE.
ENDFORM.
Es wird für beide Eingaben, string1 und string2, die Form-Routine characters aufgerufen, die daraus jeweils eine Liste sortierter Buchstaben erzeugt. Wenn die beiden resultierenden Tabellen identisch sind, dann handelt es sich um ein Anagramm, sonst nicht.

Folgende Benutzer bedankten sich beim Autor LeMinion für den Beitrag (Insgesamt 2):
rob_abcNion


Vergleichbare Themen

3
Antw.
1193
Views
Enticklungsklasse feststellen
von pohlmann-schwarza » 01.07.2008 10:21 • Verfasst in ABAP® für Anfänger
4
Antw.
2704
Views
Aurufer im RPCALC feststellen
von Guestrb » 03.01.2006 10:32 • Verfasst in Human Resources
4
Antw.
2391
Views
RFC-/Webservice-Aufrufe feststellen
von Roddy » 05.09.2012 08:49 • Verfasst in ABAP® Core
4
Antw.
6802
Views
Feststellen, ob Verzeichnis existiert
von ralf.wenzel » 22.08.2007 18:41 • Verfasst in ABAP® Core
1
Antw.
1244
Views
Feststellen ob BTC Mappe schon erzeugt wurde
von scott111 » 11.05.2006 16:07 • Verfasst in ABAP® Core

Über diesen Beitrag



Die Frage ist als "gelöst" markiert. Den entsprechend Beitrag findest du hier.

Unterstütze die Community und teile den Beitrag für mehr Leser und Austausch

Aktuelle Forenbeiträge

Regex in where
vor 9 Stunden von edwin 7 / 166
Daten an Tabelle binden
vor 23 Stunden von Bright4.5 3 / 1487

Newsletter Anmeldung

Keine Beiträge verpassen! Wöchentlich versenden wir lesenwerte Beiträge aus unserer Community.
Die letzte Ausgabe findest du hier.
Details zum Versandverfahren und zu Ihren Widerrufsmöglichkeiten findest du in unserer Datenschutzerklärung.

Aktuelle Forenbeiträge

Regex in where
vor 9 Stunden von edwin 7 / 166
Daten an Tabelle binden
vor 23 Stunden von Bright4.5 3 / 1487

Unbeantwortete Forenbeiträge

aRFC im OO-Kontext
vor 5 Wochen von ralf.wenzel 1 / 3261
Hilfe bei SWEC/SWE2
September 2024 von retsch 1 / 9822