Lời khuyên cho việc chơi golf trong APL


28

Tôi đã bắt đầu một thử thách golf mã gần đây và có vẻ như người chiến thắng là GolfScript (ngạc nhiên, ngạc nhiên!). Điều thú vị là có một đối thủ cạnh tranh rất mạnh khác có tất cả cơ hội để chiến thắng GolfScript. Tên của nó là APL. Tôi thấy rất nhiều câu trả lời được viết bằng APL ở đây. Có vẻ như ngôn ngữ này khá hiệu quả đối với việc chơi golf mã, vì vậy tôi quyết định hỏi bất kỳ mẹo chơi golf mã nào bạn biết cho các chương trình APL. Hãy đăng một số ví dụ mã. Nó thường rất thú vị để xem ngôn ngữ trong hành động.

Câu trả lời:


23

Chỉnh sửa : đối với những người đang đọc điều này, những người không biết gì về APL nhưng muốn đưa nó lên, Làm chủ Dyalog APL là một tài nguyên rất tốt.

  1. Đánh giá là đúng từ phải sang trái. Điều này bao gồm các biến thiết lập, vì vậy hãy tận dụng nó.

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

    ađược đặt thành 1, 1+ađánh giá 2, a,2đánh giá 1 22+1 2đánh giá 3 4.

  2. Giống như C, có thể được kết hợp với một chức năng, tức là a +← 3. Không giống như C, đây là chung: foo F← barđặt foothành F bar. Một cách vô tình, như một biểu hiện này trở lại bar, không F bar.

    Nó cũng hoạt động với các chức năng ẩn danh:

          a←0
          a+←3 ⋄ a
    3
          a+←3 ⋄ a
    6
          a { ⍵/'!' } ←4 ⋄ a
    !!!!
    
  3. Bạn có thể gán cho một mảng : A[3]←8, như bạn mong đợi. Nhưng bạn cũng có thể gán nhiều mục cùng một lúc : A[3 5 6]←9 1 4, hoặc thậm chí A[3 5 6]←9, đặt tất cả chúng vào cùng một mục. Tất nhiên, bạn cũng có thể thêm một chức năng vào đây. Hàm này sau đó sẽ được áp dụng cho từng phần tử riêng biệt, như thể bạn đã làm .

  4. là bạn của bạn, ngay cả khi anh ta không quá vui về điều đó.

    1. Nếu Flà dyadic, dyadic chuyển các đối số: a F b<-> b F⍨ a. Điều này rất hữu ích khi chơi golf vì nó có thể giúp bạn không phải sử dụng niềng răng:

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

      Điều này không thay đổi thứ tự đánh giá, vì tay phải luôn được đánh giá trước tay trái.

    2. Nếu Flà dyadic, monadic áp dụng cùng một đối số cho cả hai mặt của hàm:

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

      Đối số chỉ được đánh giá một lần. Điều này đặc biệt hữu ích với các sản phẩm bên ngoài, tức là để so sánh từng giá trị trong một mảng với các giá trị khác trong cùng một mảng, bạn có thể sử dụng ∘.=⍨thay vì phải làm x∘.=x←(whatever).

    3. Nếu Flà đơn âm, không làm gì cả, nhưng nó tách chức năng khỏi đối số. Vì vậy, nó vẫn có thể giúp bạn tiết kiệm niềng răng nếu chức năng phức tạp:

            {⍵+3}⍣5 6
            ∇{⍵+3}              
           ∇ ⍣ 5 6              
            ({⍵+3}⍣5)6
      21
            {⍵+3}⍣5⍨6
      21
      
  5. Học thành ngữ! Sau đó đánh golf các thành ngữ. Ví dụ:

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

    có thể được chuyển đổi cơ học thành:

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

    và sau đó tiếp tục vào:

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

    (đầu tiên) tương đương với 1↑(lấy một) trong trường hợp này. Và có thể:

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

    (kiểm đếm) tương đương với ⊃⍴(yếu tố đầu tiên của hình dạng) cho tất cả trừ vô hướng.


Có cách nào để có được giấy phép miễn phí bên cạnh việc có phiên bản raspberry pi không?
Fabinout

Một cách hợp pháp để có được nó, rõ ràng.
Fabinout

2
@Fabinout: Tại dyalog.com bạn có thể tải xuống phiên bản Windows miễn phí. Nhấp vào "Vùng tải xuống" và sau đó "Tải xuống chưa đăng ký". Nó sẽ cằn nhằn bạn đăng ký nhưng nếu không thì nó đầy đủ chức năng và miễn phí và hợp pháp. Nếu bạn là sinh viên, bạn có thể nhận phiên bản bình thường miễn phí bằng cách điền vào biểu mẫu. Nếu bạn không sống ở một đất nước nơi họ hủy hoại cuộc sống của bạn vì vi phạm bản quyền, thì bạn biết phải làm gì.
bến tàu

Ngoài ra còn có Nars2000, một triển khai mã nguồn mở có nhiều tính năng hơn Dyalog (và một số lỗi.) Một số tính năng của nó có ích cho việc chơi gôn, chẳng hạn như các hàm số nguyên tố hoặc đa số.
Tobia

1
Có GNU APL.
M. Alaggan

14

Xe lửa

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

Điều đó có nghĩa là vì lợi ích của độc giả trong tương lai, chúng ta không nên nói với Oberon cách rút ngắn nó?
Adám

Không, làm như bạn thường làm trên PPCG. Tôi sẽ xóa dòng đó sau khi biểu thức đạt được (cái mà tôi tin là) ngắn nhất. Đây là một bài tập dễ dàng - Tôi không nghĩ cá nhân bạn sẽ được hưởng lợi từ nó.
ngn

Tôi có thể giảm xuống còn 16, nhưng tôi không sử dụng bất kỳ mẹo nào của bạn, vì vậy có lẽ tôi sẽ bỏ đi.
Adám

@ Adám tốt, bạn đang sử dụng một chuyến tàu :) tôi cũng tương tự nhưng lâu hơn vì tôi không nghĩ đến ⎕ML
ngn

Không phải là "nhóm 3 từ bên phải " sao?
Adám

7

Thủ thuật để đối phó /trong xe lửa

Khi sử dụng xe lửa, bạn có thể muốn sử dụng các mức giảm f/như tổng +/hoặc thậm chí nhân rộng //. Tuy nhiên, nếu đoàn tàu của bạn có nhiều phần ở bên trái của phần giảm, bạn cần có dấu ngoặc đơn để tạo một đỉnh. Dưới đây là một số thủ thuật để lưu byte.

Sử dụng 1∊thay vì đơn âm ∨/hoặc ∨⌿trên mảng Boolean

Nhiệm vụ: Cho hai chuỗi A và B có độ dài bằng nhau, trả về 2 nếu bất kỳ ký tự tương ứng nào của A và B bằng nhau, 0 nếu không. Ví dụ A←'abc'B←'def'cho 0A←'abc'B←'dec'cho 2.

Một giải pháp dfn có thể được A{2×∨/⍺=⍵}Bnhưng bạn muốn rút ngắn nó bằng cách đi ngầm. A(2×∨/=)Bsẽ không hoạt động bởi vì các quy tắc hình thành tàu phân tích điều này như 2 (× ∨/ =)nhưng bạn muốn 2 × (∨/=).

Quan sát rằng ∨/hoặc ∨⌿trên một vectơ Boolean ( ∨/,hoặc ∨⌿,cho các mảng thứ hạng cao hơn) hỏi xem có bất kỳ 1 hiện tại nào không 1∊, vì vậy chúng ta có thể viết chuyến tàu của mình dưới dạng 2×1∊=.

Lưu ý rằng phá hủy đối số đúng của nó, vì vậy bạn không thể sử dụng nó để giảm từng hàng hoặc cột riêng biệt.

Sử dụng 1⊥thay vì đơn nguyên +/hoặc+⌿

Nhiệm vụ: Đưa ra danh sách danh sách L và chỉ số N, trả về ba lần tổng của danh sách thứ N. Ví dụ L←(3 1 4)(2 7)N←1cho 24.

Một giải pháp dfn có thể được N{3×+/⍺⊃⍵}Lnhưng bạn muốn rút ngắn nó bằng cách đi ngầm. N(3×+/⊃)Lsẽ không hoạt động bởi vì các quy tắc hình thành tàu phân tích điều này như 3(× +/ ⊃)nhưng bạn muốn 3 × (+/⊃).

Quan sát rằng việc đánh giá danh sách các số trong unary (cơ số 1) tương đương với tổng hợp danh sách vì ∑ { a , b , c , d } =  a + b + c + d  = ( a × 1³) + ( b × 1² ) + ( c × 1¹) + ( d × 1⁰). Vì vậy +/a b c d, giống như 1⊥a b c d, và chúng ta có thể viết tàu của chúng tôi là 3×1⊥⊃.

Lưu ý rằng trên các đối số cấp cao hơn, 1⊥tương đương với +⌿.

Sử dụng f.gthay vì f/gvới các đối số vô hướng và / hoặc vector

Nhiệm vụ: Cho một danh sách L và một số N, trả về phạm vi 1 triệt để số phần còn lại của phép chia tối thiểu khi các phần tử của L được chia cho NEg L←31 41 59N←7cho 1 2 3.

Một giải pháp dfn có thể được N{⍳⌊/⍺|⍵}Lnhưng bạn muốn rút ngắn nó bằng cách đi ngầm. N(⍳⌊/|)Lsẽ không hoạt động bởi vì các quy tắc hình thành tàu phân tích điều này như ⍳ (⌊/) |nhưng bạn muốn ⍳ (⌊/|).

Sản phẩm bên trong A f.g Bcủa hai hàm vô hướng khi các đối số là vô hướng và / hoặc vectơ giống như f/ A g Bvì cả hai đều (A[1] g B[1]) f (A[2] g B[2]) f (A[3] g B[3])v.v., vì vậy chúng ta có thể viết chuyến tàu của mình là ⍳⌊.|.

Lưu ý rằng điều này không hoạt động cho các mảng cấp cao hơn.

Sử dụng ∊⊆thay vì /với Boolean bên trái và các đối số vector bên phải đơn giản

Nhiệm vụ: Đưa ra danh sách L và số N, lọc danh sách sao cho chỉ còn lại số lớn hơn N. Ví dụ L←3 1 4N←1cho 3 4.

Một giải pháp dfn có thể N{(⍺<⍵)/⍵}Lnhưng bạn muốn rút ngắn nó bằng cách đi ngầm. N(</⊢)Lsẽ không hoạt động vì các quy tắc ràng buộc sẽ phân tích cú pháp này (</) ⊢nhưng bạn muốn /trở thành chức năng sao chép thay vì toán tử giảm .

Dyadic với một đối số bên trái Boolean phân vùng đối số bên phải theo các lần chạy 1s trong đối số bên trái, bỏ các phần tử được chỉ định bởi 0s. Đây gần như là những gì chúng ta muốn, tiết kiệm cho phân vùng không mong muốn. Tuy nhiên, chúng ta có thể thoát khỏi phân vùng bằng cách áp dụng đơn âm . Do đó {(⍺<⍵)/⍵}có thể trở thành {∊(⍺<⍵)⊆⍵}và do đó chúng ta có thể viết tàu của chúng tôi như ∊<⊆⊢.

Lưu ý rằng điều này không hoạt động cho các mảng cấp cao hơn.

Sử dụng 0⊥thay vì ⊢/hoặc ⊢⌿với các đối số số

Nhiệm vụ: Cho một danh sách L và một số N, nhân N với phần tử ngoài cùng bên phải của LEg L←3 1 4N←2cho 8.

Một giải pháp dfn có thể được N{⍺×⊢/⍵}Lnhưng bạn muốn rút ngắn nó bằng cách đi ngầm. N(⊣×⊢/⊢)Lsẽ không hoạt động bởi vì các quy tắc hình thành tàu phân tích điều này như ⊣ (× ⊢/ ⊢)nhưng bạn muốn ⊣ × (⊢/⊢).

Quan sát rằng 0⊥trên một mảng số giống như ⊢⌿, vì vậy chúng ta có thể viết chuyến tàu của mình là ⊣×0⊥⊢.

Lưu ý rằng điều này chọn ô chính cuối cùng của mảng thứ hạng cao hơn.


1
Có lẽ bạn có thể thêm câu trả lời trò chuyện này vào câu hỏi này?
J. Sallé

1
@ J.Sallé Đã thêm.
Adám

7

Sử dụng để kết hợp phép nhân với phép cộng

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

Giả định:

  • ablà các thuật ngữ không yêu cầu dấu ngoặc đơn khi được sử dụng làm đối số bên trái

  • C là một biểu thức có thể cần dấu ngoặc đơn khi được sử dụng làm đối số bên trái

  • a b C đánh giá vô hướng số


5

Số phức

Thường bị bỏ qua, họ đưa ra những cơ hội tuyệt vời để rút ngắn các biểu thức liên quan đến lưới, mê cung, fractals hoặc hình học.

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

Lập chỉ mục chiều dài vector modulo

⊃i⌽athường ngắn hơn ngây thơ ⊃a[(≢a)|i]hoặc a⊃⍨i|⍨≢a(trong đó alà một vectơ và ilà một số nguyên và ⎕iolà 0)

một biến thể hữu ích về vấn đề này (nhờ EriktheOutgolfer để chỉ ra) là: I↑Y⌽⍨I×Xnơi Ylà nối của một số length- Ivectơ và Xlà chỉ số của một chúng tôi muốn lựa chọn, ví dụ:3↑'JanFeb...Dec'⌽⍨3×month


3

Hàm hằng

=⍨≠⍨cảm ơn ngn.

Đôi khi bạn chỉ cần một giá trị duy nhất cho mỗi thành phần của danh sách. Mặc dù bạn có thể muốn sử dụng {value}¨, nó ngắn hơn để sử dụng value⊣¨ nhưng đối với một số giá trị phổ biến, bạn có thể thậm chí còn ngắn hơn (sử dụng ⎕IO←0):

¯1s với ⍬⍸list

0s với ⍬⍳list

1s với ⍬⍷list

Lưu ý rằng chúng chỉ hoạt động trên danh sách (mặc dù chúng có thể được lồng nhau). Đối với mảng thứ hạng cao hơn, bạn có thể sử dụng các mục sau để nhận tất cả 0 và tất cả 1:

1s với =⍨

0s với ≠⍨

Nếu bạn đặt ⎕ML←0, tất cả các số có thể được tạo thành số không (như thể ) với:

Nếu bạn chỉ cần một số duy nhất, bạn có thể sử dụng đơn âm để nhận 1 hoặc 0 thay vì sử dụng 1⊣hoặc 0⊣.


" Đôi khi bạn chỉ cần một giá trị duy nhất cho mỗi thành phần của danh sách. " - Có thể đáng chú ý: khi giá trị đó là thành phần đầu tiên của danh sách, bạn có thể sử dụng⊣\
ngn

@ngn Tôi muốn nói điều đó với /khen một bài đăng của riêng họ.
Adám

2

Sử dụng

Tránh dấu ngoặc đơn

(Đi lại) có thể giúp bạn tiết kiệm byte bằng cách tránh dấu ngoặc đơn. Bất cứ khi nào bạn có một hàm trong đó đối số bên trái cần được ngoặc đơn và đối số bên phải không có, bạn có thể lưu một byte, ví dụ (A<B)÷CC÷⍨A<B.

Mảng kép

Để nối một bản sao của một mảng vào cuối của nó, sử dụng ,⍨Ahoặc ⍪⍨A.

Số đôi

Thay vì sử dụng 2∘× để nhân đôi, bạn có thể sử dụng +⍨vì nó thêm đối số vào chính nó: 1+2∘×1++⍨.

Số vuông

Thay vì sử dụng 2*⍨Y để bình phương, bạn có thể sử dụng ×⍨Yvì nó nhân đối số với chính nó: 2*⍨A+B×⍨A+B.

Hoán vị ngẫu nhiên

?⍨Nsẽ cung cấp cho bạn một hoán vị ngẫu nhiên của chiều dài N.

Tự phân loại

Tìm các chỉ số xuất hiện đầu tiên của mỗi ô chính với ⍳⍨A

Đếm số 1 trong vectơ Boolean

Thay vì +/∧\⌽Bđếm có bao nhiêu số 1 trong đó Nbạn có thể sử dụng⊥⍨ .

Thành phần ngược

A f∘g BA f g B, nhưng nếu bạn muốn (g A) f B, sử dụngf⍨∘g⍨ .

Giảm ngược

f/ a1 a2 a3a1 f (a2 f a3). Nếu bạn muốn (a1 f a2) f a3, sử dụngf⍨/⌽ .

Quét ngược

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

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

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

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


2

Liệt kê các ký tự trong một chuỗi mà không có ⍳≢

Nhiệm vụ: Cho hai chuỗi, S và T, liệt kê các chỉ số của phép nối của chúng. Ví dụ S←'abcd'T←'xyz'cho1 2 3 4 5 6 7 .

Một giải pháp dfn có thể S{⍳≢⍺,⍵}Tnhưng bạn muốn rút ngắn nó bằng cách đi ngầm. ⍳≢,sẽ không hoạt động vì các quy tắc phân tích cú pháp tàu sẽ phân tích cú pháp này như (⍳)≢(,)nhưng bạn muốn(⍳≢), .

Dyadic với một đối số bên trái trống xếp các mảng ký tự đơn giản theo thứ tự hiện tại của chúng, giống như ⍳≢. Do đó {⍳≢⍺,⍵} có thể trở thành {⍬⍋⍺,⍵}, vì vậy chúng ta có thể viết chuyến tàu của mình như⍬⍋, .

Lưu ý rằng điều này không hoạt động cho các mảng số hoặc hỗn hợp.


Wow, không biết đó là một điều.
Zacharý
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.