Mẹo chơi gôn trong GolfScript


35

Cái gì, bài này chưa tồn tại?

Tất nhiên, GolfScript được tạo ra để chơi gôn, vì vậy bạn có thể nghĩ rằng không có mẹo cụ thể nào thực sự cần thiết. Nhưng để sử dụng đầy đủ các tính năng của GolfScript, bạn cần tìm hiểu một số thủ thuật không rõ ràng. Bài này là để thu thập những lời khuyên và thủ thuật hữu ích như vậy.

Để bắt đầu, đây là các trang tham khảo GolfScript chính thức. Bạn nên thực sự làm quen với những điều này trước:

Đặc biệt, tôi rất khuyên bạn nên đọc các trang theo thứ tự này - tài liệu tham khảo nhanh sẽ ít được sử dụng cho đến khi bạn đã quen thuộc với các phần dựng sẵn và hướng dẫn bao gồm một số chi tiết quan trọng không được giải thích trên các trang khác .


Thi thiên Vì mục đích truyền cảm hứng và sở thích cá nhân, đây là một số câu hỏi tôi muốn xem câu trả lời hay cho:

  • Làm thế nào để thực hiện chuyển ngữ giới hạn trong GolfScript? {FROM?TO=}%hoạt động nếu bạn có thể chắc chắn rằng tất cả các yếu tố đầu vào được tìm thấy trong FROM(hoặc đừng bận tâm rằng tất cả chúng được ánh xạ đến phần tử cuối cùng TO), nhưng tất cả các cách tôi đã thấy để giữ các giá trị không bị thay đổi không thay đổi nhiều hay ít.

  • Làm cách nào để chuyển đổi tốt nhất một chuỗi thành một mảng mã ASCII và ngược lại? Những hoạt động làm điều này như là một tác dụng phụ? Cách tốt nhất để đổ các ký tự trong một chuỗi lên ngăn xếp (giống như ~đối với mảng) là gì?


Một câu hỏi khác: có một cách tốt đẹp để chuyển đổi ... xthành ... [x]? Điều tốt nhất tôi có thể thấy là [.;].
Peter Taylor

@Peter: Nếu xlà một số, thì nó []+hoạt động và ngắn hơn một char. Và tất nhiên, nếu xlà điều duy nhất trên stack, thì ]sẽ làm.
Ilmari Karonen

Tôi muốn hỏi những cách tốt nhất để làm: giá trị tối thiểu, tối đa và tuyệt đối. Tất cả các giải pháp của tôi dường như chiếm nhiều nhân vật hơn họ nên làm.
Claudiu

Cách tốt nhất để sửa đổi một mảng tại một chỉ mục nhất định là gì?
user1502040

@ user1502040: Đã trả lời bên dưới. (Nếu ai biết cách tốt hơn, xin vui lòng chia sẻ!)
Ilmari Karonen

Câu trả lời:


29

Hợp lý / nổi / phức tạp

Tôi đã đọc rất nhiều lần rằng GolfScript chỉ có số nguyên mà tôi bắt đầu tin nó. Chà, điều đó không đúng.

2-1? # Raise 2 to the power of -1. Result: 0.5
4-1? # Raise 4 to the power of -1. Result: 0.25
+    # Add. Result: 0.75

Đầu ra là

3/4

với trình thông dịch GolfScript tiêu chuẩn và

0.75

trên Web GolfScript .

Các bản hack tương tự cho phép truyền tới Rational, Float hoặc thậm chí là Complex:

{-2.?./*}:rational
{2.-1??./*}:float
{-2.-1??./*}:complex

9
OMGWTFHAX o_O !!!
Ilmari Karonen

3
NƯỚC! Khá chắc chắn đây là một lỗi trong trình thông dịch, nhưng wow
Doorknob

3
Dòng 82 của thông dịch viên gần đây nhất : Gint.new(@val**b.val). Có vẻ như nhà Gintxây dựng đang thiếu một diễn viên int ...
primo

10

Phủ định một số

Một điều mà GolfScript thiếu là một toán tử phủ định tích hợp. Các cách rõ ràng để chuyển đổi một số trên ngăn xếp thành âm, như -1*hoặc 0\-, cần ba ký tự. Tuy nhiên, có một cách để làm điều đó trong hai:

~)

Điều này hoạt động vì GolfScript sử dụng số học bổ sung của hai , do đó ~ x bằng - x 1.

Tất nhiên, biến thể (~cũng hoạt động; lựa chọn giữa chúng nói chung là một vấn đề của hương vị.


9

Xáo trộn một mảng

Cách dễ nhất để xáo trộn một mảng trong GolfScript là sắp xếp nó theo một khóa sắp xếp ngẫu nhiên. Nếu bạn chỉ cần xáo trộn một vài giá trị, đoạn mã sau sẽ thực hiện:

{;9rand}$

Lưu ý rằng, ngay cả đối với các danh sách ngắn, điều này sẽ không cho một sự xáo trộn rất tốt. Do nghịch lý sinh nhật , để có được một sự xáo trộn thống nhất hợp lý, đối số randcần phải lớn hơn đáng kể so với bình phương chiều dài của danh sách được xáo trộn.

Thay thế 999Do đó, ở trên bằng cách mang lại kết quả hợp lý tốt cho danh sách tối đa mười yếu tố, nhưng thể hiện sự thiên vị đáng chú ý cho danh sách dài hơn.

Mã sau, sử dụng 9 9 = 387.420.489 giá trị có thể, phù hợp với khoảng 1000 mục hoặc hơn (và có thể chấp nhận cho tối đa khoảng 20.000):

{;9.?rand}$

Đối với các danh sách thực sự dài, hãy thêm một 9 cho các giá trị 99 99 ≈ 3.7 × 10 197 :

{;99.?rand}$

Kiểm tra:

Đây là phân phối của phần tử đầu tiên trong danh sách 10 phần tử được xáo trộn bằng các biến thể khác nhau được hiển thị ở trên, được lấy mẫu hơn 10.000 thử nghiệm:

  • Đầu ra của 10,{;9rand}$0=cho thấy một thiên vị rất rõ ràng, với 0khả năng kết thúc ở vị trí đầu tiên nhiều hơn gấp ba lần 1:

    0 16537 #######################################################
    1 5444  ##################
    2 7510  #########################
    3 8840  #############################
    4 9124  ##############################
    5 12875 ##########################################
    6 9534  ###############################
    7 8203  ###########################
    8 7300  ########################
    9 14633 ################################################
    
  • Với 10,{;99rand}$0=, hầu hết các sai lệch đã biến mất, nhưng một số lượng đáng chú ý vẫn còn:

    0 10441 ##################################
    1 9670  ################################
    2 9773  ################################
    3 9873  ################################
    4 10134 #################################
    5 10352 ##################################
    6 10076 #################################
    7 9757  ################################
    8 9653  ################################
    9 10271 ##################################
    
  • Với 10,{;9.?rand}$0=, đầu ra về cơ bản không thể phân biệt được với một mẫu thực sự ngẫu nhiên:

    0 9907  #################################
    1 9962  #################################
    2 10141 #################################
    3 10192 #################################
    4 9965  #################################
    5 9971  #################################
    6 9957  #################################
    7 9984  #################################
    8 9927  #################################
    9 9994  #################################
    

Thi thiên Để xáo trộn các mảng hoặc chuỗi số thực sự xấu, mã sau đây đôi khi có thể được chấp nhận:

{rand}$

Nhìn chung nó sẽ bị sai lệch một cách lố bịch, nhưng miễn là tất cả các phần tử của mảng đầu vào (hoặc tất cả các mã ký tự trong chuỗi) đều lớn hơn một, nó có xác suất khác không tạo ra bất kỳ hoán vị nào của mảng, đôi khi có thể thỏa mãn yêu cầu thách thức bằng văn bản kém.


3
Tôi nhớ tôi đã từng hoài nghi làm toán cho nghịch lý sinh nhật sau khi anh tôi nói với tôi về điều đó, anh ấy đã đúng :(
ajax333221

8

Để giải quyết một truy vấn con cụ thể:

Làm cách nào để chuyển đổi tốt nhất một chuỗi thành một mảng mã ASCII và ngược lại? Những hoạt động làm điều này như là một tác dụng phụ? Cách tốt nhất để đổ các ký tự trong một chuỗi vào ngăn xếp (như ~ làm cho mảng) là gì?

Đối với những người không hiểu vấn đề, hệ thống loại của GolfScript ưu tiên cho các loại theo thứ tự số nguyên, mảng, chuỗi, khối. Điều này có nghĩa là các hoạt động mảng thông thường được áp dụng cho một chuỗi hầu như luôn cung cấp cho bạn một chuỗi. Ví dụ

'ABC123'{)}%

sẽ để lại 'BCD234'trên ngăn xếp.

Kết quả là, cách tốt nhất để chuyển đổi một chuỗi thành một mảng mã ASCII gần như chắc chắn là kết xuất các ký tự trên ngăn xếp và sau đó tập hợp chúng thành một mảng.

Cách tốt nhất để đổ các ký tự trong một chuỗi lên ngăn xếp là gì? {}/

Cách tốt nhất để chuyển đổi một chuỗi thành một chuỗi các mã ASCII là gì? [{}/](với lời cảnh báo thông thường rằng nếu không có gì khác trên ngăn xếp, bạn có thể bỏ qua [)

Cách tốt nhất để chuyển đổi một mảng mã ASCII thành một chuỗi là gì? ''+(Lưu ý rằng điều này cũng flattens mảng, vì vậy ví dụ như [65 [66 67] [[[49] 50] 51]]''+cho phép 'ABC123')


Cách tốt nhất để biến một mã ASCII thành một chuỗi là gì? []+''+? (có vẻ khá dài)
Justin

@Quincunx, nó khá dài, nhưng tôi không biết cách nào tốt hơn. Điều cần làm có thể là xem xét mã ASCII đến từ đâu và xem liệu bạn có thể đưa nó đến trong một mảng không.
Peter Taylor

6

Nếu chương trình của bạn bị hỏng một cách bí ẩn, hãy kiểm tra các biến của bạn

Tôi chỉ mất một thời gian để gỡ lỗi một chương trình rõ ràng chính xác được sử dụng !như một biến (với lý do tôi sẽ không sử dụng lại nó). Thật không may, tôi đã sử dụng if, và hóa ra việc thực hiện các ifcuộc gọi !để quyết định chi nhánh nào sẽ theo dõi.


6

Gói mục trên cùng của ngăn xếp thành một mảng

Có một cách tốt đẹp để chuyển đổi ... xthành ... [x]?

Đối với tổng quát, tùy chọn tốt nhất xuất hiện là 4 ký tự. Tuy nhiên, trong một số trường hợp đặc biệt, có thể giảm điều này.

1 ký tự

]hoạt động trong trường hợp đặc biệt đó xlà điều duy nhất trên ngăn xếp.

3 ký tự

[]+hoạt động trong trường hợp đặc biệt đó xlà một số nguyên.

.,/hoạt động trong trường hợp đặc biệt đó xlà một mảng hoặc chuỗi trung thực. Vd "AB".,/cho ["AB"]; 3,.,/cho [[0 1 2]]. Tuy nhiên,"".,/[].,/cả hai cho [].

4 ký tự

[.;] làm việc vô điều kiện.


6

Cách tốt nhất để sửa đổi một mảng tại một chỉ mục nhất định là gì? - người dùng1502040

Đó là một câu hỏi hay. Không có cách trực tiếp để gán giá trị cho một phần tử mảng trong GolfScript, vì vậy, bằng cách này hay cách khác, bạn sẽ phải xây dựng lại toàn bộ mảng.

Cách chung ngắn nhất mà tôi biết để chèn một giá trị mới xvào chỉ mục itrong một mảng là tách mảng ở chỉ mục đã cho và nối xvào nửa đầu trước khi nối chúng lại với nhau:

  • .i<[x]+\i>+(11 ký tự) - chèn giá trị xvào mảng tại chỉ mục (dựa trên 0)i

Để thay thế giá trị tại chỉ mục ibằng x, chúng ta chỉ cần rút ngắn nửa sau của mảng bằng một phần tử:

  • .i<[x]+\i)>+(12 ký tự) - thay thế phần tử tại chỉ mục (dựa trên 0) ibằng giá trịx

Ngoài ra, rút ​​ngắn nửa đầu thay vào đó sẽ thực hiện tương tự, nhưng với lập chỉ mục dựa trên 1, đôi khi có thể thích hợp hơn:

  • .i(<[x]+\i>+(12 ký tự) - thay thế phần tử tại chỉ mục (dựa trên 1) ibằng giá trịx

Trong tất cả các ví dụ ở trên, nếu xlà một số, dấu ngoặc vuông xung quanh nó có thể được bỏ qua để lưu hai ký tự, vì dù sao nó sẽ được tự động ép thành một mảng +:

  • .i<x+\i>+(9 ký tự) - chèn số xvào mảng tại chỉ mục (dựa trên 0)i
  • .i<x+\i)>+(10 ký tự) - thay thế phần tử tại chỉ mục (dựa trên 0) ibằng sốx
  • .i(<x+\i>+(10 ký tự) - thay thế phần tử tại chỉ mục (dựa trên 1) ibằng sốx

Các dấu ngoặc cũng có thể được bỏ qua nếu một trong hai xhoặc "mảng" đầu vào (hoặc cả hai) thực sự là các chuỗi, trong trường hợp đó, kết quả cũng sẽ được ép thành một chuỗi (sử dụng quy tắc chuyển đổi chuỗi → chuỗi thông thường).


Thi thiên Trong trường hợp đặc biệt, nếu chúng ta biết rằng mảng có các phần tử nằm giữa ivà 2 × i, chúng ta có thể chèn một phần tử mới xvào chỉ mục ( dựa trên 0) ivới i/[x]*(6 ký tự). Điều này thực sự làm là chia mảng thành các phần của icác phần tử và chèn vào xgiữa mỗi phần. Lưu ý rằng, trong trường hợp này, dấu ngoặc là cần thiết ngay cả khi xlà số.


Pps. Một cách tiếp cận khác là sử dụng các biến được đặt tên động. Ví dụ,

 'foo' 42 ':x'\+~

sẽ gán giá trị 'foo'cho biến x42, trong khi

 42 'x'\+~

sẽ lấy nó

Bạn có thể tối ưu hóa điều này hơn nữa bằng cách bỏ qua xtiền tố và chỉ gán trực tiếp cho các chữ số - điều này hoàn toàn hợp pháp trong GolfScript và cho phép bạn lưu một char từ mã gán và rút ngắn mã truy xuất thành `~(hoặc không có gì cả, nếu chỉ số không đổi!). Dĩ nhiên, mặt trái là việc gán cho một chữ số sẽ ghi đè giá trị của chữ đó ở bất kỳ nơi nào khác trong mã của bạn. Tuy nhiên, thông thường, việc sử dụng chữ số có thể tránh được (hoặc ít nhất là bị hạn chế ở phần đầu của chương trình, trước khi bất kỳ phần nào trong số chúng được gán lại), trong trường hợp thủ thuật này là hoàn toàn tốt.


3
Hoàn toàn lạc đề: chúc mừng 10k! :-D
Doorknob

1
Nếu bạn biết rằng mảng không có các giá trị trùng lặp, bạn có thể thay thế một giá trị tại chỉ mục icho 9 byte:.[i=]/[x]*
Martin Ender

5

Thao tác đầu ra cuối cùng

Theo mặc định, khi chương trình của bạn kết thúc, trình thông dịch GolfScript sẽ xuất mọi thứ trên ngăn xếp, cộng với một dòng mới cuối cùng, chính xác như thể chương trình của bạn kết thúc bằng:

]puts

Điều mà tài liệu không đề cập trực tiếp là trình thông dịch gọi theo nghĩa đen là tích hợp sẵn putsđể tạo đầu ra này và rằng phần dựng sẵn này được định nghĩa theo nghĩa đen là:

{print n print}:puts;

Vì vậy, bạn có thể ngăn chặn hoặc thao túng kết quả cuối cùng bởi xác định lại puts, print và / hoặc n(hoặc  nếu bạn đang cảm thấy thực sự xoắn). Dưới đây là một số ví dụ:

Bỏ qua dòng mới cuối cùng:

'':n;

(Tất nhiên bạn có thể bỏ qua ;nếu bạn không nhớ thêm một chuỗi trống trên ngăn xếp.)

Bỏ hoàn toàn đầu ra cuối cùng:

:puts

Điều này ghi đè lên putsvới bất cứ điều gì xảy ra ở trên cùng của ngăn xếp. Nếu điều đó xảy ra là điều bạn không muốn thực thi, 0:puts;thay vào đó bạn có thể sử dụng . Lưu ý rằng điều này cũng triệt tiêu p(được định nghĩa là {`puts}:p;), nhưng bạn vẫn có thể sử dụng printcho đầu ra nếu bạn muốn.


nothingý bạn là \ngì?
Máy

Nếu bạn không quan tâm đến dòng mới, bạn cũng có thể sử dụng ];để chặn đầu ra cuối cùng.
lãng phí

5

Tôi muốn hỏi những cách tốt nhất để làm: giá trị tối thiểu, tối đa và tuyệt đối. Tất cả các giải pháp của tôi dường như chiếm nhiều nhân vật hơn họ nên làm. -

nhỏ nhất lớn nhất

Để tìm giá trị nhỏ nhất / lớn nhất trong một mảng, chỉ cần sắp xếp nó và lấy phần tử đầu tiên / cuối cùng:

  • $0= (3 ký tự) - yếu tố tối thiểu trong một vũ trang
  • $-1= (4 ký tự) - phần tử tối đa trong một mảng

Nếu bạn biết độ dài của mảng và 10 phần tử trở xuống, bạn có thể tìm mức tối đa trong ba ký tự bằng cách thay thế -1bằng chỉ mục của phần tử cuối cùng.

Nếu bạn có các giá trị trên ngăn xếp, trước tiên bạn có thể thu thập chúng thành một mảng. Đối với điều này, một mẹo đôi khi hữu ích là[\] thu thập hai phần tử trên cùng của ngăn xếp thành một mảng, trong khi [@]thu thập ba phần tử trên cùng. Vì vậy, chúng tôi nhận được:

  • [\]$0= (6 ký tự) - tối thiểu hai giá trị trên ngăn xếp
  • [@]$0= (6 ký tự) - tối thiểu ba giá trị trên ngăn xếp
  • [\]$1= (6 ký tự) - tối đa hai giá trị trên ngăn xếp
  • [@]$2= (6 ký tự) - tối đa ba giá trị trên ngăn xếp

Thủ thuật tương tự cũng có thể được sử dụng để tìm trung vị của ba giá trị, đôi khi có thể hữu ích:

  • [@]$1= (6 ký tự) - trung vị của ba giá trị trên ngăn xếp

Đây là một mẹo có khả năng hữu ích khác để tìm giá trị tối thiểu / tối đa của hai giá trị trong khi để lại các giá trị ban đầu trên ngăn xếp :

  • .2$>$ (5 ký tự) - tìm tối thiểu hai giá trị trên ngăn xếp, trong khi không để lại giá trị gốc
  • .2$<$ (5 ký tự) - tìm tối đa hai giá trị trên ngăn xếp, trong khi không để lại giá trị gốc

Cách thức hoạt động của nó là .2$sao chép hai phần tử trên cùng của ngăn xếp theo thứ tự đảo ngược (nghĩa là a ba b b a), </ >so sánh các bản sao và trả về 0 hoặc 1, và vô hướng $sau đó sao chép một trong hai giá trị đầu vào tùy thuộc vào kết quả so sánh.


Nếu bạn có hai số nguyên không âm trên ngăn xếp, bạn có thể sử dụng ,\,&,(5 ký tự) để tìm mức tối thiểu của chúng và ,\,|,(5 ký tự) để tìm mức tối đa của chúng. Thủ thuật này sử dụng giao cắt và liên kết tương ứng trên các phạm vi. Bạn có thể lưu một ký tự khác nếu có thể áp dụng, cho từng đối số mà không phải trao đổi chúng. Vì phương pháp này tính toán một phạm vi cho mỗi đối số, nên nó không hiệu quả đối với các số lớn hơn, nhưng có thể rất hữu ích cho các đầu vào nhỏ hơn.

Một cách thậm chí ngắn hơn để tìm tối thiểu hai số nguyên không âm trên ngăn xếp là ,<,(3 ký tự). Than ôi, thủ thuật này không hoạt động để tìm tối đa.


giá trị tuyệt đối

Toán tử giá trị tuyệt đối tích hợp trong GolfScript là abs(3 ký tự). Mặc dù đây là hai ký tự nhiều hơn tôi muốn, nhưng nói chung thật khó để đánh bại.

Trong một số trường hợp (ví dụ: để sắp xếp theo giá trị tuyệt đối), bạn có thể thấy bình phương của một số thay thế đầy đủ cho giá trị tuyệt đối của nó; điều này có thể được tính trong hai ký tự, 2?hoặc .*. Vì vậy, chúng tôi nhận được:

  • {.*}$0= (7 ký tự) - phần tử tối thiểu theo giá trị tuyệt đối trong mảng
  • {.*}$-1= (8 ký tự) - phần tử tối đa theo giá trị tuyệt đối trong mảng

Tương tự, thay vì kiểm tra ví dụ nếu giá trị tuyệt đối của một số nhỏ hơn 3 với abs 3<(6 ký tự, bao gồm cả khoảng trắng), bạn có thể kiểm tra xem bình phương của nó có nhỏ hơn 9 với .*9<(4 ký tự, không cần khoảng trắng).


Nếu bạn có hai số nguyên không âm trên ngăn xếp, bạn có thể sử dụng ,\,&,(5 ký tự) để tìm mức tối thiểu của chúng và ,\,|,(5 ký tự) để tìm mức tối đa của chúng. Thủ thuật này sử dụng giao cắt và liên kết tương ứng trên các phạm vi. Bạn có thể lưu một ký tự khác nếu có thể áp dụng riêng ,cho từng đối số mà không phải trao đổi chúng. Vì phương pháp này tính toán một phạm vi cho mỗi đối số, nên nó không hiệu quả đối với các số lớn hơn, nhưng có thể rất hữu ích cho các đầu vào nhỏ hơn.
KirarinSnow

@KirarinSnow: Cảm ơn! Tôi đã thêm nó vào câu trả lời.
Ilmari Karonen

4

Loại bỏ trùng lặp từ một mảng

Các toán tử tập hợp |(union), &(ngã tư) và^ (khác biệt đối xứng) sẽ thu gọn nhiều phần tử mảng thành một. Vì vậy, cách đơn giản nhất để loại bỏ các phần tử trùng lặp khỏi một mảng là lấy liên kết hoặc giao điểm của nó với chính nó:

.|

hoặc là:

.&

Các toán tử này sẽ coi các chuỗi là các mảng ký tự, vì vậy chúng cũng có thể được sử dụng để loại bỏ các ký tự trùng lặp khỏi chuỗi.


4

Phiên âm có giới hạn

Để giải quyết một truy vấn con cụ thể: đưa ra một chuỗi, cách tốt nhất để thực hiện là trgì? Ví dụtr/ABC/abc/

Nếu tất cả các ký tự trong chuỗi sẽ bị ảnh hưởng, điều này khá dễ dàng: {'ABC'?'abc'=}% (trên cao: 9 ký tự).

Tuy nhiên, điều đó sẽ phá vỡ nếu một số ký tự không được phiên âm và 'ABC'?đưa ra-1 .

Nếu việc chuyển ngữ không theo chu kỳ, nó có thể được thực hiện một lần thay thế tại một thời điểm với các chuỗi phân tách và nối: 'AaBbCc'1/2/{~@@/\*}/(trên cao: 15 ký tự). Điều này có thể là ngẫu hứng, nhưng có một cách tiếp cận khác hiện đang tốt hơn và hoạt động cho phiên âm theo chu kỳ.

Hiện tại, các giải pháp chung ngắn nhất có tổng cộng 14 ký tự:

  • Một cách tiếp cận liên quan đến một ký tự thoát : , trong đó biểu thị một byte rỗng bằng chữ. (Tất nhiên, phương thức này không hoàn toàn chung chung: nó không thể ánh xạ bất kỳ ký tự nào khác thành một byte rỗng.){.'ABC'?'abc0'=\or}%0

  • Ngoài ra, {.'ABC'?'abc'@),+=}%có cùng chi phí, nhưng chỉ sử dụng các ký tự ASCII có thể in. Đây @),+là một cách phức tạp (nhưng, rõ ràng, ngắn nhất) để đảm bảo rằng chuỗi thay thế luôn kết thúc bằng ký tự đầu vào.


Sử dụng phương pháp cuối cùng, cho chuỗi đầu vào 'ABCDEF'tôi nhận được kết quả 'abc000', nhưng kết quả đúng sẽ là 'abcDEF'. Tui bỏ lỡ điều gì vậy?
Cristian Lupascu

1
@ w0lf, số 0 đó được in đậm vì đó là ký tự thoát được đề cập trước đó - tức là byte 0.
Peter Taylor

4

Biến một chuỗi thành một mảng char

Bạn có thể làm điều này bằng cách gõ: 1/sau nó.

Ví dụ: "String"1/đẩy để xếp chồng mảng ['S''t''r''i''n''g'].

Điều này rất hữu ích khi bạn muốn di chuyển ký tự xung quanh chuỗi.


1
Bạn có thể đưa ra một ví dụ về làm thế nào điều này có thể có ích? Các chuỗi đã hoạt động như các mảng vì vậy điều này dường như không hữu ích.
Justin

@Quincunx thật tiện lợi khi bạn muốn bật ra các ký tự và không phải giá trị ascii của họ
user3700847

Và khi nào bạn muốn làm điều đó?
Justin

5
@Quincunx: Xoay một chuỗi chẳng hạn. "abc"1/(+-> "bca", nhưng "abc"(+-> bc97.
Dennis

4

Gán cho số chữ

Thông thường, thay vì viết 1:xvà sau đó sử dụng / cập nhật biến x, bạn chỉ có thể sử dụng và cập nhật 1trực tiếp:

1:^;{^.p.+:^;}5*
{1.p.+:1;}5*       (4 bytes shorter)

Tất nhiên, điều này cũng hoạt động cho các giá trị bắt đầu khác, nhưng sẽ phá vỡ nếu giá trị đó xảy ra ở bất kỳ nơi nào khác trong mã của bạn.

Dấu câu dưới dạng tên biến

Nếu bạn sử dụng các biến, nó cũng thường khôn ngoan để sử dụng dấu chấm câu đó không phải là đã có trong mã của bạn - rất nhiều chương trình có thể làm mà không có &, |, ^, hoặc ?. Bằng cách này, ví dụ, bạn có thể viết &nthay vì x nđẩy biến của mình và sau đó đẩy một dòng mới.


3
Một số bài tập có thể có tác dụng phụ bất ngờ, mặc dù. Đặc biệt, giao đến !thường là một ý tưởng tồi, vì nó sẽ phá vỡ ifdo(cũng như while, until, and, orxor). Tương tự, orđược trình thông dịch định nghĩa là bí danh 1$\if, do đó 1, xác định lại $hoặc \cũng sẽ phá vỡ nó. Xác định lại `thời gian nghỉ p.
Ilmari Karonen

3

Lọc một mảng

Cách tổng quát nhất để lọc một mảng là sử dụng { },, đánh giá khối mã cho từng phần tử của mảng và chọn các phần tử mà giá trị kết quả là đúng (nghĩa là nó hoạt động như greptrong Perl).

Tuy nhiên, sử dụng toán tử trừ mảng -thường ngắn hơn. Toán tử này có hai mảng và loại bỏ mọi phần tử xảy ra trong mảng thứ hai từ mảng thứ nhất. Nó không làm thay đổi thứ tự của các phần tử trong mảng đầu tiên hoặc thu gọn các bản sao. Một mẹo hữu ích là áp dụng thao tác trừ hai lần để mang lại toán tử giao điểm mảng không sụp đổ:

  • a b -: loại bỏ bất kỳ phần tử nào được tìm thấy trong mảng bkhỏi mảnga
  • a. b --: loại bỏ bất kỳ phần tử nào không tìm thấy trong mảng bkhỏi mảnga

Cụ thể, điều này có thể được sử dụng để đếm số lần một phần tử xảy ra trong một mảng:

  • a.[c]--,: đếm số lần phần tử cxảy ra trong mảnga

Nói chung, phương pháp này không tối ưu, vì một trong hai:

  • a[c]/,(: đếm số lần phần tử cxảy ra trong mảnga
  • a{c=},,: đếm số lần phần tử cxảy ra trong mảnga

ngắn hơn một ký tự (và, nếu không có gì để số đếm bị tắt bởi một, hãy a[c]/,lưu thêm một ký tự). Tuy nhiên, trong trường hợp đặc biệt clà một số và alà một mảng bình thường (không phải là một chuỗi), dấu ngoặc vuông xung quanhc có thể bị bỏ qua vì -toán tử ép các đối số của nó thành cùng loại:

  • a.c--,: đếm số lần số c xảy ra trong mảng (không phải chuỗi!)a

(Nếu alà một chuỗi và clà một số từ 0 đến 9, a.c--sẽ đếm số lần chữ số c xảy ra a.)


Một thủ thuật tương tự có thể được sử dụng để tìm phần tử phổ biến nhất trong một mảng :

:a{a\[.]-,}$0=

Một lần nữa, nếu đầu vào là một mảng các số, toàn bộ [.]chuỗi có thể bị bỏ qua. Than ôi, điều này không làm việc cho chuỗi mà không có [.].


Để đếm số lần xuất hiện (trường hợp chung) a[c]/,(a{c=},,ngắn hơn một byte.
Dennis

@Dennis: Cảm ơn! Tôi đã chỉnh sửa nó trong.
Ilmari Karonen

3

Đọc từ STDIN

GolfScript có thể đọc từ stdin:

"#{STDIN.read}"

Điều này sẽ tiếp tục đọc từ STDIN cho đến khi đạt được EOF. Cách khác:

"#{STDIN.gets}"

hoặc là

"#{STDIN.readline}"

Những thứ khác có sẵn:

getbyte
getc
gets([sep])
gets(limit)
gets(sep, limit)
inspect # perhaps useful for an underhanded contest
isatty
read([length])
readbyte
readchar
readline([sep])
readline(limit)
readline(sep, limit)
readlines([sep])
readlines(limit)
readlines(sep, limit)
readpartial(maxlen [, outbuf])

Đối với mỗi trong số này, chúng chỉ có thể được sử dụng một lần (và cũng có thể một lần cho mỗi thay đổi của tham số, cũng một lần nữa với dấu ngoặc rỗng); sau đó, giá trị ban đầu là những gì bạn sẽ nhận được thay vì một giá trị mới.


2
Bạn có thể muốn thêm một nhận xét {"#{STDIN.readline}"p}2*không đọc 2 dòng mà thay vào đó, chuỗi chỉ được đánh giá một lần.
Howard

2
Nếu bạn khởi tạo ibất kỳ số nguyên nào, '"#{'i):i';STDIN.gets}"'++~sẽ cho kết quả khác nhau mỗi lần đánh giá. Backticks cũng có thể được đề cập. Nếu chúng ta giả sử Linux, chúng ta có thể sử dụng, ví dụ, `head -1`thay vì STDIN.gets.
Dennis

@Dennis: "#{var'g','gpush Gstring.new(STDIN.gets)'.cc}";cũng sẽ cho phép bạn xác định toán tử GolfScript mới g đọc một dòng từ stdin và đẩy nó lên ngăn xếp.
Ilmari Karonen

2

Giải mã đầu vào thập lục phân

GolfScript không có số nguyên hex, vì vậy, than ôi, bạn không thể phân tích cú pháp đầu vào thập lục phân bằng ~. Thay vào đó, nếu mã của bạn phải lấy đầu vào hex, bạn sẽ cần phân tích cú pháp bằng tay.

Vòng lặp 8 ký tự này, được áp dụng cho một chuỗi, sẽ chuyển đổi các chữ số hex chữ thường thành tương đương số của chúng:

{39%9-}%

Nếu bạn phải (cũng) chấp nhận chữ số hex viết hoa, giải pháp dễ nhất (và có thể ngắn nhất) là trước tiên viết thường chúng với 32|, với tổng số 11 ký tự:

{32|39%9-}%

Lưu ý rằng về mặt kỹ thuật vẫn sẽ là một chuỗi (bao gồm các ký tự ASCII 0 - 15), nhưng hầu hết các hàm mảng GolfScript cũng sẽ chấp nhận chuỗi. Nếu bạn thực sự cần một mảng, bạn luôn có thể sử dụng [{39%9-}/](trong đó đầu tiên [là tùy chọn nếu ngăn xếp trống nếu không).

Để chuyển đổi đầu ra của mã ở trên thành một số nguyên, bạn chỉ cần sử dụng 16base(6 ký tự). Nếu bạn muốn có một mảng byte thay vào đó, giải pháp ngắn nhất tôi tìm thấy chỉ đơn giản là giải mã từng cặp chữ số hex bằng 2/{16base}%(11 ký tự). Tất cả được đặt cùng nhau, mã ngắn nhất tôi tìm thấy để biến một chuỗi hex thành một mảng byte là 8 + 11 = 19 ký tự:

{39%9-}%2/{16base}%

Lưu ý rằng đầu ra của mã này thực sự là một mảng, không phải là một chuỗi. Nếu cần, bạn có thể xâu chuỗi nó bằng cách nối nó, ví dụ như với ""+hoặc, nếu bạn không nhớ một dòng mới bổ sung ở cuối , n+.


2

Xác định toán tử tích hợp mới

Trình thông dịch GolfScript tiêu chuẩn có một tính năng hiếm khi được sử dụng cho phép mã Ruby được nội suy theo hai chuỗi ký tự được trích dẫn.

Một lý do tại sao tính năng này không được sử dụng phổ biến hơn là, một cách vụng về, mã nội suy được thực thi tại thời gian biên dịch và đầu ra được trình thông dịch GolfScript lưu vào bộ đệm để cùng một chuỗi ký tự sau đó sẽ luôn mang lại cùng một giá trị, ngay cả bên trong chuỗi eval.

Tuy nhiên, một điều mà tính năng này hóa ra là tốt cho việc xác định các toán tử GolfScript mới được triển khai theo mã Ruby. Ví dụ: đây là cách xác định toán tử cộng nhị phân mới hoạt động giống như +toán tử tích hợp chuẩn:

"#{var'add','gpush a+b'.cc2}";

Nó không thực sự quan trọng khi bạn đặt định nghĩa trong mã của bạn; toán tử mới được định nghĩa ngay khi chuỗi trích dẫn kép chứa mã Ruby được phân tích cú pháp. Các addnhà điều hành được xác định trên công trình chính xác như được xây dựng trong +điều hành, và có thể được sử dụng trong một cách chính xác theo cùng một cách:

1 2 add          # evaluates to 3
"foo" "bar" add  # evaluates to "foobar"

Tất nhiên, việc xác định toán tử bổ sung mới là khá vô ích, trừ khi bạn đã làm điều gì đó ngớ ngẩn như xóa +toán tử tích hợp . Nhưng bạn có thể sử dụng cùng một mẹo để xác định các toán tử mới thực hiện những điều mà Golfscript không thể (dễ dàng) thực hiện một cách tự nhiên như, giả sử, xáo trộn đồng đều một mảng:

"#{var'shuf','gpush a.factory(a.val.shuffle)'.cc1}";

10,shuf          # evaluates to 0,1,2,...,9 in random order

hoặc in nội dung của toàn bộ ngăn xếp:

"#{var'debug','puts Garray.new($stack).ginspect'.cc}";

4,) ["foo" debug  # prints ["" [0 1 2] 3 "foo"], leaving the stack untouched

hoặc đầu vào tương tác:

"#{var'gets','gpush Gstring.new(STDIN.gets)'.cc}";

]; { "> " print gets ~ ]p 1 } do   # simple GolfScript REPL

hoặc thậm chí truy cập web:

"#{
  require 'net/http'
  require 'uri'
  var'get','gpush Gstring.new(Net::HTTP.get_response(URI.parse(a.to_s)).body)'.cc1
}";

"http://example.com" get

Tất nhiên, việc triển khai phần sau golfer (và rủi ro hơn!) Sẽ là:

"#{var'get','gpush Gstring.new(`curl -s #{a}`)'.cc1}";

Mặc dù bản thân nó không đặc biệt chơi gôn, nhưng điều này cho phép bạn mở rộng khả năng của GolfScript ngoài những gì các lệnh tích hợp cung cấp.


Làm thế nào nó hoạt động?

Tất nhiên, tài liệu tham khảo có thẩm quyền về cách xác định các toán tử GolfScript mới theo cách này là mã nguồn cho trình thông dịch . Điều đó nói rằng, đây là một vài mẹo nhanh:

  • Để xác định toán tử mới namechạy mã Ruby code, hãy sử dụng:

    var'name','code'.cc
  • Bên trong mã, sử dụng gpopđể đọc một giá trị khỏi ngăn xếp và gpushđẩy một giá trị trở lại. Bạn cũng có thể truy cập ngăn xếp trực tiếp qua mảng $stack. Ví dụ, để đẩy cả hai ablên ngăn xếp, việc chơi gôn sẽ $stack<<a<<btốt hơn gpush a;gpush b.

    • Các vị trí của các [dấu bắt đầu mảng được lưu trữ trong $lbmảng. Các gpopchức năng chăm sóc điều chỉnh các điểm đánh dấu xuống nếu stack co lại xuống đến vị trí của họ, nhưng thao tác $stackmảng trực tiếp thì không.
  • Các .ccphương pháp chuỗi mà biên dịch mã Ruby trong một chuỗi thành một nhà điều hành GolfScript chỉ là một wrapper tiện xung quanh Gblock.new(). Nó cũng có các biến thể .cc1, .cc2.cc3khiến các nhà điều hành tự động bật 1, 2 hoặc 3 đối số ra khỏi stack và gán chúng cho các biến a, bc. Ngoài ra còn có một .orderphương thức hoạt động như thế .cc2, ngoại trừ việc nó tự động sắp xếp các đối số theo mức độ ưu tiên .

  • Tất cả các giá trị trên stack GolfScript là (và nên) đối tượng của loại hình Gint, Garray, Gstringhoặc Gblock. Số nguyên hoặc mảng gốc bên dưới, nếu cần, có thể được truy cập thông qua .valphương thức.

    • Tuy nhiên, lưu ý rằng Gstring.valtrả về một mảng của Gints! Để biến một Gstringchuỗi thành chuỗi Ruby gốc, .to_sthay vào đó , hãy gọi nó (hoặc sử dụng nó trong ngữ cảnh tự động thực hiện, như nội suy chuỗi). Gọi .to_gsbất kỳ giá trị GS nào cũng biến nó thành một Gstring, vì vậy mọi giá trị GS đều có thể được xâu chuỗi bằng .to_gs.to_s.
  • Các gpushchức năng không tự động quấn số của Ruby tự nhiên, chuỗi hoặc mảng thành các loại GS tương ứng, vì vậy bạn sẽ thường xuyên phải làm điều đó cho mình bằng cách gọi một cách rõ ràng ví dụ Gstring.new(). Nếu bạn đẩy bất cứ thứ gì ngoài một trong các loại giá trị GS lên ngăn xếp, bất kỳ mã nào sau đó cố gắng thao tác nó đều có khả năng bị sập.

  • Các loại giá trị GS cũng có một .factoryphương thức gọi hàm tạo của kiểu, có thể hữu ích, ví dụ như để sắp xếp lại các mảng / chuỗi sau khi thao tác với nội dung của chúng. Tất cả các loại cũng có một .coercephương thức thực hiện cưỡng chế kiểu : a.coerce(b)trả về một cặp chứa abép buộc cùng loại.

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.