APL'de golf oynamak için ipuçları


28

Son zamanlarda bir kod golf mücadelesine başladım ve galibi GolfScript (sürpriz, sürpriz!) Gibi görünüyor. İlginç olan, GolfScript'te kazanma şansı olan başka bir çok güçlü rakip olması. Adı APL. Burada APL ile yazılmış bir sürü cevap görüyorum. Görünüşe göre bu dil kod golfü için oldukça verimli, bu yüzden APL programları için bildiğiniz kod golfü ipuçlarını sormaya karar verdim. Bazı kod örnekleri göndermekten çekinmeyin. Dili çalışırken görmek çok ilginçtir.

Yanıtlar:


23

Düzenleme : hiç APL biliyorum ama bunu almak istemiyorsanız bu okuma insanlar için, Mastering Dyalog APL bir olduğunu çok iyi bir kaynak.

  1. Değerlendirme kesinlikle sağdan soladır. Bu ayar değişkenleri içerir, bundan faydalanın.

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

    aolarak ayarlanır 1, 1+adeğerlendirilir 2, a,2değerlendirilir 1 2ve 2+1 2değerlendirilir 3 4.

  2. C gibi, bir fonksiyonla birleştirilebilir, yani a +← 3. C aksine, bu geneldir: foo F← barkümeler fooiçin F bar. Garip bir şekilde, bunun bir ifadesi olarak bar, değil döndürür F bar.

    Anonim işlevlerle de çalışır:

          a←0
          a+←3 ⋄ a
    3
          a+←3 ⋄ a
    6
          a { ⍵/'!' } ←4 ⋄ a
    !!!!
    
  3. Bir diziye atayabilirsiniz: A[3]←8beklediğiniz gibi. Ancak, aynı anda birden fazla öğe de atayabilirsiniz:, A[3 5 6]←9 1 4hatta A[3 5 6]←9hepsini aynı öğeye ayarlayarak. Elbette buraya da bir işlev ekleyebilirsiniz . İşlev daha sonra, yaptığınız gibi, her bir elemana ayrı olarak uygulanacaktır .

  4. Arkadaşın, bu konuda mutlu görünmese bile.

    1. Eğer Fdiyadik olduğu diyadik argümanları geçer: a F b<-> b F⍨ a. Golf yaparken kullanışlıdır, çünkü sizi parantez kullanmaktan kurtarabilir:

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

      Bu, sağ el her zaman sol elden önce değerlendirildiği için değerlendirme sırasını değiştirir.

    2. Eğer Fdiyadik olduğunu monadic fonksiyonunun her iki tarafa da aynı argümanı geçerlidir:

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

      Argüman sadece bir kez değerlendirilir. Bu özellikle dış ürünlerle birlikte kullanışlıdır, yani bir dizideki her bir değeri aynı dizideki diğer değerlerle karşılaştırmak için, kullanmak ∘.=⍨yerine kullanabilirsiniz x∘.=x←(whatever).

    3. Eğer Fmonadik ise , hiçbir şey yapmaz, ancak işlevi argümandan ayırır. Bu nedenle eğer işlev karmaşıksa, sizi parantezlerden kurtarabilir:

            {⍵+3}⍣5 6
            ∇{⍵+3}              
           ∇ ⍣ 5 6              
            ({⍵+3}⍣5)6
      21
            {⍵+3}⍣5⍨6
      21
      
  5. Deyimleri öğren! Sonra deyimler golf. Örneğin:

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

    mekanik olarak dönüştürülebilir:

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

    ve daha sonra:

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

    (ilk) 1↑bu durumda (bir ) ile eşdeğer olmak . Ve muhtemelen:

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

    (taksitli) ⊃⍴skalarlar hariç herkes için (şeklin ilk elemanı ) eşdeğerdir .


Ahududu pi sürümüne sahip olmanın yanı sıra ücretsiz bir lisans almak için bir yolu var mı?
Fabinout

Belli ki almanın yasal bir yolu.
Fabinout

2
@Fabinout: dyalog.com adresinde ücretsiz bir Windows sürümü indirebilirsiniz. "İndirme Bölgesi" ni ve ardından "Kayıtsız İndirme" seçeneğini tıklayın. Sizi kayıt altına alacak, aksi halde tamamen işlevsel ve özgür ve hukuki. Öğrenciyseniz, normal formunu ücretsiz doldurarak bir form doldurabilirsiniz. Korsanlık için hayatını mahvettiği bir ülkede yaşamıyorsan, ne yapacağını biliyorsun.
marinus

Ayrıca, Dyalog'dan (ve bazı hatalardan) daha fazla özelliği olan bir açık kaynak uygulaması olan Nars2000 de bulunmaktadır.
Tobia

1
GNU APL var.
M. Alaggan

14

Trenler

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

Bu, gelecekteki okuyucular uğruna, Oberon'a nasıl kısaltılacağını söylemememiz gerektiği anlamına mı geliyor?
Adám

Hayır, normalde PPCG'de yaptığınız gibi yapın. İfade en kısa sürede (olabileceğime inanıyorum) ulaştıktan sonra bu satırı kaldıracağım. Bu kolay bir egzersiz - Kişisel olarak bundan faydalanabileceğini sanmıyorum.
ngn

16'ya indirebilirim, ama senin ipuçlarından hiçbirini kullanmıyorum, o yüzden belki de yolumu kapatıyorum.
Adám

@ Adám peki, bir tren kullanıyorsunuz :) benimki benzerdi ama daha uzun çünkü ⎕ML
ngn

Bu " sağdan 3 kişilik gruplar " değil mi?
Adám

7

Trenlerle /ve trenlerle uğraşmak için püf noktaları

Ne zaman trenler kullanarak size indirim kullanmak isteyebilirsiniz f/toplamı gibi +/ve hatta çoğaltmak azaltılması //. Bununla birlikte, treninizin azaltma işleminin solunda daha fazla bölümü varsa, üstüne oluşturmak için parantez gerekir. İşte bayt kurtarmak için bazı püf noktaları.

1∊Monadik ∨/veya ∨⌿Boolean dizileri yerine kullanın

Görev: İki eşit uzunluktaki A ve B dizeleri göz önüne alındığında, A ve B'nin karşılık gelen karakterlerinin her ikisi de eşitse, 2 döndürün. Örneğin A←'abc've B←'def'verir 0ve A←'abc've B←'dec'verir 2.

Bir dfn çözümü olabilir, A{2×∨/⍺=⍵}Bancak zımni yaparak kısaltmak istiyorsunuz. A(2×∨/=)Bişe yaramayacak çünkü tren oluşum kuralları 2 (× ∨/ =)bunu istediğiniz gibi ayrıştırıyor 2 × (∨/=).

Bunu ∨/veya ∨⌿bir Boolean vektöründe ( ∨/,veya ∨⌿,daha yüksek dereceli diziler için) var olup olmadığını sorar, yani 1∊treni şu şekilde yazabiliriz 2×1∊=.

Bunun doğru argümanını ortaya çıkardığına dikkat edin, böylece her bir satırı veya sütunu ayrı ayrı azaltmak için kullanamazsınız.

Kullanım 1⊥yerine monadic ait +/veya+⌿

Görev: L listelerinin ve N dizininin bir listesi göz önüne alındığında, Nci listenin toplamını üç kere döndürün. Örn L←(3 1 4)(2 7)ve N←1verir 24.

Bir dfn çözümü olabilir, N{3×+/⍺⊃⍵}Lancak zımni yaparak kısaltmak istiyorsunuz. N(3×+/⊃)Lişe yaramayacak çünkü tren oluşum kuralları 3(× +/ ⊃)bunu istediğiniz gibi ayrıştırıyor 3 × (+/⊃).

Unary (sayı-1) 'deki bir sayı listesinin değerlendirilmesinin listenin toplanmasına eşdeğer olduğunu gözlemleyin, çünkü because { a , b , c , d } =  a + b + c + d  = ( a × 1³) + ( b × 1² ) + ( c × 1¹) + ( d × 1⁰). Bu nedenle +/a b c d, aynı 1⊥a b c dve treni de aynı şekilde yazabiliriz 3×1⊥⊃.

Yüksek rütbeli argümanlarda, 1⊥bunun eşdeğeri olduğuna dikkat edin +⌿.

Skaler ve / veya vektör argümanları f.gyerine kullanınf/g

Görev: L ve N sayısının bir listesi verildiğinde, L'nin elemanları NEg'ye bölündüğünde L←31 41 59ve N←7verdiğinde , 1. aralığı, minimum bölme kalanı sayısının sonuna kadar döndürün 1 2 3.

Bir dfn çözümü olabilir, N{⍳⌊/⍺|⍵}Lancak zımni yaparak kısaltmak istiyorsunuz. N(⍳⌊/|)Lişe yaramayacak çünkü tren oluşum kuralları ⍳ (⌊/) |bunu istediğiniz gibi ayrıştırıyor ⍳ (⌊/|).

A f.g BSkaler iki iç çarpımı , argümanlar skaler ve / veya vektörler olduğu zaman aynıdır, f/ A g Bikisi de (A[1] g B[1]) f (A[2] g B[2]) f (A[3] g B[3])vb. İle aynıdır , bu yüzden treni şu şekilde yazabiliriz ⍳⌊.|.

Bunun yüksek dereceli diziler için çalışmadığını unutmayın.

Boolean left ve simple vector right argümanları ∊⊆yerine kullanın/

Görev: Bir L listesi ve bir N numarası verildiğinde, yalnızca N'den büyük sayıların kalması için listeyi filtreleyin. Örn L←3 1 4ve N←1verir 3 4.

Bir dfn çözümü olabilir, N{(⍺<⍵)/⍵}Lancak bunu yapıp kısalmak istersiniz. N(</⊢)LBağlayıcı kurallar bunu ayrıştıracağı için çalışmayacak, (</) ⊢ancak operatörün azaltmasından ziyade /işlev kopyası olmak istiyorsunuz .

Diyadik bir BooleANDile sol argüman 1s ishal göre argüman bölümler sağ argüman sol bırakarak elemanları 0s ile gösterilir. Neredeyse istediğimiz bu, istenmeyen bölümlere ayırmak. Ancak, monadik uygulayarak bölümlemeden kurtulabiliriz . Böylece {(⍺<⍵)/⍵}olabilir {∊(⍺<⍵)⊆⍵}ve böylece trenimizi olarak yazabiliriz ∊<⊆⊢.

Bunun yüksek dereceli diziler için çalışmadığını unutmayın.

0⊥Bunun yerine ⊢/veya ⊢⌿sayısal değişkenlerle kullanın

Görev: ayağın en sağdaki eleman içeren bir liste L ve bir numara N, çarpma N Verilen L←3 1 4ve N←2verir 8.

Bir dfn çözümü olabilir, N{⍺×⊢/⍵}Lancak zımni yaparak kısaltmak istiyorsunuz. N(⊣×⊢/⊢)Lişe yaramayacak çünkü tren oluşum kuralları ⊣ (× ⊢/ ⊢)bunu istediğiniz gibi ayrıştırıyor ⊣ × (⊢/⊢).

0⊥Sayısal bir dizideki ile aynı olduğuna dikkat edin ⊢⌿, böylece trenimizi şu şekilde yazabiliriz ⊣×0⊥⊢.

Bunun, yüksek dereceli dizilerin son ana hücresini seçtiğini unutmayın.



1
@ J. Sallé Eklendi.
Ad

7

Çarpma işlemini toplama ile birleştirmek için kullanın

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

Varsayımlar:

  • ave bsol argüman olarak kullanıldığında parantez gerektirmeyen terimlerdir.

  • C sol argüman olarak kullanıldığında parantez içinde olması gereken bir ifadedir.

  • a b C sayısal skalarları değerlendirebilir


5

Karışık sayılar

Genellikle göz ardı edilir, ızgaralar, labirentler, fraktallar veya geometriyle ilgili ifadeleri kısaltmak için harika fırsatlar sunarlar.

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

İndeksleme modülü vektör uzunluğu

⊃i⌽agenellikle saflıktan daha kısadır ⊃a[(≢a)|i]veya a⊃⍨i|⍨≢a( abir vektör ve itam sayıdır ve ⎕io0'dır)

(işaret için teşekkürler EriktheOutgolfer) bu konuda yararlı bir çeşididir: I↑Y⌽⍨I×Xnerede Ybazı uzunluk- birleşimidir Ivektörler ve Xbiz örneğin almak istiyorum birinin endeksidir:3↑'JanFeb...Dec'⌽⍨3×month


3

Sabit fonksiyonlar

=⍨ve ≠⍨ngn sayesinde.

Bazen bir listenin her elemanı için sadece tek bir değere ihtiyacınız vardır. Eğer kullanım için cazip olabilir iken {value}¨, bu kullanıma kısadır value⊣¨ ama bazı ortak değerler için, siz (kullanarak daha kısa alabilirsiniz ⎕IO←0):

¯1ile ⍬⍸list

0ile ⍬⍳list

1ile ⍬⍷list

Bunların yalnızca listelerde işe yaradığını unutmayın (yuvalanmış olabilirler). Daha yüksek dereceli diziler için, tüm 0'ları ve tüm 1'leri elde etmek için aşağıdakileri kullanabilirsiniz:

1ile =⍨

0ile ≠⍨

Ayarladıysanız ⎕ML←0, tüm sayılar aşağıdaki gibi sıfırlarla (sanki ) yapılabilir

Yalnızca tek bir numara gerekiyorsa, monadic kullanmak mümkün olabilir kullanmak yerine 1 veya 0 olsun 1⊣ya 0⊣.


Bazen listenin her öğesi için tek bir değere ihtiyacınız olur. ” - Dikkate değer olabilir: bu değer listenin ilk öğesi olduğunda, kullanabilirsiniz⊣\
ngn

@ ngn Bunu söyleyebilirim ve ile /ve kendi başlarına değer.
Adám

2

kullanım

Parantez kullanmaktan kaçının

(Commute) parantezleri önleyerek sizi baytlardan kurtarabilir. Sol argümanın parantez içinde alınması gereken ve sağ argümanın olmadığı bir işleve sahip olduğunuzda, bir baytı, örneğin (A<B)÷C→ kaydedebilirsiniz C÷⍨A<B.

Çift dizileri

Bir dizinin kopyasını sonuna eklemek için ,⍨Aveya düğmesini kullanın ⍪⍨A.

Çift sayılar

İkiye 2∘×katlamak yerine +⍨, argümanı kendine eklediği için kullanabilirsiniz : 1+2∘×1++⍨.

Kare sayılar

2*⍨YKareye kullanmak yerine ×⍨Y, argümanı kendisiyle çarptığı için kullanabilirsiniz : 2*⍨A+B×⍨A+B.

Rasgele permütasyon

?⍨Nsize rastgele uzunluktaki bir permütasyon verecek N.

Kendinden sınıflandırmak

Her ana hücrenin ilk oluşum indekslerini bulun ⍳⍨A

Boolean vektöründeki sondaki 1leri say

İçinde +/∧\⌽Bkaç iz bıraktığını saymak yerine, onu Nkullanabilirsin ⊥⍨.

Ters kompozisyon

A f∘g Bise A f g B, ancak isterseniz (g A) f B, kullanım f⍨∘g⍨.

Ters azaltın

f/ a1 a2 a3olduğunu a1 f (a2 f a3). İstersen (a1 f a2) f a3kullan f⍨/⌽.

Ters tarama

f\ A B Colduğunu
A (A f B) (A f (B f C)).

f⍨/∘⌽¨,\ A B Colduğunu
A (A f B) ((A f B) f C).

f⍨\⌽ A B Colduğunu
((A f B) f C) (B f C) C.

⌽f/∘⌽¨,\⌽ A B C. olduğunu
(A f (B f C)) (B f C) C.


2

Dize olmayan karakterleri numaralandırmak ⍳≢

Görev: Verilen iki karakter, S ve T, birleştirme indekslerini listeler. Örn S←'abcd've T←'xyz'verir 1 2 3 4 5 6 7.

Bir dfn çözümü olabilir, S{⍳≢⍺,⍵}Tancak bunu yapıp kısalmak istersiniz. ⍳≢,çalışmayacaktır çünkü tren ayrıştırma kuralları (⍳)≢(,)bunu istediğiniz gibi ayrıştırır (⍳≢),.

Boş bir sol argüman olan Dyadiç , şu anki sırasına göre basit karakter dizileridir ⍳≢; Böylece {⍳≢⍺,⍵} olabilir {⍬⍋⍺,⍵}, böylece trenimizi olarak yazabiliriz ⍬⍋,.

Bunun sayısal veya karma diziler için çalışmadığını unutmayın.


Vay, bunun bir şey olduğunu bilmiyordum.
Zacharı
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.