Tipps zum Golfen in APL


28

Ich habe kürzlich eine Code Golf Challenge gestartet und es scheint, als ob der Gewinner GolfScript ist (Überraschung, Überraschung!). Interessant ist, dass es einen weiteren sehr starken Konkurrenten gab, der alle Chancen hatte, GolfScript zu gewinnen. Sein Name ist APL. Ich sehe hier eine Menge Antworten in APL. Es scheint, dass diese Sprache für Code-Golf ziemlich effizient ist, deshalb entscheide ich mich, nach Tipps für Code-Golf zu fragen, die Sie für APL-Programme kennen. Zögern Sie nicht, einige Codebeispiele zu posten. Es ist normalerweise sehr interessant, Sprache in Aktion zu sehen.

Antworten:


23

Bearbeiten : Für Leser, die APL nicht kennen, es aber aufgreifen möchten, ist das Beherrschen von Dyalog APL eine sehr gute Ressource.

  1. Die Bewertung erfolgt ausschließlich von rechts nach links. Dies schließt das Setzen von Variablen ein, nutzen Sie diese also.

    2+a, 1+a←1 -> 3 4

    awird gesetzt auf 1, 1+abewertet auf 2, a,2bewertet auf 1 2und 2+1 2bewertet auf 3 4.

  2. Wie C kann mit einer Funktion kombiniert werden, dh a +← 3. Im Gegensatz zu C ist dies generisch: foo F← barsetzt fooauf F bar. Etwas unintuitiv, als Ausdruck kehrt dies barnicht zurück F bar.

    Es funktioniert auch mit anonymen Funktionen:

          a←0
          a+←3 ⋄ a
    3
          a+←3 ⋄ a
    6
          a { ⍵/'!' } ←4 ⋄ a
    !!!!
    
  3. Sie können ein Array zuweisen:, A[3]←8wie Sie es erwarten würden. Sie können jedoch auch mehrere Elemente gleichzeitig zuweisen A[3 5 6]←9 1 4oder sogar A[3 5 6]←9alle auf dasselbe Element festlegen. Natürlich können Sie auch hier eine Funktion hinzufügen . Die Funktion wird dann auf jedes Element separat angewendet, als ob Sie es getan hätten .

  4. ist dein Freund, auch wenn er nicht allzu glücklich darüber aussieht.

    1. Wenn Fdyadisch ist, wechselt dyadisch die Argumente: a F b<-> b F⍨ a. Dies ist praktisch, wenn Sie Golf spielen, da Sie auf die Verwendung von Hosenträgern verzichten können:

      (F G H x) K y      <->     y K⍨ F G H x
      

      Dies ändert die Auswertungsreihenfolge, da die rechte Hand immer vor der linken Hand ausgewertet wird.

    2. Wenn Fdyadisch ist, wendet monadisch dasselbe Argument auf beide Seiten der Funktion an:

            5⍴5
      5 5 5 5 5
            ⍴⍨5
      5 5 5 5 5
      

      Das Argument wird nur einmal ausgewertet. Dies ist besonders praktisch bei äußeren Produkten, dh wenn Sie jeden Wert in einem Array mit den anderen Werten in demselben Array vergleichen möchten, können Sie dies verwenden, ∘.=⍨anstatt dies zu tun x∘.=x←(whatever).

    3. Wenn Fist monadisch, tut nichts, aber es trennt die Funktion vom Argument. Wenn die Funktion komplex ist, können Sie immer noch geschweifte Klammern sparen:

            {⍵+3}⍣5 6
            ∇{⍵+3}              
           ∇ ⍣ 5 6              
            ({⍵+3}⍣5)6
      21
            {⍵+3}⍣5⍨6
      21
      
  5. Lerne die Redewendungen! Dann spielen Sie die Redewendungen. Beispielsweise:

    ((((1↑⍴X),⍴Y)↑X)^.=Y)⌿X
    

    kann mechanisch umgewandelt werden in:

    X⌿⍨Y^.=⍨X↑⍨(1↑⍴X),⍴Y
    

    und dann weiter in:

    X⌿⍨Y^.=⍨X↑⍨(⊃⍴X),⍴Y
    

    (erstens) 1↑in diesem Fall äquivalent sein zu (nimm eins). Und möglicherweise:

    X⌿⍨Y^.=⍨X↑⍨(≢X),⍴Y
    

    (Tally) entspricht ⊃⍴(dem ersten Element der Form) für alle außer Skalaren.


Gibt es neben der Himbeer-Pi-Version eine Möglichkeit, eine kostenlose Lizenz zu erhalten?
Fabinout

Ein legaler Weg, um es zu bekommen, offensichtlich.
Fabinout

2
@Fabinout: Auf dyalog.com können Sie eine kostenlose Windows-Version herunterladen. Klicken Sie auf "Download Zone" und dann auf "Nicht registrierter Download". Es wird Sie nerven, sich zu registrieren, aber ansonsten ist es voll funktionsfähig und kostenlos und legal. Wenn Sie Student sind, können Sie die normale Version kostenlos herunterladen, indem Sie ein Formular ausfüllen. Wenn Sie nicht in einem Land leben, in dem die Piraterie Ihr Leben ruiniert, wissen Sie, was zu tun ist.
Marinus

Es gibt auch Nars2000, eine Open-Source-Implementierung mit viel mehr Funktionen als Dyalog (und einigen Fehlern). Einige der Funktionen eignen sich zum Golfen, z. B. die Primzahlfunktionen oder Multisets.
Tobia

1
Es gibt GNU APL.
M. Alaggan

14

Züge

A(f g h)B      ←→  (A f B)g A h B  ⍝ fork
 (f g h)B      ←→  (  f B)g   h B  ⍝ fork
A(  g h)B      ←→         g A h B  ⍝ atop
 (  g h)B      ←→         g   h B  ⍝ atop
 (A g h)       ←→  ({A} g h)       ⍝ "Agh" fork
 (f g h k)     ←→  (f (g h k))     ⍝ 4-train
 (f g h k l)   ←→  (f g (h k l))   ⍝ 5-train, etc
 (f g h k l m) ←→  (f(g h(k l m))) ⍝ groups of 3 from the right, last could be 2
  f∘g B        ←→    f g B         ⍝ "compose" operator, useful in trains
A f∘g B        ←→  A f g B

Bedeutet das, dass wir künftigen Lesern zuliebe Oberon nicht sagen sollten, wie er es verkürzen soll?
Adám

Nein, machen Sie wie gewohnt mit PPCG. Ich werde diese Zeile entfernen, sobald der Ausdruck den kürzesten erreicht (was ich glaube). Es ist eine einfache Übung - ich glaube nicht, dass Sie persönlich davon profitieren würden.
30.

Ich kann es auf 16 bringen, aber ich verwende keine Ihrer Tipps, also bin ich vielleicht weit davon entfernt.
Adám

@ Adám na
ja

Ist es nicht "Dreiergruppen von rechts "?
Adám

7

Tricks für den Umgang mit /und in Zügen

Wenn Sie Züge benutzen, möchten Sie vielleicht Reduzierungen f/wie Summe +/oder sogar Nachbildung verwenden //. Wenn Ihr Zug jedoch links von der Verkleinerung mehr Teile enthält, benötigen Sie Klammern, um eine Spitze zu erstellen. Hier sind einige Tricks zum Speichern von Bytes.

Verwenden Sie diese 1∊Option anstelle von monadischen ∨/oder ∨⌿booleschen Arrays

Aufgabe: Geben Sie bei zwei gleichlangen Zeichenfolgen A und B 2 zurück, wenn die entsprechenden Zeichen von A und B gleich sind, andernfalls 0. ZB A←'abc'und B←'def'gibt 0und A←'abc'und B←'dec'gibt 2.

Eine DFN-Lösung kann sein, A{2×∨/⍺=⍵}Baber Sie möchten sie durch Stillschweigen verkürzen. A(2×∨/=)Bwird nicht funktionieren, weil die Regeln der Zugbildung dies so parsen, wie 2 (× ∨/ =)Sie es möchten 2 × (∨/=).

Beobachten Sie, dass ∨/oder ∨⌿auf einem Booleschen Vektor ( ∨/,oder ∨⌿,für Arrays mit höherem Rang) gefragt wird, ob 1 vorhanden ist, dh 1∊, wir können unseren Zug schreiben als 2×1∊=.

Beachten Sie, dass das richtige Argument verwendet wird, sodass Sie nicht jede Zeile oder Spalte einzeln reduzieren können.

Verwenden Sie 1⊥anstelle von monadisch +/oder+⌿

Aufgabe: Geben Sie bei einer Liste von Listen L und einem Index N die Summe der N-ten Liste dreimal zurück. ZB L←(3 1 4)(2 7)und N←1gibt 24.

Eine DFN-Lösung kann sein, N{3×+/⍺⊃⍵}Laber Sie möchten sie durch Stillschweigen verkürzen. N(3×+/⊃)Lwird nicht funktionieren, weil die Regeln der Zugbildung dies so parsen, wie 3(× +/ ⊃)Sie es möchten 3 × (+/⊃).

Beachten Sie, dass das Auswerten einer Liste von Zahlen in Unary (Basis-1) gleichbedeutend ist mit dem Summieren der Liste, da because { a , b , c , d } =  a + b + c + d  = ( a × 1³) + ( b × 1²) ) + ( c × 1¹) + ( d × 1⁰). Deshalb +/a b c dist das genauso 1⊥a b c d, und wir können unseren Zug so schreiben 3×1⊥⊃.

Beachten Sie, dass bei übergeordneten Argumenten 1⊥gleichbedeutend mit ist +⌿.

Verwenden Sie f.gstatt f/gmit Skalar- und / oder Vektorargumenten

Aufgabe: Geben Sie für eine Liste L und eine Zahl N den Bereich 1 durch die Anzahl der verbleibenden minimalen Divisionen zurück, wenn die Elemente von L durch NEg dividiert sind L←31 41 59und N←7ergeben 1 2 3.

Eine DFN-Lösung kann sein, N{⍳⌊/⍺|⍵}Laber Sie möchten sie durch Stillschweigen verkürzen. N(⍳⌊/|)Lwird nicht funktionieren, weil die Regeln der Zugbildung dies so parsen, wie ⍳ (⌊/) |Sie es möchten ⍳ (⌊/|).

Das innere Produkt A f.g Bvon skalaren zwei Funktionen, wenn die Argumente Skalare und / oder Vektoren sind, ist dasselbe wie, f/ A g Bweil beide (A[1] g B[1]) f (A[2] g B[2]) f (A[3] g B[3])usw. sind, so dass wir unseren Zug schreiben können als ⍳⌊.|.

Beachten Sie, dass dies für höherrangige Arrays nicht funktioniert.

Verwenden Sie ∊⊆anstelle von /booleschen linken und einfachen Vektor-rechten Argumenten

Aufgabe: Filtern Sie die Liste mit einer Liste L und einer Zahl N so, dass nur Zahlen größer als N übrig bleiben. ZB L←3 1 4und N←1gibt 3 4.

Eine DFN-Lösung kann sein, N{(⍺<⍵)/⍵}Laber Sie möchten sie durch Stillschweigen verkürzen. N(</⊢)Lwird nicht funktionieren, da die Bindungsregeln dies analysieren, (</) ⊢aber Sie möchten /die Funktion replizieren und nicht den Operator reduzieren .

Dyadisch mit einem booleschen linken Argument unterteilt das rechte Argument in Einsenreihen im linken Argument und löscht Elemente, die durch 0en gekennzeichnet sind. Dies ist fast das, was wir wollen, abgesehen von der unerwünschten Partitionierung. Wir können jedoch die Partitionierung durch Anwenden von monadic aufheben . So {(⍺<⍵)/⍵}können {∊(⍺<⍵)⊆⍵}wir werden und so können wir unseren Zug schreiben ∊<⊆⊢.

Beachten Sie, dass dies für höherrangige Arrays nicht funktioniert.

Verwenden Sie 0⊥anstelle von ⊢/oder ⊢⌿mit numerischen Argumenten

Aufgabe: Multiplizieren Sie das N mit dem am weitesten rechts stehenden Element von LEg L←3 1 4und N←2geben Sie eine Liste L und eine Zahl N an 8.

Eine DFN-Lösung kann sein, N{⍺×⊢/⍵}Laber Sie möchten sie durch Stillschweigen verkürzen. N(⊣×⊢/⊢)Lwird nicht funktionieren, weil die Regeln der Zugbildung dies so parsen, wie ⊣ (× ⊢/ ⊢)Sie es möchten ⊣ × (⊢/⊢).

Beachten Sie, dass 0⊥in einem numerischen Array dasselbe wie in einem numerischen Array ist ⊢⌿, sodass wir unseren Zug als schreiben können ⊣×0⊥⊢.

Beachten Sie, dass hiermit die letzte Hauptzelle höherrangiger Arrays ausgewählt wird.


1
Vielleicht könntest du diese Chat-Antwort zu dieser hinzufügen ?
J. Sallé

1
@ J.Sallé Hinzugefügt.
Adám

7

Verwenden Sie diese Option , um die Multiplikation mit der Addition zu kombinieren

(a×b)+C  ->  a⊥b,C
(C)+a×b  ->  a⊥b,C
(a×b)-C  ->  a⊥b,-C

Annahmen:

  • aund bsind Begriffe, die keine weiteren Klammern erfordern, wenn sie als linkes Argument verwendet werden

  • C ist ein Ausdruck, für den möglicherweise Klammern erforderlich sind, wenn er als linkes Argument verwendet wird

  • a b C zu numerischen Skalaren auswerten


5

Komplexe Zahlen

Oft übersehen, bieten sie wunderbare Möglichkeiten, um Ausdrücke zu verkürzen, die sich mit Gittern, Irrgärten, Fraktalen oder Geometrien befassen.

0j1⊥¨    0j1⊥   ⍝ pair(s) of reals -> complex
11 9∘○¨  11 9○  ⍝ complex -> pair(s) of reals
|z0-z1          ⍝ distance between two points
0j1×z   0j¯1×z  ⍝ rotate by ±90° around (0,0)
0j1*⍳4          ⍝ the four cardinal directions
+z       -+z    ⍝ reflect across x or y axis
+\0,z           ⍝ sequence of steps -> path
2-/z            ⍝ path -> sequence of steps
0j1⊥¨n-⍳2⍴1+2×n ⍝ lattice centred on (0,0)

4

Indizierung der Modulo-Vektorlänge

⊃i⌽aist oft kürzer als die naive ⊃a[(≢a)|i]oder a⊃⍨i|⍨≢a(wo aist ein Vektor und iist eine ganze Zahl und ⎕ioist 0)

Eine nützliche Variation dazu (danke EriktheOutgolfer für den Hinweis) ist: I↑Y⌽⍨I×XWo Yist die Verkettung einiger Längenvektoren Iund wo Xist der Index desjenigen , den wir auswählen möchten, zum Beispiel:3↑'JanFeb...Dec'⌽⍨3×month


3

Konstante Funktionen

=⍨und ≠⍨danke an ngn.

Manchmal brauchen Sie nur einen einzigen Wert für jedes Element einer Liste. Während Sie vielleicht versucht sind zu verwenden {value}¨, ist es kürzer zu verwenden, value⊣¨ aber für einige gängige Werte können Sie noch kürzer werden (mit ⎕IO←0):

¯1s mit ⍬⍸list

0s mit ⍬⍳list

1s mit ⍬⍷list

Beachten Sie, dass diese nur auf Listen funktionieren (obwohl sie möglicherweise verschachtelt sind). Für höherrangige Arrays können Sie Folgendes verwenden, um alle Nullen und alle Einsen abzurufen:

1s mit =⍨

0s mit ≠⍨

Wenn Sie festlegen ⎕ML←0, können alle Zahlen zu Nullen gemacht werden (als ob ) mit:

Wenn Sie nur eine einzelne Zahl benötigen, können Sie möglicherweise monadic verwenden , um 1 oder 0 zu erhalten, anstatt 1⊣oder zu verwenden 0⊣.


" Manchmal brauchen Sie nur einen einzigen Wert für jedes Element einer Liste. " - Es kann bemerkenswert sein: Wenn dieser Wert das erste Element der Liste ist, können Sie⊣\
ngn

@ngn Ich würde das sagen und mit /und einen eigenen Beitrag verdienen.
Adám

2

Verwenden

Vermeiden Sie Klammern

(Pendeln) kann Ihnen Bytes sparen, indem Klammern vermieden werden. Wenn Sie eine Funktion haben, bei der das linke Argument in Klammern gesetzt werden muss und das rechte Argument nicht, können Sie ein Byte speichern, z . B. (A<B)÷CC÷⍨A<B.

Doppelte Arrays

Verwenden Sie ,⍨Aoder , um eine Kopie eines Arrays an dessen Ende anzuhängen ⍪⍨A.

Doppelte Zahlen

Anstatt 2∘×zu double zu verwenden, können Sie Folgendes verwenden, +⍨da das Argument zu sich selbst hinzugefügt wird: 1+2∘×1++⍨.

Quadratzahl

Anstatt 2*⍨Yzu quadrieren, können Sie verwenden, ×⍨Yda es das Argument mit sich selbst multipliziert: 2*⍨A+B×⍨A+B.

Zufällige Permutation

?⍨Ngibt Ihnen eine zufällige Permutation der Länge N.

Selbsteinstufung

Finden Sie die Indizes des ersten Auftretens jeder Hauptzelle mit ⍳⍨A

Zählen Sie nachfolgende 1s in einem Booleschen Vektor

Anstatt +/∧\⌽Bzu zählen, wie viele nachfolgende Einsen sich in NIhnen befinden, können Sie verwenden ⊥⍨.

Umgekehrte Zusammensetzung

A f∘g Bist A f g B, aber wenn du willst (g A) f B, benutze f⍨∘g⍨.

Rückwärts reduzieren

f/ a1 a2 a3ist a1 f (a2 f a3). Wenn Sie möchten (a1 f a2) f a3, verwenden Sie f⍨/⌽.

Reverse Scan

f\ A B Cist
A (A f B) (A f (B f C)).

f⍨/∘⌽¨,\ A B Cist
A (A f B) ((A f B) f C).

f⍨\⌽ A B Cist
((A f B) f C) (B f C) C.

⌽f/∘⌽¨,\⌽ A B C. ist
(A f (B f C)) (B f C) C.


2

Zählen Sie die Zeichen in einer Zeichenfolge ohne auf ⍳≢

Aufgabe: Geben Sie zwei Zeichenfolgen an, S und T, und listen Sie die Indizes ihrer Verkettung auf. ZB S←'abcd'und T←'xyz'gibt 1 2 3 4 5 6 7.

Eine DFN-Lösung kann sein, S{⍳≢⍺,⍵}Taber Sie möchten sie durch Stillschweigen verkürzen. ⍳≢,wird nicht funktionieren, weil die Regeln für das Parsen von Zügen dies so analysieren, wie (⍳)≢(,)Sie es möchten (⍳≢),.

Dyadisch mit einem leeren linken Argument bewertet einfache Zeichenarrays gemäß ihrer aktuellen Reihenfolge, die mit identisch ist ⍳≢. So {⍳≢⍺,⍵} können {⍬⍋⍺,⍵}wir werden , so können wir unseren Zug als schreiben ⍬⍋,.

Beachten Sie, dass dies nicht für numerische oder gemischte Arrays funktioniert.


Wow, wusste nicht, dass das eine Sache ist.
Zacharý
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.