Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Alles Rund um SAP®.
13 Beiträge • Seite 1 von 1
13 Beiträge Seite 1 von 1

Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von black_adept (Top Expert / 3462 / 68 / 681 ) »
Moin allerseits,

da wir längere Zeit kein Rätsel / Knobelaufgabe mehr hatten habe ich für die 3. Adventswoche eine recht einfache erstellt.
Kurze Regeln. Damit die Spannung ein wenig steigt bitte zunächst nur posten, ob ihr eine Lösung gefunden habt und - um den Wettbewerb ein wenig anzustacheln - wie viele Variablen/Befehle/Wörter (ohne Kommentare) eure Lösung benötigt. Bitte auch die Lösung via PM an mich schicken, damit ich ein Fazit vorbereiten kann was für Lösungsansätze gewählt wurden.
________________________________________________
Diesmal ist die Sache eigentlich ganz einfach: Eingabe der Methode "SOLUTION" ist eine interne Tabellen mit Längen und als Ausgabe erwarte ich die Summe der einzelnen Längen in Metern.
Mein eigener Lösungsansatz ist zwar sowohl sehr elegant als auch sehr laufzeitoptimiert - aber leider liefert er nicht in allen Fällen das Richtige Ergebnis, so dass diese Lösung leider nicht zählen kann. 😞 Eure Aufgabe ist es also diese Lösung so ändern, dass das korrekt summiert wird.
Wenn ihr mehrere Lösungsansätze habt die sich stark bezüglich Laufzeit oder Eleganz unterscheiden sind alle sehr willkommen.
Wie üblich habe ich auch ein kleines Testprogramm vorgesehen damit genau wisst worauf ihr euch einlasst:

Code: Alles auswählen.

REPORT.

PARAMETERS: p_lines TYPE i OBLIGATORY DEFAULT 1000,
            p_seed  TYPE i.

CLASS lcl_test DEFINITION FINAL.
  PUBLIC SECTION.
    TYPES: BEGIN OF mts_data,
             distance TYPE s_distance,
             distid   TYPE s_distid,
           END OF mts_data,
           mtt_data TYPE STANDARD TABLE OF mts_data WITH EMPTY KEY.
    CLASS-METHODS:
      create_testdata IMPORTING iv_lines TYPE i
                                iv_seed  TYPE i,
      solution RETURNING VALUE(rv_distance) TYPE f.

    CLASS-DATA:
      mt_testdata TYPE mtt_data.
ENDCLASS.

END-OF-SELECTION.
  lcl_test=>create_testdata( iv_lines = p_lines
                             iv_seed  = p_seed ).

  WRITE:/ p_lines, p_seed, lcl_test=>solution( ) DECIMALS 4 EXPONENT 0.



CLASS lcl_test IMPLEMENTATION.
  METHOD solution.
* Bitte hier austoben
* Längen summieren

    rv_distance = 42.  " Sehr mutige Annahme die leider manchmal  falsch ist

  ENDMETHOD.

  METHOD create_testdata.
    DATA: lo_rnd1     TYPE REF TO cl_abap_random_int,
          lo_rnd2     TYPE REF TO cl_abap_random_int,
          ls_testdata LIKE LINE OF mt_testdata.

    lo_rnd1 = cl_abap_random_int=>create( seed = iv_seed
                                         min  = 1
                                         max  = 10 ).

    lo_rnd2 = cl_abap_random_int=>create( seed = iv_seed
                                           min  = 1
                                           max  = 7 ).

    DO iv_lines TIMES.
      ls_testdata-distance = lo_rnd1->get_next( ).
      CASE lo_rnd2->get_next( ).
        WHEN 1. ls_testdata-distid = 'CM'.
        WHEN 2. ls_testdata-distid = 'DM'.
        WHEN 3. ls_testdata-distid = 'FT'.
        WHEN 4. ls_testdata-distid = 'IN'.
        WHEN 5. ls_testdata-distid = 'KM'.
        WHEN 6. ls_testdata-distid = 'M'.
        WHEN 7. ls_testdata-distid = 'MI'.
        WHEN OTHERS.
          ASSERT 1 = 0." ls_testdata-distid = 'IN'.
      ENDCASE.
      APPEND ls_testdata TO mt_testdata.

    ENDDO.
  ENDMETHOD.

ENDCLASS.
Viel Spaß beim Knobeln diese Woche

P.S. Nur wer es ausprobiert kann nachher die Qualität anderer Ansätze richtig würdigen ( Und es gibt immer mehrere Ansätze - und sei es nur weil sich die persönlichen Präferezen von Person zu Person unterscheiden ). Wer mir seine Lösung via PM zuschickt bekommt normalerweise auch immer einen kleinen Kommentar dazu und was mir daran gefällt oder was ich ändern würde.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de


Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von black_adept (Top Expert / 3462 / 68 / 681 ) »
😋 Nachtrag: Ich habe am mit Seed 13498 und 5 Zeilen getestet

Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von a-dead-trousers (Top Expert / 3590 / 124 / 933 ) »
Du willst mit der Lösung wohl auf einen INLINE-CASE (SWITCH) mit Berechnung und das alles in einem Schritt mit REDUCE hinaus. 😉

Kurze Frage, wenn man es "klassisch" lösen möchte:
Darf man die Struktur-/Tabellendefinition irgendwie "optimieren" oder ist das so fix vorgegeben.
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.07
Basis: 7.40

Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von black_adept (Top Expert / 3462 / 68 / 681 ) »
Nö - die Struktur-/Tabellendefinition ist absichtlich "unschön" vorgegeben. Soll ja nicht zu einfach werden.
Und es führen viele Wege nach Rom...
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von a-dead-trousers (Top Expert / 3590 / 124 / 933 ) »
Ich hab zwei Lösungen:
1) "Klassische" Variante, so wie ich sie aufgrund der Lesbarkeit schreiben würde:
1 Schleife
1 Abfrage (CASE)
7 Zuweisungen
82 Wöter
539 Zeichen ohne Leerzeichen

2) "Optimierte" Variante:
1 Zuweisung
54 Wörter
218 Zeichen ohne Leerzeichen

Von der Performance her sind beide fast ident, wobei die zweitere vermutlich aufgrund der geringeren Anzahl an zu parsenden Befehlen um eine Hauch schneller arbeitet.

lg ADT

EDIT:
Im Sinne einer "allgemeinen" Optimierung würde ich mir das zweimalige Umwandeln von Zahl auf "Einheit" und dann wieder von "Einheit" auf Umrechnungswert sparen und gleich den Umrechnungswert aus der T006 lesen und in der Tabelle hinterlegen.
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.07
Basis: 7.40

Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von whaslbeck (ForumUser / 28 / 3 / 0 ) »
Hallo,

hab auch zwei Lösungsansätze mit folgenden Metriken:

1. Lösung
5 Befehle,
31 Wörter
201 Zeichen ohne Leerzeichen

2. Lösung:
2 Befehle,
52 Wörter
178 Zeichen ohne Leerzeichen.

Wobei ich in produktiven Code eher den ersten Ansatz verwenden würde. Und beim zweiten Ansatz kann ich noch ein paar Bytes sparen, wenns sein muss :-)

Walter

Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von whaslbeck (ForumUser / 28 / 3 / 0 ) »
Hallo nochmal,

hier die Metrik einer leicht optimierten Variante meiner zweiten Lösung:
2 Befehle
46 Wörter
157 Zeichen ohne Leerzeichen

Walter

Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von black_adept (Top Expert / 3462 / 68 / 681 ) »
Einsendeschluss ist wie üblich der Freitag damit ich am WE ein Fazit vorbereiten kann.
Die bisher geposteten Lösungen sind schon sehr, sehr gut. Aber beim Mitmachen geht es hier wirklich nicht darum den Highscore zu erzielen ( auch wenn das gerne als Motivation herhalten kann ) einfach weil jeder einen anderen Erfahrungsschatz vorweisen kann, sondern darum seine eingefahrenen Denkmuster mal beiseite zu legen um zu schauen mit was für verschiedenen Ansätzen und Optimierungszielen man denn so eine scheinbar klare Aufgabe lösen kann.
Und da ihr doch sowieso wegen des Lockdowns jetzt keine Weihnachtsgeschenke mehr kaufen könnt ist das eine nette Art sich die Zeit alternativ zu vertreiben.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von DeathAndPain (Top Expert / 1490 / 165 / 335 ) »
Ich habe auch eine Lösung entwickelt. Inhaltlich scheint sie auf das von adt genannte hinauszulaufen, wobei ich das erst gelesen habe, als meine Lösung schon fertig war.

Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von black_adept (Top Expert / 3462 / 68 / 681 ) »
Moin allerseits,

wie bei der letzten Knobelaufgabe möchte ich gerne nach eine Woche ein Fazit ziehen, die Probleme der Aufgabenstellung und die mir ab jetzt bekannten Lösungsmöglichkeiten erläutern. Auch hier wieder "Danke" an alle die mir ihre Lösung via PM ( oder Email ) zugeschickt haben - und wie beim letzen Mal stelle ich fest: Auch wenn sonst niemand anderes was hieraus lernt: Ich habe zumindest den einen oder anderen Anstoß erfahren was ich in meinen eigenen Codings verändern könnte.

Die Aufgabenstellung war ja diesmal recht simpel. Es gab eine Tabelle mit Längen in verschiedenen Längeneinheiten und man sollte möglichst "elegant" die Gesamtlänge in Metern errechnen.
Im Grundsatz haben mich nur zwei Arten von Lösungsansätzen erreicht. Der eine Ansatz geht über einen LOOP macht die Umrechnung in Meter und addiert das Ergebnis dann zur Ausgabe. Der andere Ansatz macht das Ganze in einem Schritt unter Verwendung der Befehle REDUCE und FOR.

Interessanter waren dann aber die Unterschiede wie man die Umrechnung z.B. von Meilen in Meter vollzog.
Eine Möglichkeit ist einfach zu Googeln und bei den wenigen Vorgaben die in dieser Tabelle daherkamen dass einfach hart zu codieren. Ist vielleicht nicht der eleganteste Ansatz - aber er führt definitiv zu einem sauberen Ergebnis.
Beispiel einer solchen Lösung von a-d-t ( hier die Variante mit "RECUDE und FOR":

Code: Alles auswählen.

rv_distance = REDUCE #( INIT re TYPE f
                        FOR  wa IN mt_testdata
                        NEXT re = re + ( wa-distance * SWITCH f( wa-distid WHEN 'CM' THEN '0.01'
                                                                           WHEN 'DM' THEN '0.1'
                                                                           WHEN 'FT' THEN '0.3048'
                                                                           WHEN 'IN' THEN '0.0254'
                                                                           WHEN 'KM' THEN 1000
                                                                           WHEN 'M'  THEN 1
                                                                           WHEN 'MI' THEN '1609.344' ) ) ).
Die 2. Möglichkeit war sich diese Daten stattdessen aus der Tabelle T006 zu ziehen. Da "Meter" die SI-Längeneinheit ist stehen Zähler und Nenner für jede andere Mengeneinheit dort direkt zur Verfügung. Hier eine Variante von whaslbeck die diesen Ansatz verfolgt.

Code: Alles auswählen.

    SELECT msehi AS m, zaehl AS z, nennr AS n
      INTO TABLE @DATA(t)
      FROM t006.
    rv_distance = REDUCE #(
      INIT e TYPE f
      FOR w IN mt_testdata
        NEXT e = e + w-distance * t[ m = w-distid ]-z / t[ m = w-distid ]-n ).
Wenn es denn tatsächlich auf Geschwindigkeit ankommt kann das noch beschleunigt werden wie von mehreren Teilnehmern angedeutet ( oder sogar zugeschickt ) indem man die Umrechnungsfaktoren vorberechnet und dann in einer Hashtabelle vorhält.

Die 3. - und in meinen Augen eigentlich schönste - Möglichkeit geht den ganz klassischen Ansatz und benutzt die Programmiertechnik des "Ich muss das Rad nicht neu erfinden". Es wird "einfach" der von SAP bereitgestellte Funktionsbaustein UNIT_CONVERSION_SIMPLE verwendet der die Umrechnung von einer Mengeneinheit in eine andere zur Verfügung stellt. Dies ist wahrscheinlich nicht die laufzeitkürzeste Variante da SAP in den Tiefen dieser Bausteine eine ganze Menge Prüfungen macht, aber man kann im Zweifelsfall immer die Schuld auf SAP schieben.
Hier die von whaslbeck vorgeschlagene Lösung, die sich ( für mich überraschenderweise) auch als kürzeste ergeben hat was die Anzahl der Wörter angeht.

Code: Alles auswählen.

    DATA o TYPE s_distance.
    LOOP AT mt_testdata ASSIGNING FIELD-SYMBOL(<t>).
      CALL FUNCTION 'UNIT_CONVERSION_SIMPLE'
        EXPORTING
          input    = <t>-distance
          unit_in  = <t>-distid
          unit_out = 'M'
        IMPORTING
          output   = o.
      ADD o TO rv_distance.
    ENDLOOP.
Außer Konkurrenz wollte ich dann noch die wohl kürzeste Lösung präsentieren, die letztlich aber auch nur das macht was bisher gepostet wurde und nur auf einem System ab Release 7.52 aufwärts funktioniert. ( sql-function division ab 7.51, interne Tabelle als Datenquelle ab 7.52 )

Code: Alles auswählen.

    SELECT SUM( division( itab~distance * t006~zaehl ,t006~nennr ,11 ) )
      FROM @mt_testdata AS itab JOIN t006 ON itab~distid = t006~msehi
      INTO @rv_distance.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von a-dead-trousers (Top Expert / 3590 / 124 / 933 ) »
Hi.

Den Ansatz mit UNIT_CONVERSION_SIMPLE hatte ich auch kurz verfolgt, aber die Gesamtlaufzeit war jenseits von gut und böse. Ich hab dann echt lange nach einer möglichst eleganten Lösung gesucht die ohne Funktionsbaustein Aufruf auskommt. Aber entweder die SAP bietet dafür nichts an oder ich habs nicht gefunden. Schön wäre etwas analog zu "|{ ls_alpha alpha = out }|" oder eine (Klassen-)Methode mit Returnvalue. Das ließe sich dann ganz bequem anstatt des großen SWITCH oder des Funktionsbausteinaufrufs verwenden. Natürlich hätte ich jetzt die Klasse auch selber schreiben können, aber das hätte meines Erachtens den Rahmen der Aufgabenstellung gesprengt.

Den Ansatz mit der internen Tabelle hatte ich auch im Kopf aber leider kein System mit dem entsprechenden Releasestand.
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.07
Basis: 7.40

Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von a-dead-trousers (Top Expert / 3590 / 124 / 933 ) »
Ein Beispiel hätte ich (der Vollständigkeit halber) noch anzubieten, wobei mir das von der Aufgabenstellung her aber auch zu aufwändig erschienen ist. Ich wollte ja das CALL FUNCTION loswerden 😉

Code: Alles auswählen.

  DATA o TYPE s_distance.
  LOOP AT mt_testdata ASSIGNING FIELD-SYMBOL(<t>)
    GROUP BY ( distid = <t>-distid ) ASSIGNING FIELD-SYMBOL(<g>).
    CALL FUNCTION 'UNIT_CONVERSION_SIMPLE'
      EXPORTING
        input    = 1
        unit_in  = <g>-distid
        unit_out = 'M'
      IMPORTING
        output   = o.
    LOOP AT GROUP <g> ASSIGNING FIELD-SYMBOL(<m>) 
      rv_distance = rv_distance + <m>-distance * o.
    ENDLOOP.
  ENDLOOP.
Damit erspart man sich die erwähnte HASH-Tabelle und kann trotzdem die Findung des Umrechnungsfaktors optimieren.

EDIT: Kleine Fehlerkorrektur
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.07
Basis: 7.40

Re: Knobelaufgabe zum Wochenende/Wochenbeginn ( Dezember 2020 )

Beitrag von DeathAndPain (Top Expert / 1490 / 165 / 335 ) »
Und da hast Du jetzt kein CALL FUNCTION drin? 😁

j/k

Seite 1 von 1

Vergleichbare Themen

Knobelaufgabe zum Wochenende/Wochenbeginn
von black_adept » 04.09.2020 11:23
Knobelaufgabe zum Wochenende / Wochenbeginn
von black_adept » 23.08.2019 08:46
Umstellung Umsatzsteuer zum Juli 2020
von jocoder » 15.06.2020 12:21
Nur Werktage zählen (Ohne Wochenende)
von Dyrdek » 13.12.2016 13:44
FAUF-Terminierung fällt auf das Wochenende
von Thomas17 » 07.09.2012 13:13