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


21

Bạn có lời khuyên chung nào cho việc chơi golf ở Lua? Tôi đang tìm kiếm những ý tưởng có thể được áp dụng cho các vấn đề về golf nói chung ít nhất là cụ thể đối với Lua (ví dụ: "xóa bình luận" không phải là một câu trả lời). Xin vui lòng gửi một lời khuyên cho mỗi câu trả lời.


6
Câu hỏi mẹo nên được cộng đồng wiki. Nhưng với bất kỳ ai đã gửi bài này gần như là "chủ yếu dựa trên quan điểm", Mẹo chơi gôn trong các câu hỏi ngôn ngữ là ngoại lệ được chấp nhận của chúng tôi đối với quy tắc đó. Bản chất mở của những câu hỏi này là tại sao chúng là cộng đồng wiki-ed.
Jonathan Van Matre 17/03/2016

Câu trả lời:


9

Ngoài những thủ thuật đã được đăng, đây là một số thủ thuật tôi đã thu thập theo thời gian, không theo thứ tự cụ thể ...

  • Đối với các lệnh gọi hàm chỉ có một tham số được phân tách bằng ký hiệu ( "đối với chuỗi, {đối với bảng), tham số không cần phải được bao quanh dấu ngoặc đơn.
    Ví dụ, thay vì làm print("hello"), bạn chỉ có thể làm:print"hello"

  • Xóa càng nhiều khoảng trắng càng tốt - điều này đặc biệt dễ thực hiện sau khi một biểu tượng đóng chuỗi (hoặc trước khi mở), gọi hàm, bảng ...
    Thay vì print(42) a=1bạn có thể làm print(42)a=1. Ví dụ khác : print(a and-1 or-2).

  • Sử dụng toán tử ternary khi bạn có thể! Thay vì if a>0 then print("hello") else print("goodbye") end, thích print(a>0 and "hello" or "goodbye"). Thêm thông tin ở đây .
    (Điều này thực sự có thể trở nên tốt hơn nữa print(a>0 and"hello"or"goodbye"):)

  • Sử dụng đường cú pháp gọi đại tràng khi bạn có thể: thay vì string.rep(str,12)làm str:rep(12). Điều đó cũng hoạt động trên các biến không theo cách này (và chỉ theo cách này):("a"):rep(5)

  • Thay vì làm tonumber(str)chỉ làmstr+0

  • Đối với các hàm không có tham số, thay vì xác định chúng theo cách thông thường ( function tick() blabla() end), bạn có thể thực hiện : ticks=loadstring"blabla()", giúp tiết kiệm 1 hoặc nhiều byte, tùy thuộc vào nội dung. Ngoài ra, nếu bạn xác định nhiều hàm, hãy bản địa hóa loadstringthành biến 1 char trước đó và bạn sẽ tiết kiệm được rất nhiều byte;). Tín dụng cho Jim Bauwens cho thủ thuật này.

  • Lua coi chuỗi rỗng (và 0không giống các ngôn ngữ khác) là đúng trong các bài kiểm tra có điều kiện, vì vậy, ví dụ, thay vì thực hiện while 1 do ... end, hãy lưu 1 byte bằng cách viếtwhile''do ... end


(Đã thêm thủ thuật tải dây)
Adriweb

2
0 là một giá trị trung thực chỉ là ngớ ngẩn
SuperJedi224

str+0tương đương khác ~~str, có thể hữu ích cho sự ưu tiên của nó
Felipe Nardi Batista

@FelipeNardiBatista tuy nhiên điều đó chỉ được hỗ trợ trên Lua 5.3+
Adriweb

5

Tôi đã nghĩ về một. Tôi không biết nếu nó hoạt động trong một số ngôn ngữ khác, nhưng Lua là người duy nhất tôi biết những gì cho phép bạn lưu trữ các hàm trong các biến. Vì vậy, nếu eg string.subđược sử dụng nhiều lần trong chương trình của bạn, hãy sử dụng eg s=string.sub.


4
Nó cũng hoạt động trong nhiều ngôn ngữ khác như Python và Ruby.
nyuszika7h

4
Javascript và Haskell cũng có thể có các giá trị hàm.
tự hào

Điều này tương đương với s=("").subhoặc s=a.subcho bất kỳ biến nào achứa giá trị chuỗi.
Egor Skriptunoff

Đây được gọi là chức năng hạng nhất
Chương trình Redwolf

5

Đó là một ngôn ngữ dài dòng để chơi gôn ... nhưng một số mẹo chung mà bạn nghĩ đến là:

  • Cố gắng tránh các điều kiện, vì if... then... else... endlà một sự lãng phí lớn.
  • Thay vào đó, hãy cố gắng tập trung vào các cấu trúc ngôn ngữ ngắn hơn, ví dụ for i=1,5 do.
  • Các #nhà điều hành là khá tuyệt vời để chơi golf (và nói chung).

5

Rút ngắn vòng lặp vô hạn của bạn

Khi bạn phải sử dụng một vòng lặp vô hạn, bạn có thể nghĩ đến việc sử dụng một while, nhưng sử dụng nhãn thay vì ngắn hơn 2 byte:

while''do end
::a::goto a

Sử dụng ít không gian nhất có thể

Có một điều đơn giản mà bạn có thể (ab) sử dụng để xóa nhiều khoảng trống hơn khỏi mã của mình. Thông số kỹ thuật của Lua rất rõ ràng về tên bạn đặt cho các biến: Chúng phải bắt đầu bằng một chữ cái. Nó ngụ ý rằng, đôi khi, bạn có thể bỏ qua khoảng trắng giữa các số và hàm / biến

x=0>1 and 0or 1print(x)

Khả năng xóa khoảng trắng phụ thuộc vào chữ cái theo số, đây là chữ cái không cho phép bạn làm điều này:

a,b,c,d,e,f            -- They would be interpreted as hexadecimal
x                      -- only fail when after a 0, other number are fine
                       -- (0x indicates the following is an hexadecimal number)

Bằng cách sử dụng điều này và chú ý đến cách bạn gọi các biến của mình, bạn có thể làm cho hầu hết các mã nguồn của mình không có chỗ trống.

Chọn một ví dụ đã có ở đây và sử dụng lời khuyên này, đây là một byte nữa bạn có thể xóa đi :).

print(a and-1 or-2)
print(a and-1or-2)

Sử dụng đúng phương thức nhập

Nếu chúng ta nhìn vào bản mẫu và chi phí cho mỗi lớn loại đầu vào, đây là những gì chúng ta có:

function f(x)x end
io.read()
arg[1]

Mỗi một phương thức này cho phép chúng tôi lấy 1 đầu vào, với chức năng là một đầu vào có chi phí nặng nhất (nhưng cho phép chúng tôi lấy một bảng làm đầu vào)

Bây giờ chúng ta có thể thấy rằng sử dụng đối số dòng lệnh là cách dễ dàng nếu bạn muốn chơi gôn, nhưng lưu ý: nó có thể còn ngắn hơn

arg[1]
...

...một chút đặc biệt trong lua, đó là một biến chứa nội dung được giải nén arghoặc các tham số đã giải nén trong trường hợp hàm matrixdic.

Khi bạn sẽ phải nhận được nhiều hơn một đầu vào và sử dụng từng đầu vào, việc lưu chúng vào một biến là điều tốt. Dưới đây là một số cách để lưu 2 đầu vào trong các biến

a=arg[1]b=arg[2]    -- highly un-efficient, costs 8 bytes by variable
a,b=unpack(arg)     -- costs 15, but at least doesn't depends on the number of argument
a,b=...             -- only costs 7

và đây là cuộc gọi ngắn nhất bạn có thể thực hiện mà không có các biến:

...     -- using a allow a gain of 1-2 bytes at each use
arg[2]  -- using b allow a gain of 4-5 bytes at each use

Từ điểm bạn có 3 đối số hoặc khi bạn sử dụng 2 đối số, với một đối số được sử dụng hai lần, bạn đã đạt được byte do a,b=...! :)

Hầu như không bao giờ sử dụng nếu!

Gần như không có trường hợp nào sử dụng câu lệnh if / otherif / if sẽ có giá thấp hơn một câu ba. cái nồi hơi cho một tuyên bố như vậy là rất nặng:

-- exemple with dumb values
if 1>0then v=1 else v=0 end
v=1>0 and 1or 0

Với một ví dụ đơn giản, bạn đã lưu 12 byte, khi bạn phải thực hiện một số thao tác khác, nó sẽ ngày càng trở nên quan trọng hơn, vì vậy hãy lưu ý điều đó!

Ngoài ra, chim nhạn ở lua rất đặc biệt , có một số điều kiện trong cách chúng hoạt động, đối với những người quan tâm, tôi sẽ giải thích nó dưới đây:

Chim nhạn ở lua có dạng <condition> and <case true: have to be a true value> or <case false: can be anything>

Trước hết, hãy xem bảng chân lý của or. A orcó thể được coi là một hàm: nó luôn trả về một giá trị, đây là giá trị mà nó trả về:

x | y ||x or y
------||-------
0 | 0 ||   y
0 | 1 ||   y
1 | 0 ||   x
1 | 1 ||   x

Đó là những gì cho phép chúng tôi xây dựng chim nhạn của chúng tôi.

Các andlà những gì cho phép chúng tôi đánh giá điều kiện, nó sẽ luôn luôn trở lại ynếu x and yđánh giá lại là true.

Vấn đề với nó là nó sẽ thất bại nếu chúng ta muốn một nilhoặc falseđược trả lại khi có điều kiện false. Chẳng hạn, những điều sau đây sẽ luôn trả về 5, mặc dù điều kiện là đúng.

v = true and false or 5

Dưới đây là từng bước đánh giá của một con chim nhạn để giải thích cách thức hoạt động của nó (nó sẽ hữu ích khi bạn phải lồng chúng :))

-- let's use our dumb ternary
= true and false or 5
-- and statement will be evaluated first, leading to
= false or 5
-- and we saw how the or works
= 5

Một lời khuyên cho mỗi câu trả lời, xin vui lòng.
ATaco

Lưu ý rằng thủ thuật "Sử dụng ít không gian nhất có thể" chỉ hoạt động trên Lua 5.2 trở lên.
Adriweb

4

Tôi đã biên soạn một số lời khuyên là tốt. Tôi chắc chắn rằng một số của tôi sẽ trùng lặp với những gì đã được nêu, nhưng tôi sẽ đưa chúng vào bất cứ cách nào để tạo ra một câu trả lời đầy đủ hơn.


Gán các hàm lặp lại cho các biến

Lua cho phép bạn gán các hàm cho các biến. Thậm chí một biến nhân vật. Điều này có nghĩa là nếu bạn lặp lại chức năng string.sub(x, y)nhiều hơn hai lần, bạn sẽ nhận được lợi ích từ việc gán nó cho một biến.

Không gán cho một biến (69 ký tự):

print(string.sub(x, y))
print(string.sub(x, y))
print(string.sub(x, y))

Gán cho một biến (51 ký tự):

s=string.sub
print(s(x,y))
print(s(x,y))
print(s(x,y))

Có những trường hợp bạn có thể tiến xa hơn một bước này. Lua cho phép OOP xử lý chuỗi, như vậy: str:sub(x, y)hoặc str.sub(x, y)Điều này mở ra các tùy chọn mới cho mã của chúng tôi. Bạn có thể gán một biến cho hàm bằng tham chiếu của nó như được hiển thị (46 ký tự.)

s=z.sub
print(s(x, y))
print(s(x, y))
print(s(x, y))

Sử dụng cách hiệu quả nhất để phân tích chuỗi

Bạn có thể thấy mình sử dụng một forvòng lặp và string.sublặp lại ký tự theo ký tự trong Lua. Đôi khi điều này có thể hoạt động tốt nhất, tùy thuộc vào nhu cầu của bạn, nhưng những lần khác, string.gmatch sẽ hoạt động với ít ký tự hơn. Đây là một ví dụ về cả hai:

s=io.read()
for a = 1, s:len() do
    print(s:sub(a, a))
end 

for i in io.read():gmatch('.') do
    print(i)
end

Và khi chơi golf, sự khác biệt đáng chú ý hơn:

s=io.read()for a=1,s:len()do print(s:sub(a, a))end

for i in io.read():gmatch'.'do print(i)end

Tái cấu trúc các nhiệm vụ để tối ưu hóa khoảng trắng

Trong Lua, bạn không phải đặt ký tự khoảng trắng giữa dấu ngoặc đơn đóng hoặc dấu ngoặc kép kết thúc và ký tự tiếp theo. Cho đến nay, tôi đã tìm thấy hai trường hợp trong đó tái cấu trúc với ý nghĩ này sẽ cắt giảm các ký tự.

  • Gán các biến:

     x,y=io.read(),0 print(x)
     vs.
     y,x=0,io.read()print(x)
    
  • Nếu Tuyên bố:

     if x:sub(1,1)==1 then
     vs
     if 1==x:sub(1,1)then
    

Trả lại ít ký tự nhất có thể

Nếu bạn phải trả về giá trị đúng hoặc sai, thì có vẻ như bạn nhất thiết phải sử dụng ít nhất 5 ký tự cho giá trị trả về. Trong thực tế, các công việc sau đây cũng vậy:

return true
return false
vs
return 1>0
return 0>1

Những mẹo hay, tôi đã tự do đề nghị chỉnh sửa bài viết của mình. Chỉ nilfalseđánh giá lại là false trong lua, mọi thứ khác là đúng, vì vậy lời khuyên của bạn về thay thế x==0, x==""x==''bởi xlà sai. Tôi hiện đang thay đổi nó thành nil:).
Katenkyo

À, bạn đúng rồi. Cảm ơn bạn đã sửa nó!
Skyl3r

2

Đây chỉ là tối ưu hóa Lua (tôi nghĩ):

Chuỗi được tự động chuyển đổi thành số khi thực hiện các phép toán số học trên chúng. Chỉ cần coi chừng các tuyên bố có điều kiện, chúng không tự động chuyển đổi. Điều này là tuyệt vời để lấy đầu vào của người dùng làm số trong khi tiết kiệm không gian.

Chuyển đổi nội dung của hai biến không yêu cầu một biến tạm thời. a,b=b,asẽ trao đổi các giá trị của a và b.

Ngoài ra, để mở rộng những gì đã nói ở trên, bất kỳ ký tự chữ và số nào cũng có thể chạm vào một ký tự không phải là chữ và số. Vì vậy, a,b=io.read():match"(.+)/(.+)"u,v=a,blà một kịch bản hoàn hảo, làm việc, ngay cả khi thiếu khoảng trắng.


2

Kết hợp các bài tập biến cục bộ

Thay vì:

local a=42
local b=17
local c=99

Sử dụng gán song song:

local a,b,c=42,17,19

6 byte được lưu cho mỗi biến!

Khai báo các biến cục bộ thông qua các tham số hàm không sử dụng

Thay vì:

function foo(a,b) local c,d ... end
function bar(a,b) local c,d=42,17 ... end

Sử dụng

function foo(a,b,c,d) ... end
function bar(a,b,c,d) c,d=42,17 ... end

Đã lưu 6 byte (trừ 1-2 byte cho mỗi biến có thể bị trùng lặp).


1
Bị từ chối vì hoàn toàn không có trường hợp sử dụng locallà hợp lý khi chơi golf, bởi vì bạn chỉ cần sử dụng một tên khác. Chúng tôi có thể sử dụng TẤT CẢ các tên lên đến 7 ký tự VÀ bảng với chỉ mục chuỗi lên đến 7 kết hợp ký tự trước khi chúng tôi đạt được thứ gì đó có thể có lợi từ việc sử dụng người địa phương
Katenkyo

1

Chức năng biến thể

Các hàm chính biến sẽ gây rắc rối cho bạn là print(). Chẳng hạn, khi bạn sử dụng nó dọc theo String.gsub()nó sẽ in chuỗi bạn đã sửa đổi VÀ số lần gsubđược kích hoạt.

Để thay thế đầu ra thứ hai đó, hãy đóng gói các gsubparens của bạn để buộc nó chỉ trả về một giá trị

print(String.gsub("aa",".","!"))    -- outputs "!!    2\n"
print((String.gsub("aa",".","!")))  -- outputs "!!\n"

1

Biết cách xuất

Có hai phương pháp đầu ra chính trong lua

io.write()    -- outputs without trailing newline
print()       -- outputs with trailing new line and shorter by 3 bytes

Khi bạn phải nối nhiều lần, bạn có thể rút ngắn điều đó bằng cách sử dụng io.write()gán cho một biến một chữ cái thay vì toán tử ghép nối chuẩn..

i(a)    -- i was defined as io.write
s=s..a

Bạn nhận được 2 byte cho mỗi cuộc gọi trong khi trả trước

i=io.write  -- longer by 6 bytes
s=""

Bạn thậm chí đang kết nối thứ ba và bắt đầu đạt được byte vào lần thứ tư.


3
Nó là printvà không printf!
val nói Phục hồi Monica

@val Wow, tôi thậm chí không biết làm thế nào tôi có thể làm sai lầm đó. Cảm ơn đã chỉ ra, tôi sẽ chỉnh sửa
Katenkyo

1

Một loạt các mẹo không theo thứ tự cụ thể:

  • stringlà tên khá dài. Hiệu quả, ('').chargiống như string.char. Thậm chí kết quả tốt hơn có thể đạt được nếu bạn sử dụng nó cùng với dấu chấm phẩy trên các biến: a=...; print(a:sub(1, 5))nhưng một số stringhàm không lấy chuỗi làm đầu vào.
  • Lua có chuyển đổi tự động giữa các chuỗi và số trong hầu hết các trường hợp, vì vậy tonumber+0thường chỉ lãng phí byte.
  • Luôn luôn sử dụng load'your function code here'thay vì function()your function code here end. Truy cập đối số chức năng bằng cách sử dụng ...bên trong.
  • Một số hàm chuỗi trong Lua có thể được sử dụng theo những cách ngoài ý muốn! Ví dụ, a:gsub('.',load'my function')dường như là cách ngắn nhất để lặp lại các ký tự trong chuỗi
  • Trong khi công cụ chuỗi là mạnh mẽ, hãy cẩn thận với sức mạnh của nó khi sử dụng đầu vào của người dùng làm mẫu! Do đó, bạn có thể phải sử dụng a:find('.',1,1)(để kiểm tra vấn đề này, thử bao gồm %ở nhiều nơi khác nhau trong đầu vào của bạn và kiểm tra kết quả). Vô số ý tưởng đã bị phá vỡ vì Lua cố gắng phân tích cú pháp đầu vào dưới dạng mẫu.
  • nillà ba byte, _là một byte (nó chỉ là tên ngẫu nhiên mà rất có thể không tồn tại). Ngoài ra, bất kỳ chữ số sẽ làm việc như giá trị trung thực.
  • Biết logic của bạn phía sau x and i or o. Nó không chỉ là một toán tử ternary - nó là một biểu thức logic hoàn chỉnh. Trong thực tế, nó có nghĩa như sau: "nếu xlà sự thật, hãy thử i. Nếu x hoặc i là giả, hãy trả về o". Vì vậy, nếu ikhông phải là sự thật, kết quả là o. Ngoài ra, cả hai andhoặc ormột phần có thể được bỏ qua ( x and i, x or o).
  • Sử dụng phép chia số nguyên cho một thay vì math.floor: 5.3//1==5.0. Xin lưu ý rằng số kết quả luôn tuân theo loại đầu vào (số nguyên / float).

1
"Ngoài ra, bất kỳ chữ số nào sẽ hoạt động như giá trị trung thực." Chỉ muốn giải thích rằng điều này bao gồm 0, có thể không trực quan cho một số lập trình viên từ nền tảng C / C ++.
ngerak
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.