Lời khuyên cho việc chơi golf ở CJam


43

CJam là một ngôn ngữ chơi gôn dựa trên ngăn xếp lấy cảm hứng từ GolfScript, được tạo bởi người dùng aditsu của PPCG .

Vì vậy, trong các câu hỏi mẹo ngôn ngữ cụ thể khác:

Bạn có lời khuyên chung nào cho việc chơi golf ở CJam? Xin vui lòng gửi một lời khuyên cho mỗi câu trả lời.


4
Xem thêm Mẹo để chơi gôn trong GolfScript ; các ngôn ngữ tương tự nhau đến mức nhiều thủ thuật có thể được điều chỉnh theo một trong hai cách.
Ilmari Karonen

2
@IlmariKaronen Sau khi xem qua các câu trả lời trong câu hỏi đó, tôi chỉ nói rằng khoảng một nửa trong số đó áp dụng cho CJam, do sự khác biệt về cú pháp hoặc logic trong các ngôn ngữ.
Trình tối ưu hóa

Câu trả lời:


23

Modulo đúng cho số âm

Điều thường gây khó chịu là kết quả của phép toán modulo có cùng dấu với toán hạng đầu tiên. Ví dụ -5 3%cho -2thay vì 1. Thường xuyên hơn không bạn muốn sau này. Cách khắc phục ngây thơ là áp dụng modulo, thêm ước số một lần và áp dụng lại modulo:

3%3+3%

Nhưng đó là dài và xấu. Thay vào đó, chúng ta có thể sử dụng thực tế là mảng chỉ mục luôn là mô-đun và làm việc một cách chính xác với chỉ số tiêu cực. Vì vậy, chúng tôi chỉ cần biến ước số thành một phạm vi và truy cập vào đó:

3,=

Áp dụng cho -5, điều này mang lại 1như mong đợi. Và nó chỉ dài hơn một byte so với tích hợp %!

Nếu mô-đun có công suất bằng 2, bạn có thể lưu một byte khác bằng cách sử dụng số học bitwise (cũng nhanh hơn rất nhiều). So sánh:

32,=
31&

Đối với trường hợp đặc biệt của 65536 == 2^16một byte khác có thể được lưu bằng cách sử dụng hành vi gói của kiểu ký tự:

ci

13

Đẩy phạm vi ký tự nối

  • Chuỗi chứa tất cả các chữ số "0123456789"có thể được viết là

    A,s
    
  • Các chữ cái ASCII chữ hoa ( A-Z) có thể được đẩy như

    '[,65>
    

    tạo chuỗi của tất cả các ký tự lên đến Z , sau đó loại bỏ 65 đầu tiên (tối đa @ ).

  • Tất cả các chữ cái ASCII ( A-Za-z) có thể được đẩy như

    '[,65>_el+
    

    hoạt động như trên, sau đó tạo một bản sao, chuyển đổi thành chữ thường và nối thêm.

    Nhưng có một cách ngắn hơn để làm điều đó!

    Sau đó, ^toán tử thường bị bỏ qua (sự khác biệt đối xứng cho danh sách) cho phép tạo cùng một phạm vi trong khi lưu ba byte:

    '[,_el^
    

    '[,tạo phạm vi của tất cả các ký tự ASCII lên đến Z , _eltạo một bản sao chữ thường và ^chỉ giữ các ký tự của cả hai chuỗi xuất hiện trong một nhưng không phải cả hai.

    Vì tất cả các chữ cái trong chuỗi đầu tiên là chữ hoa, tất cả các chữ cái thứ hai là chữ thường và tất cả các ký tự không phải là chữ cái đều ở cả hai chuỗi, kết quả là chuỗi các chữ cái.

  • Bảng chữ cái RFC 1642 Base64 ( A-Za-z0-9+/) có thể được đẩy bằng cách sử dụng kỹ thuật trên và nối thêm các chữ cái không:

    '[,_el^A,s+"+/"+
    

    Một cách ngắn không kém để đẩy chuỗi này chỉ sử dụng các khác biệt đối xứng:

    "+,/0:[a{A0":,:^
    

    Làm thế nào chúng ta có thể tìm thấy chuỗi ở đầu?

    Tất cả các dãy nhân vật đã qua sử dụng ( A-Z, a-z, 0-9, +, /) có thể được đẩy bằng chênh lệch đối xứng của để phạm vi đó bắt đầu từ byte null, cụ thể là 'A,'[,^, 'a,'{,^, '0,':,^, '+,',,^'/,'0,^.

    Do đó, thực thi :,:^trên "A[a{):+,/0"sẽ đẩy các ký tự mong muốn, nhưng không theo đúng thứ tự.

    Làm thế nào để chúng ta tìm thấy thứ tự đúng? Lực lượng vũ trang để giải cứu! Chương trình

    '[,_el^A,s+"+/"+:T;"0:A[a{+,/0"e!{:,:^T=}=
    

    lặp lại trên tất cả các hoán vị có thể có của chuỗi, áp dụng :,:^và so sánh kết quả với đầu ra mong muốn ( permalink ).

  • Bảng chữ cái radix-64 được sử dụng, ví dụ, bằng crypt ( .-9A-Za-z) có thể được tạo bằng phương thức trên:

    ".:A[a{":,:^
    

    Đây là phương pháp ngắn nhất mà tôi biết.

    Vì tất cả các ký tự trong đầu ra mong muốn đều theo thứ tự ASCII, việc lặp lại các hoán vị là không cần thiết.

  • Không phải tất cả các phạm vi ký tự nối có thể được đẩy theo thứ tự mong muốn bằng cách sử dụng :,:^.

    Ví dụ, phạm vi 0-9A-Za-z;-?không thể được đẩy bằng cách thực hiện :,:^trên bất kỳ hoán vị nào của "0:A[a{;@".

    Tuy nhiên, chúng ta có thể tìm thấy một biến thể xoay của chuỗi mong muốn có thể, bằng cách sử dụng mã

    A,'[,_el^'@,59>]s2*:T;"0:A[a{;@"e!{:,:^T\#:I)}=Ip
    

    sẽ in ( permalink ) như sau:

    10
    0:@[a{A;
    

    Điều này có nghĩa rằng

    "0:@[a{A;":,:^Am>
    

    có tác dụng tương tự như

    A,'[,_el^'@,59>]s
    

    chỉ có thể được sử dụng với một ngăn xếp trống mà không cần trả trước a [.


11

Tránh {…}{…}?

Giả sử bạn có một số nguyên trên ngăn xếp. Nếu là số lẻ, bạn muốn nhân nó với 3 và thêm 1; nếu không bạn muốn chia nó cho 2.

Một câu lệnh "bình thường" nếu / khác sẽ trông như thế này:

_2%{3*)}{2/}?

Tuy nhiên, sử dụng các khối thường không phải là cách để đi, vì {}{}đã thêm bốn byte. ?cũng có thể được sử dụng để chọn một trong hai mục trên ngăn xếp:

_2%1$3*)@2/?

Đây là một byte ngắn hơn.


Khối-? với một tuyên bố nếu trống luôn luôn là không có. Ví dụ,

{}{2/}?

dài hơn hai byte

{2/}|

Nếu thay vào đó bạn có

{2/}{}?

và điều bạn đang kiểm tra là số nguyên không âm, bạn có thể làm

g)/

Cái mới {}&{}|tiện dụng, nhưng đôi khi có vấn đề nếu bạn không thể làm lộn xộn ngăn xếp.

Tuy nhiên, trong trường hợp

_{…}{;}?

thay vào đó, bạn có thể sử dụng một biến tạm thời:

:T{T…}&

1
!)/g)/ngắn hơn trong các ví dụ.
jimmy23013

11

Chuyển báo cáo

CJam không có báo cáo chuyển đổi. Lồng nhau nếu các câu lệnh cũng hoạt động tốt, nhưng {{}{}?}{}?đã dài 12 byte ...

Nếu chúng ta có thể chuyển đổi điều kiện thành một số nguyên nhỏ, không âm, chúng ta có thể chuyển đổi tất cả các câu lệnh tình huống trong một chuỗi phân tách và đánh giá kết quả tương ứng.

Ví dụ: nếu chúng ta muốn thực thi code0nếu số nguyên của ngăn xếp là 0 , code1nếu là 1code2nếu là 2 , chúng ta có thể sử dụng

_{({code2}{code1}?}{;code0}?

hoặc là

[{code0}{code1}{code2}]=~

hoặc là

"code0 code1 code2"S/=~

S/tách chuỗi thành ["code0" "code1" "code2"], =trích xuất đoạn tương ứng và ~đánh giá mã.

Nhấn vào đây để xem các tuyên bố chuyển đổi trong hành động.

Cuối cùng, như được đề xuất bởi @ jimmy23013 và @RetoKoradi, chúng tôi có thể rút ngắn công tắc hơn nữa trong một số trường hợp. Say code0, code1code2có độ dài L 0 , L 1L 2 , tương ứng.

Nếu L 0 = L 1 L 2

"code0code1code2"L/=~

có thể được sử dụng thay vào đó, nơi LL 0 . Thay vì chia tách tại một dấu phân cách, hãy /chia chuỗi thành các đoạn có độ dài bằng nhau ở đây.

Nếu L 0 L 1 ≥ L 2 L 0 - 1 ,

"cccooodddeee012">3%~

có thể được sử dụng thay thế. >loại bỏ 0, 1 hoặc 2 phần tử từ đầu chuỗi và 3%trích xuất mọi phần tử thứ ba (bắt đầu bằng phần tử thứ nhất).


Ví dụ cuối cùng, điều đó có lợi thế hơn "code0code1code2"5/=~không? Có vẻ đơn giản hơn nhiều đối với tôi, và nó có cùng chiều dài.
Reto Koradi

@RetoKoradi Nếu tất cả các đoạn có cùng độ dài, không có lợi thế. Đối với độ dài khác nhau, phương thức của bạn có thể ngắn hơn và dài hơn phương thức mô đun.
Dennis

11

Đánh gôn các giá trị mảng và chuỗi chung

Có một số mảng hoặc chuỗi ngắn nhất định mọc lên mỗi giờ, ví dụ, để khởi tạo lưới. Ngây thơ, những cái này có thể tốn 4 byte trở lên, vì vậy, đáng để tìm kiếm các hoạt động trên các giá trị tích hợp sẽ cho kết quả tương tự. Đặc biệt là chuyển đổi cơ sở thường hữu ích.

  • [0 1]có thể được viết là 2,.
  • [1 0]có thể được viết là YYb(tức là 2 trong nhị phân).
  • [1 1]có thể được viết là ZYb(tức là 3 trong nhị phân).
  • Ma trận [[0 1] [1 0]]có thể được viết là 2e!.
  • [LL] có thể được viết dưới dạng SS/(tách một khoảng trắng bằng khoảng trắng).
  • "\"\""có thể được viết là L`.
  • "{}"có thể được viết là {}s.

Cái sau có thể được mở rộng cho các trường hợp bạn muốn tất cả các loại khung lưu một byte khác:

  • "[{<()>}]"có thể được viết là {<()>}a`.
  • "()<>[]{}"có thể được viết là {<()>}a`$.

Đặc biệt là thủ thuật chuyển đổi cơ sở có thể hữu ích để ghi nhớ cho một số trường hợp che khuất bật lên mọi lúc mọi nơi. Ví dụ [3 2]sẽ là E4b(14 trong cơ sở 4).

Trong các trường hợp thậm chí hiếm hơn, bạn thậm chí có thể thấy toán tử nhân tố mfhữu ích. Ví dụ như [2 7]Emf.

Xin vui lòng mở rộng danh sách này nếu bạn gặp bất kỳ ví dụ nào khác.


10

Dọn dẹp ngăn xếp

Nếu bạn chỉ muốn xóa toàn bộ ngăn xếp, hãy bọc nó trong một mảng và bật nó:

];

Điều khó khăn hơn một chút là, nếu bạn đã thực hiện nhiều tính toán, nhưng chỉ muốn giữ phần tử ngăn xếp trên cùng và loại bỏ mọi thứ bên dưới. Cách tiếp cận ngây thơ sẽ là lưu trữ phần tử trên cùng trong một biến, xóa ngăn xếp, đẩy biến. Nhưng có một cách thay thế ngắn hơn nhiều: bọc ngăn xếp trong một mảng và trích xuất phần tử cuối cùng:

]W=

(Cảm ơn Trình tối ưu hóa đã cho tôi xem cái này vào ngày khác.)

Tất nhiên, nếu chỉ có hai yếu tố trên ngăn xếp, \;thì ngắn hơn.


\;sẽ chỉ bật phần tử bên dưới ĐKDV. Ý bạn là ;;sao
Máy

1
@CalculatorFeline nửa sau của câu trả lời là về việc xóa tất cả mọi thứ trừ ĐKDV.
Martin Ender

9

e và sức mạnh của mười

Như trong nhiều ngôn ngữ khác, bạn có thể viết 1e3thay vì 1000bằng tiếng CJam.

Điều này hoạt động cho các cơ sở không nguyên và thậm chí cho các số mũ không nguyên. Ví dụ, 1.23e2đẩy 123,01e.5đẩy 3,1622776601683795 (căn bậc hai của 10 ).

Điều không rõ ràng ngay lập tức 1e3hai mã thông báo:

  • 1đẩy số nguyên 1 trên ngăn xếp.

  • e3nhân nó với 1000 .

Tại sao điều đó quan trọng?

  • Bạn có thể gọi e<numeric literal>một cái gì đó đã có trên ngăn xếp.

    2 3 + e3 e# Pushes 5000.
    
  • Bạn có thể ánh xạ e<numeric literal>qua một mảng.

    5 , :e3  e# Pushes [0 1000 2000 3000 4000].
    

9

Định mức Euclide

Cách đơn giản để tính định mức Euclide của một vectơ, nghĩa là căn bậc hai của tổng bình phương của các phần tử của nó, là

2f#:+mq

Tuy nhiên, có một cách ngắn hơn nhiều.

mh, toán tử hypotenuse, bật hai số nguyên ab từ ngăn xếp và đẩy sqrt (a 2 + b 2 ) .

Nếu chúng ta có một vectơ x: = [x 1 Vay x n ], n> 1 trên ngăn xếp, :mh(giảm theo hypotenuse) sẽ đạt được những điều sau:

  • Đầu tiên x 1x 2 được đẩy và mhđược thực thi, để lại sqrt (x 1 2 + x 2 2 ) , trên ngăn xếp.

  • Sau đó, x 3 được đẩy và mhđược thực hiện lại, để lại
    sqrt (sqrt (x 1 2 + x 2 2 ) 2 + x 3 2 ) = sqrt (x 1 2 + x 2 2 + x 3 2 ) trên ngăn xếp.

  • Sau khi x n đã được xử lý, chúng ta còn lại với sqrt (x 1 2 + Sọ x n 2 ) , chỉ tiêu Euclide của x .

Nếu n = 1x 1 <0 , đoạn mã trên sẽ tạo ra kết quả không chính xác. :mhzlàm việc vô điều kiện. (Cảm ơn @ MartinBüttner đã chỉ ra điều đó.)

Tôi đã sử dụng thủ thuật này lần đầu tiên trong câu trả lời này .


2
Tất nhiên, điều này có ý nghĩa đối với việc phân tích số lượng chương trình của bạn ...
Peter Taylor

8

Chuyển đổi từ cơ sở n với danh sách các số lớn hơn n

CJam chuyển đổi một danh sách thành một số với công thức này: A 0 * n l + A 1 * n l-1 + A 2 * n l-2 + A l * n 0 (với không âm n). nlà cơ sở và llà chiều dài danh sách. Điều này có nghĩa là A i có thể là bất kỳ số nguyên nào, không phải nằm trong phạm vi [0,n).

Vài ví dụ:

  • 0btrích xuất mục cuối cùng và chuyển nó thành số nguyên. Hoạt động như W=ivà lưu một byte nếu nó không phải là số nguyên. Nhưng mọi thứ khác trong danh sách cũng phải có khả năng chuyển thành số nguyên.
  • 1btrả lại tổng. Hoạt động như :i:+và lưu hai byte nếu chúng không phải là số nguyên. Nó cũng hoạt động với danh sách trống trong khi :+không.
  • [i{_1&9 32?_@\m2/}16*;]W%:cchuyển đổi một ký tự thành một chuỗi các kết thúc dòng và tab, có thể được chuyển đổi trở lại với 2bc. Mặc dù vậy, chức năng mã hóa không dễ bị đánh gôn trong chương trình mã golf. Nhưng bạn thường không cần điều đó.
  • Bạn có thể sử dụng đoạn mã sau để chuyển đổi một chuỗi thành các ký tự Unicode không trong 16 bit, có thể được chuyển đổi lại bằng 2A#b128b:c. (Giải thích sẽ được bổ sung sau. Hoặc có lẽ tôi sẽ viết một phiên bản mới sau.)

    128b2A#b         " Convert to base 1024. ";
    W%2/)W%\:+       " Convert to two base 1024 digit groups. ";
    [0X@
    {
      _54+
      @I+_Am>@\-
      _Am<@+ 0@-@1^
    }fI
    ]);)
    @\+[~+]2A#b_2G#<!{2A#b}*
    \W%+:c
    

Phương thức tương tự hoạt động với bất kỳ bộ nsố nguyên nào có mod giá trị khác nhau n, nếu bạn có thể tìm cách nào đó để loại bỏ chữ số có ý nghĩa nhất.


8

Dùng $làm ternary nếu

Khi bạn không bận tâm đến việc rò rỉ bộ nhớ, tức là để lại các phần tử không được sử dụng trên ngăn xếp mà sau này bạn sẽ xóa ];, toán tử sao chép $có thể là một sự thay thế tiện dụng cho toán tử ternary ?.

? hoạt động tốt nếu bạn quản lý để tính toán điều kiện trước khi đẩy hai mục để chọn, nhưng thường xuyên hơn không, điều kiện thực sự phụ thuộc vào các mục đó và việc đặt nó lên trên chúng sẽ cho kết quả tự nhiên hơn nhiều.

Nếu bạn có A B Ctrên ngăn xếp, bạn có thể thực thi

!$

thay vì

\@?

để sao chép Bnếu Clà sự thật và Anếu không.

Nếu Clà Boolean ( 0hoặc 1) thực tế , bạn có thể thực thi

$

thay vì

@@?

để sao chép Anếu Clà sự thật và Bnếu không.


Nhìn lại, đây là một mẹo khá rõ ràng, nhưng tôi chưa bao giờ nghĩ về nó trước đây. Tôi đã sử dụng nó lần đầu tiên trong câu trả lời này .
Dennis

7

Bản đồ cho danh sách lồng nhau

Giả sử bạn đã có một danh sách lồng nhau, như một ma trận:

[[0 1 2][3 4 5][6 7 8]]

Hoặc một chuỗi các chuỗi:

["foo""bar"]

Và bạn muốn ánh xạ một khối lên cấp độ lồng nhau (nghĩa là áp dụng nó cho từng số hoặc từng ký tự). Giải pháp ngây thơ là một lồng nhau %:

{{...}%}%

Tuy nhiên, bạn thực sự có thể đẩy khối bên trong lên ngăn xếp và sau đó sử dụng f%. flà "ánh xạ với tham số bổ sung", do đó, nó sẽ ánh xạ %vào danh sách bên ngoài, sử dụng khối làm tham số thứ hai:

{...}f%

Lưu hai byte.

Một mẹo gọn gàng khác để làm một cái gì đó như for (i=0; i<5; ++i) for (j=0; j<5; ++j) {...}

5,_f{f{...}}

Bên ngoài fsẽ ánh xạ vào phạm vi đầu tiên, cung cấp phạm vi thứ hai như một tham số bổ sung. Nhưng bây giờ, nếu bạn sử dụng flại, chỉ có phần tử ngăn xếp trên cùng là một mảng, do đó bạn fánh xạ khối bên trong vào đó, cung cấp "biến lặp" bên ngoài như một tham số bổ sung. Điều này có nghĩa là khối bên trong được chạy cùng ijtrên ngăn xếp.

Điều này có cùng số lượng ký tự như chỉ ánh xạ một khối lên sản phẩm của Cartesian (mặc dù cái sau sẽ ngắn hơn nếu bạn cần các cặp dưới dạng mảng):

5,_m*{~...}%

Sự khác biệt là phiên bản này mang lại một mảng kết quả cho tất cả các cặp, trong khi phiên bản kép fmang lại một danh sách lồng nhau, có thể hữu ích nếu bạn muốn lưu trữ kết quả trong một lưới, với các biến lặp là tọa độ.

Cảm ơn Dennis đã chỉ cho tôi thủ thuật này.

Cập nhật 0.6.4

f:hiện đã được cải thiện rất nhiều bằng cách sử dụng bất kỳ nhà khai thác nào khác bao gồm cả chính họ. Điều này có nghĩa là bạn có thể tiết kiệm nhiều byte hơn bây giờ. Ánh xạ một toán tử vào một danh sách lồng nhau thậm chí còn ngắn hơn:

{:x}%
{x}f%
::x

Điều này không thực sự giúp với việc ánh xạ các khối vào danh sách lồng nhau.

Đối với các khối hoặc toán tử áp dụng cho sản phẩm của Cartesian, điều này cũng đã rút ngắn hơn bây giờ, đối với các khối cũng như các toán tử:

5,_f{f{...}}
5,_ff{...}

5,_f{fx}
5,_ffx

Điều tuyệt vời là bây giờ bạn có thể lồng những thứ này. Vì vậy, bạn có thể áp dụng một toán tử dễ dàng cho cấp thứ ba trong danh sách:

:::x

Hoặc một khối với một số mánh khóe:

{...}ff%

Cập nhật tuyệt vời. Nhưng vẫn không có f~...
jimmy23013

@ user23013 fmong đợi một toán tử nhị phân, ~là đơn nguyên; có lẽ bạn muốn :~? Ngoài ra, chúng ta có thể thảo luận điều này trong trò chuyện
aditsu 13/2/2015

Tôi có thiếu điều gì về bản cập nhật 0.6.4 này không? Tôi vẫn nhận được thông báo lỗi khi thực hiện các thủ thuật đó, như Unhandled char after ':': :( liên kết )
Runer112

2
@ Runer112 Hoạt động cho tôi. Hãy chắc chắn rằng bạn tải lại đúng cách (tức là không phải từ bộ đệm). Tùy thuộc vào trình duyệt của bạn Ctrl + F5 sẽ hoạt động.
Martin Ender

@ MartinBüttner Nó thực sự được gây ra bởi bộ nhớ đệm ngớ ngẩn. Cảm ơn.
Runer112

7

Toán tử vector hóa cho nghệ thuật ASCII

Đối với nhiều thách thức nghệ thuật ASCII, sẽ rất hữu ích khi tạo hai mẫu khác nhau để chồng chúng sau này. Toán tử véc tơ có thể rất hữu ích để đạt được các loại chồng chất khác nhau.

Một thuộc tính hữu ích của vector hóa toán tử là toán tử chỉ được thực thi một lần cho mỗi phần tử của chuỗi / mảng ngắn hơn, trong khi các phần tử của phần tử lớn hơn không có đối tác vẫn chưa được xử lý.

  • .e<

    Toán tử tối thiểu e<làm việc cho các cặp chuỗi, ký tự, mảng và số nguyên; nó bật hai mục từ ngăn xếp và đẩy thấp hơn về phía sau.

    Vì một không gian có điểm mã thấp hơn tất cả các ký tự ASCII có thể in khác, .e<có thể được sử dụng để "xóa" các phần của mẫu được tạo:

    "\/\/\/\/\/" "    " .e<
    
    e# This pushes "    \/\/\/".
    

    Để biết ví dụ đầy đủ, hãy xem câu trả lời của tôi cho Me Want Honeycomb .

  • .e>

    Toán tử tối đa e>hoạt động như toán tử tối thiểu, với kết quả ngược lại.

    Một lần nữa, do điểm mã thấp của không gian, .e>có thể được sử dụng để chèn một mẫu các ký tự có thể in trong một khối khoảng trắng:

    [[" " " " " " " "] [" " " " " " " "]][["+" "" "-" ""]["" "*" "" "/"]] ..e>
    
    e# This pushes [["+" " " "-" " "] [" " "*" " " "/"]].
    

    Để biết ví dụ đầy đủ, hãy xem câu trả lời của tôi cho Seven Slash Display .

  • .e&

    Toán tử AND logic e&đẩy đối số bên trái của nó nếu nó sai và đối số bên phải của nó.

    Nếu không có mẫu nào chứa các phần tử giả, thì mẫu này có thể được sử dụng để áp đặt một cách vô điều kiện một mẫu khác:

    "################" " * * * *" .e&
    
    e# This pushes " * * * *########".
    

    Để biết ví dụ đầy đủ, hãy xem câu trả lời của tôi để In Cờ Mỹ! .

  • .e|

    Toán tử OR logic e|có thể được sử dụng như trên, với thứ tự đối số đảo ngược:

    " * * * *" "################" .e|
    
    e# This pushes " * * * *########".
    

6

Sử dụng &để kiểm tra xem một mục có trong danh sách không

Dành cho

1 [1 2 3] #W>
1 [1 2 3] #)

Bạn có thể dùng

1 [1 2 3] &,
1 [1 2 3] &

thay vào đó, trả về 0/1 và true / falsey tương ứng.


6

z và mảng không phải hình chữ nhật

Nhà điều hành zip ztransposes các hàng và cột của một hai chiều 1 mảng A , mà các thành phần cũng có thể là iterables.

Đối với các mảng không phải hình chữ nhật - không giống như các hàm dựng sẵn ziptrong, ví dụ: Python (cắt các hàng có cùng độ dài) hoặc Ruby (đệm các hàng với nil) - CJam chỉ cần chuyển đổi các cột của mảng thành các hàng, bỏ qua độ dài của chúng và bỏ qua những khoảng trống

Ví dụ, nén mảng

[
  [1]
  [2 4]
  [3 5 6]
]

tương đương với việc nén mảng

[
  [1 4 6]
  [2 5]
  [3]
]

hoặc mảng

[
  [1]
  [2 4 6]
  [3 5]
]

khi cả ba hành động thúc đẩy

[
  [1 2 3]
  [4 5]
  [6]
]

trên ngăn xếp.

Mặc dù điều này có nghĩa là đó zkhông phải là một cuộc xâm lược (sẽ hữu ích trong các dịp), nhưng nó có một vài ứng dụng.

Ví dụ:

  • Chúng ta có thể căn chỉnh các cột của một mảng thành trên cùng (nghĩa là biến mảng đầu tiên thành mảng thứ hai) bằng cách nén hai lần:

    zz
    
  • Sửa đổi nhỏ của phương pháp trên có thể được sử dụng cho các vấn đề tương tự.

    Chẳng hạn, để căn chỉnh các cột của một mảng xuống dưới cùng (nghĩa là để biến mảng thứ hai thành mảng thứ nhất), chúng ta có thể nén hai lần với thứ tự hàng đảo ngược:

    W%zzW%
    
  • Đưa ra một chuỗi các chuỗi, chúng ta có thể tính độ dài của chuỗi dài nhất như thế này:

    :,:e>
    

    Tuy nhiên, bằng cách nén và tính toán số lượng hàng của kết quả, chúng ta có thể lưu ba byte:

    z,
    

1 Nếu bất kỳ "hàng" nào của A không lặp lại được, hãy zcoi chúng là singletons, do đó, nén hoạt động cho các mảng tùy ý.


1
Chỉ là một cách khác để hình dung cùng một thứ, nhưng đối với tôi hành vi hợp lý hơn nhiều nếu tôi hình dung zcác cột chuyển đổi thành các hàng, trong khi các giá trị trống bị bỏ qua. Trong ví dụ, cột đầu tiên trong đầu vào là 1, 2, 3, cột thứ hai là 4, 5 (vị trí trống được bỏ qua) và cột thứ ba là 6. Đây là các hàng của kết quả.
Reto Koradi

@RetoKoradi Đó là một cách tốt hơn để mô tả nó.
Dennis

6

Ngoại lệ

Tất cả các trường hợp ngoại lệ đều gây tử vong ở CJam. Vì đầu ra cho STDERR được bỏ qua theo mặc định , chúng tôi có thể sử dụng điều này để lợi thế của chúng tôi.

Tất cả toán tử trong CJam hoạt động bằng cách bật 0 hoặc nhiều phần tử từ ngăn xếp, thực hiện một số tác vụ và đẩy 0 hoặc nhiều phần tử trên ngăn xếp. Các ngoại lệ xảy ra trong khi tác vụ được thực hiện, vì vậy điều này vẫn bật các phần tử, nhưng không có gì được trả lại.

Dưới đây là một vài trường hợp sử dụng:

  • Dọn dẹp một chồng nhỏ

    Để xóa một ngăn xếp có chứa hai yếu tố, @có thể được sử dụng. @cố gắng bật ba phần tử ngăn xếp, nhưng không thành công sau khi bật phần tử thứ hai.

    Bất kỳ toán tử nào khác xuất hiện ba phần tử sẽ phục vụ cùng một mục đích.

    Xem nó trong hành động ở đây .

  • Loại bỏ hai hoặc ba yếu tố khỏi ngăn xếp

    Bất kỳ toán tử nào không được triển khai cho các phần tử cụ thể này đều có thể được sử dụng để bật hai hoặc ba phần tử từ ngăn xếp ngay trước khi thoát.

    Để bật hai phần tử, bhoạt động nếu một trong số chúng là ký tự hoặc không có phần tử nào là số nguyên.

    Để bật ba phần tử, thoạt động nếu không có phần tử nào ở dưới cùng là hai lần lặp, phần lặp dưới cùng nhất là trống hoặc không có phần tử nào là số nguyên.

  • Thoát khỏi một vòng lặp

    Đôi khi, chúng ta cần thoát khỏi một vòng lặp khi một số nguyên trở thành số không hoặc một chuỗi quá ngắn. Thay vì kiểm tra các điều kiện này, nếu các hoạt động liên quan không thành công, chuỗi rỗng hoặc singletons, chúng ta có thể chỉ cần để chương trình diễn ra theo cách tự nhiên.

    Để biết một ví dụ liên quan đến số học, xem tại đây .

    Đối với một ví dụ liên quan đến chuỗi, xem ở đây .

  • Thi công có điều kiện

    Nếu mã nguồn không được thực thi đối với một số loại đầu vào nhất định, đôi khi chúng ta có thể sử dụng một toán tử không thành công loại đầu vào đó.

    Ví dụ: isẽ thất bại đối với các chuỗi không đánh giá thành một số nguyên và ewsẽ thất bại đối với các chuỗi có độ dài 0 hoặc 1.

    Xem nó trong hành động ở đây .


5

Tối đa / tối thiểu từ một mảng

Đây là một cho người mới bắt đầu!

Khi bạn cần tìm số tối đa hoặc tối thiểu từ một mảng, cách dễ nhất và nhỏ nhất là sắp xếp mảng và sau đó lấy ra phần tử đầu tiên hoặc cuối cùng.

Vì vậy, nếu mảng là biến A

A$W=

là tối đa và

A$0=

là mức tối thiểu

Nhận cả hai cùng một lúc cũng có thể

A$)\0=

Điều này có vẻ rõ ràng sau khi đọc, nhưng nỗ lực đầu tiên của bất kỳ ai có xu hướng hướng tới việc sử dụng e<hoặc e>thông qua việc lặp qua mảng, giống như

A{e<}*

dài hơn 2 byte và thậm chí dài hơn nếu bạn muốn cả max và min.


Tất nhiên, nếu bạn không quan tâm đến phần còn lại của mảng còn lại trên ngăn xếp, bạn thực sự có thể sử dụng ()thay vì 0=W=.
Martin Ender

Bây giờ có :e<:e>
aditsu

@aditsu Mặc dù, chúng không ngắn hơn mẹo trên.
Trình tối ưu hóa

5

Sử dụng dấu thời gian cho số lượng lớn

Nếu bạn cần một số lượng rất lớn nhưng tùy ý, bạn thường sẽ sử dụng ký hiệu khoa học như 9e9hoặc nâng một trong các biến tích hợp lớn lên thành một công suất tương tự KK#. Tuy nhiên, nếu bạn không quan tâm số thực tế là gì và nó không nhất thiết phải giống nhau (ví dụ như giới hạn trên của một số ngẫu nhiên), bạn có thể thực hiện bằng hai byte bằng cách sử dụng

es

thay thế. Điều này đưa ra dấu thời gian hiện tại tính bằng mili giây và theo thứ tự 10 12


3
Cũng lưu ý rằng nếu bạn muốn một số lớn tùy ý và muốn loại bỏ một số dương với nhau, bạn có thể sử dụng e9.
jimmy23013

5

Kiểm tra hai chuỗi / mảng không bằng nhau

Đôi khi bạn muốn một giá trị trung thực khi hai chuỗi hoặc mảng không bằng nhau và giá trị sai lệch nếu có. Giải pháp rõ ràng là hai byte:

=!

Kiểm tra sự bình đẳng, và đảo ngược kết quả. Tuy nhiên, trong một số điều kiện bạn có thể sử dụng

#

Khi #được áp dụng cho hai mảng, nó thực sự tìm kiếm mảng thứ hai dưới dạng một phân đoạn của mảng thứ nhất (và cung cấp cho bạn chỉ mục nơi bắt đầu phân đoạn phụ). Vì vậy, nếu hai mảng là như nhau, subarray sẽ được tìm thấy ngay khi bắt đầu và cho 0, đó là giả. Nhưng nếu mảng thứ hai không thể được tìm thấy, nó sẽ cho -1đó là sự thật.

Lý do chúng ta cần một số điều kiện bổ sung trên hai mảng là vì điều này cũng mang lại giá trị sai lệch nếu mảng thứ hai là tiền tố không tầm thường của đầu tiên, ví dụ:

"abc""ab"#

đưa ra 0mặc dù các chuỗi không giống nhau. Điều kiện đơn giản nhất loại trừ trường hợp này là nếu bạn biết rằng cả hai mảng sẽ có cùng độ dài - trong trường hợp đó nếu một là tiền tố của cái kia, bạn biết rằng chúng bằng nhau. Nhưng trong những trường hợp cụ thể có thể có những điều kiện yếu hơn cũng đủ. Chẳng hạn, nếu bạn biết rằng các chuỗi được sắp xếp, tiền tố sẽ luôn là chuỗi đầu tiên, không phải là chuỗi thứ hai.


5

c và số nguyên 16 bit

Để thêm (hoặc trừ) số nguyên 16 bit không dấu với gói phù hợp, bạn có thể sử dụng +65536%hoặc +2G#%.

Tuy nhiên,

+ci

ngắn hơn rất nhiều Các ký tự bao quanh arround ở 65536 , do đó, việc chuyển sang Ký tự ( c) rồi đến Long ( i) có hiệu ứng tương tự 65536%, với lợi ích bổ sung là kết quả sẽ không âm.

Thủ thuật tương tự có thể được sử dụng để đẩy 65535 :

Wci

4

Bộ nguồn

Giả sử bạn có một mảng và bạn muốn một mảng có tất cả các tập hợp con có thể có của mảng đó. Mẹo nhỏ là bắt đầu với một mảng trống, và sau đó, với mỗi phần tử, sao chép các tập hợp con bạn đã có và thêm phần tử mới vào chúng (giữ kết quả trước đó khi phần tử không được thêm vào ). Lưu ý rằng bạn cần khởi tạo ngăn xếp với trường hợp cơ sở, tức là một mảng chỉ chứa một mảng trống: Điều đó có thể trông như thế này:

[1 2 3 4 5]La\{1$f++}/

Điều tuyệt vời ở đây là, bạn có thể chạy ngay một số tính toán trên tập hợp con, có khả năng không cần thêm ký tự. Nói rằng bạn muốn các sản phẩm của tất cả các tập hợp con. Trong trường hợp đó, trường hợp cơ sở là một mảng chứa 1và ở mỗi bước, bạn lấy danh sách các sản phẩm có thể trước đó, sao chép nó và nhân mọi thứ trong bản sao bằng phần tử mới:

[1 2 3 4 5]1a\{1$f*+}/

4

Kiểm tra xem các mục trong danh sách có giống nhau không

Tôi nghĩ điều này cũng đáng nói. Sử dụng:

)-

Trả về sự thật nếu không phải tất cả giống nhau, hoặc danh sách trống nếu tất cả đều giống nhau. Lỗi nếu danh sách trống.

Trong trường hợp mục được trích xuất có thể là một mảng (hoặc chuỗi):

)a-

Sử dụng !hoặc !!để có được giá trị boolean. Trong trường hợp mục được trích xuất có thể là một mảng và có nhiều nhất hai loại mục khác nhau và bạn muốn nó là 1 nếu không hoàn toàn giống nhau, thì điều này ngắn hơn:

_|,(

4

0= cho chuỗi

Để lấy phần tử đầu tiên của một mảng, bạn phải sử dụng 0=(hoặc (, nếu bạn không để phần còn lại của mảng trên ngăn xếp).

Tuy nhiên, nếu mảng đó là một chuỗi, truyền vào ký tự là đủ.

Thí dụ

"xyz"c e# Pushes 'x.

Tôi không thấy lý do tại sao CJam không chỉ ctrích xuất phần tử đầu tiên của bất kỳ mảng nào, điều này sẽ hữu ích và nhất quán hơn.
Trái cây Esolanging

4

Xoay một mảng (hoặc ngăn xếp) một đơn vị sang trái

CJam có toán tử xoay tráim< , thường là những gì bạn nên sử dụng để xoay một mảng một số lượng đơn vị tùy ý sang trái.

Trong một số trường hợp, bạn cũng có thể sử dụng (+để thay đổi và chắp thêm:

[1 2 3]       (+ e# Pushes [2 3 1].
[[1] [2] [3]] (+ e# Pushes [[2] [3] 1].

Ví dụ thứ hai không hoạt động vì phần tử đầu tiên của mảng cũng là một lần lặp, do đó được +nối thay vì nối thêm.

Ngoài ra, nếu bạn muốn kết xuất mảng đã xoay trên ngăn xếp, bạn có thể sử dụng :\(giảm bằng cách hoán đổi) vô điều kiện:

[1 2 3]       :\ e# Pushes 2 3 1.
[[1] [2] [3]] :\ e# Pushes [2] [3] [1].

Miễn là bạn không mở [, thủ thuật này cũng có thể được sử dụng để xoay toàn bộ ngăn xếp, nghĩa là, để đưa mục ngăn xếp dưới cùng lên trên cùng:

]:\

3

In một danh sách và xóa ngăn xếp

Hãy nói rằng ngăn xếp của bạn có một danh sách các chuỗi / số / vv. trên đầu trang và một số mặt hàng bổ sung khác bên dưới nó. I E

123 "waste" ["a" "b" "rty" "print" "me" "please"]

Bây giờ bạn chỉ quan tâm đến việc in danh sách cuối cùng, vì vậy bạn làm

S*]W=

đầu ra nào

a b rty print me please

Điều này có vẻ thực sự thông minh khi chúng ta sử dụng thủ thuật xóa stack và chỉ in danh sách được nối với dấu cách (có thể không phải là cách mong muốn để in danh sách đôi khi).

Điều này có thể được chơi golf hơn nữa!

p];

Đó là 2 byte ngắn hơn !

và nếu bạn chỉ có 1 mục trên stack ngoài danh sách, nó thậm chí còn ngắn hơn!

p;

Cái hay của pnó là loại bỏ hầu hết các mục hàng đầu khỏi ngăn xếp, xâu chuỗi nó (cũng thêm một dòng mới ở cuối) và in ra STDOUT ngay lập tức mà không cần chờ hoàn thành mã.

Vì vậy, đoạn mã trên sẽ xuất ra

["a" "b" "rty" "print" "me" "please"]

đó là đại diện chính xác của một danh sách khi nó ở trong ngăn xếp!


3

Các sản phẩm của Cartesian hoặc tất cả các kết hợp có thể có của hai hoặc nhiều bộ

CJam có một máy tính sản phẩm Cartesian sẵn có m*, lấy hai danh sách / chuỗi hàng đầu trên ngăn xếp và tạo tất cả các cặp có thể từ nó. Ví dụ

[1 2 3 4]"abc"m*

[[1 'a] [1 'b] [1 'c] [2 'a] [2 'b] [2 'c] [3 'a] [3 'b] [3 'c] [4 'a] [4 'b] [4 'c]]

như chồng

Nhưng nếu bạn muốn tất cả các kết hợp có thể từ hơn 2 danh sách / chuỗi. Bạn sử dụng m*nhiều lần? Ví dụ

[1 2 3 4][5 6]"abc"m*m*

sẽ để lại những thứ sau trên stack

[[1 [5 'a]] [1 [5 'b]] [1 [5 'c]] [1 [6 'a]] [1 [6 'b]] [1 [6 'c]] [2 [5 'a]] [2 [5 'b]] [2 [5 'c]] [2 [6 'a]] [2 [6 'b]] [2 [6 'c]] [3 [5 'a]] [3 [5 'b]] [3 [5 'c]] [3 [6 'a]] [3 [6 'b]] [3 [6 'c]] [4 [5 'a]] [4 [5 'b]] [4 [5 'c]] [4 [6 'a]] [4 [6 'b]] [4 [6 'c]]]

Lưu ý rằng các sản phẩm vẫn là các cặp, trong đó một trong các mặt hàng là một cặp. Điều này không được mong đợi và chúng tôi muốn kết hợp phẳng.

Có một cách dễ dàng để làm điều đó. Chỉ cần bọc mọi danh sách mà bạn muốn cho sản phẩm cartesian của bạn trong một mảng, tạo cặp sản phẩm Cartesian và làm phẳng nó mỗi lần:

[1 2 3 4][5 6]"abc"]{m*{(+}%}*

Cái lá này

[['a 5 1] ['b 5 1] ['c 5 1] ['a 6 1] ['b 6 1] ['c 6 1] ['a 5 2] ['b 5 2] ['c 5 2] ['a 6 2] ['b 6 2] ['c 6 2] ['a 5 3] ['b 5 3] ['c 5 3] ['a 6 3] ['b 6 3] ['c 6 3] ['a 5 4] ['b 5 4] ['c 5 4] ['a 6 4] ['b 6 4] ['c 6 4]]

trên ngăn xếp.

Bạn muốn duy trì trật tự? , chỉ cần trao đổi trước khi thêm mục popped trở lại mảng. I E

{m*{(\+}%}*

Bạn chỉ muốn hoán vị?

{m*{(+$}%_&}*

Bạn chỉ muốn các yếu tố độc đáo trong các kết hợp?

{m*{(+_&}%}*

Đó là tất cả mọi người. cho bây giờ .


1
Bây giờ bạn cũng có thể làm ]:m*:e_, với bất kỳ số lượng mảng nào
aditsu

3

Hoạt động trên chuỗi

Đôi khi nếu bạn đang làm việc với một cấu trúc dữ liệu phức tạp, trong khi các mục trong đó đơn giản, việc chuyển đổi thành chuỗi có thể giúp ích.

Ví dụ: nếu bạn muốn lấy một vài mục đầu tiên hoặc cuối cùng trong một mảng bit 2D và không quan tâm đến loại được trả về, hãy sA<lưu một byte từ 0=A<hoặc :+A<.

Hoặc nếu bạn muốn sửa đổi một số bit trong đầu vào, bạn có thể sửa đổi chuỗi trước khi đánh giá nó.

Hoặc nếu bạn có cấu trúc này và muốn chuyển đổi nó thành một danh sách đơn giản:

[[[[[[[[[1]2]3]4]5]6]7]8]9]

Bạn có thể làm điều đó với nhiều nhân vật theo những cách khác:

[a{~)\}h;]W%

Nhưng nó có thể ngắn hơn nhiều với các chuỗi:

s:~

Nó ngắn hơn ngay cả khi nó có thể có các số có nhiều hơn một chữ số:

[`La`-~]

Hoặc là:

`']-~]

Nếu bạn không cần một mảng khác chứa nhiều mảng như vậy.


Hiện e_tại
aditsu

@aditsu Xem câu trả lời và bình luận này . Đôi khi svẫn hoạt động tốt hơn.
jimmy23013

Chắc chắn, khi bạn có thể làm việc với một chuỗi trực tiếp, nó sẽ ngắn hơn.
aditsu

3

Sử dụng Nthay vìLa

Trong nhiều trường hợp, bạn cần một cái gì đó được khởi tạo cho một mảng chứa một mảng trống là phần tử duy nhất của nó La, dường như không cần thiết dài hơn 1 byte.

Trong nhiều trường hợp, bạn cũng cần thêm một dòng mới sau mỗi phần tử trước khi in, đó sẽ là một cái gì đó như Nohoặc N*.

Nhưng nếu cả hai đều đúng, đôi khi bạn có thể phát hiện ra rằng bạn chỉ có thể khởi tạo mảng với N, có ký tự dòng mới là thành phần duy nhất của nó. Hãy chắc chắn rằng bạn chỉ trả trước mọi thứ cho các phần tử trong phần còn lại của mã của bạn và điều đầu tiên để trả trước luôn là một ký tự hoặc một mảng. Hoặc chỉ thêm vào, nếu một dòng mới hàng đầu được chấp nhận và điều đó làm cho nó ngắn hơn.

Đôi khi Scũng hoạt động nếu bạn cần tách đầu ra với khoảng trắng.

Trong trường hợp hiếm hơn, phần tử ban đầu phải là một chuỗi. Nhưng bạn vẫn có thể sử dụng Nacó thể ngắn hơn so với nối thêm dòng mới sau đó.


2

Chia tách trên một hoặc nhiều lần

Giả sử bạn có một chuỗi "abbcdbbfghbdbb"và bạn muốn tách nó rab

"abbcdbbfghbdbb"'b/

Lá này trên stack:

["a" "" "cd" "" "fgh" "d" "" ""]

Chú ý các chuỗi trống? Những người ở đó vì hai bngười đã ở cùng nhau và không có gì ở giữa họ. Đôi khi, bạn muốn tránh điều này. Bạn có thể làm điều này bằng cách

"abbcdbbfghbdbb"'b/La-

hoặc lọc ra các chuỗi trống

"abbcdbbfghbdbb"'b/{},

nhưng đó là 3 byte thêm.

Một toán tử ít được biết đến cho trường hợp sử dụng cụ thể này là %. Ngoài việc thực hiện mod và ánh xạ và phân tách dựa trên số ( "abcd"2%= "ac"), %còn có thể phân chia trên chuỗi / mảng. Vì vậy, đối với trường hợp sử dụng ở trên:

"abbcdbbfghbdbb"'b%

sẽ rời khỏi

["a" "cd" "fgh" "d"]

trên ngăn xếp.

Cảm ơn @ user23013 đã chỉ ra điều này trong một trong những câu trả lời của tôi ngày hôm nay.


Tôi nghĩ cái này nên được đặt tên là "cũng học GolfScript", trong đó có các ví dụ tốt hơn trong tài liệu.
jimmy23013

@ user23013 nhưng chúng tôi không bao giờ chắc chắn tất cả những gì tương tự như GS và những gì không.
Tối ưu hóa

2

Sử dụng nếp gấp / thu nhỏ dưới dạng thông tin

Chúng tôi có :xmột tốc ký cho {x}%và hoặc {x}*(tùy thuộc vào việc xlà đơn nhất hay nhị phân). Thật không may, không có toán tử infix tương đương để rút ngắn {x}/. Tuy nhiên, rất thường xuyên khi chúng ta làm {x}/, xthực sự là một toán tử nhị phân liên tục sửa đổi mục nằm bên dưới ngăn xếp. Nếu đó là trường hợp và mục nói không phải là một mảng, chúng ta có thể lưu một byte bằng cách lạm dụng gập / giảm như foreach:

5 [1 2 3 4]{-}/  e# Gives -5
5 [1 2 3 4]+:-

Điều này hoạt động vì nếp gấp luôn để lại phần tử đầu tiên không bị ảnh hưởng. Thật không may, nó không lưu một byte, khi phần tử được sửa đổi là một mảng, bởi vì thêm nó sẽ mở khóa nó. Tuy nhiên, đôi khi bạn đủ may mắn rằng mảng của bạn đã chứa phần tử đó ở phía trước, trong trường hợp này nên ghi nhớ giảm (thay vì xóa phần tử thủ công trước khi sử dụng {}/phần còn lại).


2

in và in

CJam có printnhà điều hành : o. Nó hoạt động nhưng stack đang in ngay lập tức sau khi tất cả các mã đã được thực thi. Bạn có thể dừng nó nếu bạn xóa ngăn xếp vào cuối chương trình. Đơn giản chỉ cần đặt cái này ở cuối:

];

Để println bạn có thể sử dụng oNohoặc p(hoạt động như `oNo)


3
Có một sự khác biệt lớn hơn giữa op. pbắt đầu bằng cách chuyển đổi mục được in thành biểu diễn chuỗi rõ ràng. plà bình đẳng để thực hiện ​`oNo.
Dennis
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.