루아에서의 골프 팁


21

루아 골프에 대한 일반적인 팁은 무엇입니까? 루아에 대해 다소 특정한 코드 골프 문제에 적용 할 수있는 아이디어를 찾고 있습니다 (예 : "댓글 제거"는 답이 아닙니다). 답변 당 하나의 팁을 게시하십시오.


6
팁 질문은 커뮤니티 위키 여야합니다. 그러나 이것을 "주요 의견 기반"으로 가깝게 제출 한 사람에게는 언어 로 골프를 치기위한 팁 이 해당 규칙의 예외입니다. 이러한 질문의 개방형 특성은 이들이 커뮤니티 위키에있는 이유입니다.
Jonathan Van Matre

답변:


9

이미 게시 된 것 외에도 시간이 지남에 따라 수집 한 몇 가지 트릭이 특정 순서없이 있습니다 ...

  • 기호 ( "문자열, {테이블)로 구분 된 매개 변수가 하나만있는 함수 호출의 경우 매개 변수를 괄호로 묶을 필요는 없습니다.
    예를 들어을 수행하는 대신 print("hello")간단히 다음을 수행 할 수 있습니다.print"hello"

  • 가능한 한 많은 공백을 제거하십시오. 이것은 문자열을 닫는 기호 (또는 한 번 열기 전에), 함수 호출, 테이블 뒤에 수행하는 것이 특히 쉽습니다.
    대신에 print(42) a=1할 수 있습니다 print(42)a=1. 다른 예 : print(a and-1 or-2).

  • 가능하면 삼항 연산자를 사용하십시오! 대신에 if a>0 then print("hello") else print("goodbye") end선호하십시오 print(a>0 and "hello" or "goodbye"). 자세한 내용은 여기를 참조하십시오 .
    (이것은 실제로 더 나은조차 얻을 수 있습니다 print(a>0 and"hello"or"goodbye"))

  • 때 당신이 할 수있는 콜론 통화 문법 설탕을 사용하는 대신 string.rep(str,12), 할 str:rep(12). 그것은 비 변수에 대해서도 이런 식으로 작동합니다 (이 방법으로 만 가능합니다).("a"):rep(5)

  • tonumber(str)그냥하지 말고str+0

  • 매개 변수가없는 함수의 경우 일반적인 방법 ( function tick() blabla() end) 을 정의하는 대신 :을 수행 ticks=loadstring"blabla()"하여 컨텐츠에 따라 1 바이트 이상을 절약 할 수 있습니다 . 또한 여러 함수를 정의하는 경우 loadstring이전에 1 문자 변수로 지역화 하면 많은 바이트를 절약 할 수 있습니다.;). 이 트릭에 대한 Jim Bauwens의 공로.

  • 루아 는 조건부 테스트에서 빈 문자열 (및 0다른 언어와 달리)을 true 로 간주 하므로 예를 들어 대신 수행 while 1 do ... end하여 1 바이트를 저장while''do ... end



2
0 진실한 가치는 바보입니다
SuperJedi224

또 다른 str+0동등한 것은 ~~str, 그것의 우선 순위에 유용 할 수 있습니다
Felipe Nardi Batista

@FelipeNardiBatista 그러나 그것은 Lua 5.3 이상에서만 지원됩니다
Adriweb

5

나는 이미 하나를 생각했다. 다른 언어로 작동하는지는 모르겠지만 Lua는 변수에 함수를 저장할 수있는 유일한 방법입니다. 따라서 string.sub프로그램에서 eg 를 여러 번 사용하는 경우 eg 를 사용하십시오 s=string.sub.


4
또한 Python 및 Ruby와 같은 다른 많은 언어에서도 작동합니다.
nyuszika7h

4
Javascript와 Haskell도 함수 값을 가질 수 있습니다.
자랑스러운 Haskeller

이것은 문자열 값을 포함 하는 변수 와 동일 s=("").sub하거나 동일 합니다. s=a.suba
Egor Skriptunoff

이것을 일급 함수라고합니다
Redwolf 프로그램

5

골프를 치기에는 매우 장황한 언어입니다.하지만 몇 가지 일반적인 팁은 다음과 같습니다.

  • if... then... else... end큰 낭비 이므로 조건을 피하십시오 .
  • 대신, 더 짧은 언어 구성에 초점을 맞추십시오 (예 :) for i=1,5 do.
  • #운영자는 꽤 골프에 좋은 (그리고 일반적으로)입니다.

5

무한 루프를 단축

무한 루프를 사용해야 할 때 a를 사용하는 것을 생각할 수 while있지만 대신 레이블을 사용하는 것이 2 바이트만큼 짧습니다.

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

적은 공간을 사용하십시오

코드에서 더 많은 공간을 제거하는 데 사용할 수있는 간단한 방법이 있습니다. Lua의 스펙은 변수에 부여한 이름에 대해 명확합니다. 문자로 시작해야합니다. 때로는 숫자와 함수 / 변수 사이의 공백을 건너 뛸 수 있음을 의미합니다.

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

공백을 제거 할 수있는 가능성은 숫자 다음에 나오는 문자에 따라 다릅니다.

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)

이를 사용하고 변수를 호출하는 방법에주의를 기울이면 대부분의 소스 코드를 공백없이 만들 수 있습니다.

이미 여기에서 예제를 선택 하고이 조언을 사용하면 면도 할 수있는 바이트가 하나 더 있습니다. :).

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

올바른 입력 방법을 사용하십시오

주요 유형의 입력에 대한 상용구 및 비용을 살펴보면 다음과 같습니다.

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

이 방법을 사용하면 비용이 가장 많이 드는 함수를 사용하여 하나의 입력을 취할 수 있습니다 (그러나 테이블을 입력으로 사용할 수 있습니다)

우리는 이제 골프를 즐기고 싶다면 명령 줄 인수를 사용하는 것이 길이라는 것을 알 수 있습니다.

arg[1]
...

(가) ...루아에서 조금 특별하다, 그것의 압축을 푼 내용을 포함하는 변수 arg또는 가변 기능의 경우 압축을 푼 매개 변수.

둘 이상의 입력을 가져 와서 각각을 사용해야 할 때 변수에 저장하는 것이 좋습니다. 변수에 2 개의 입력을 저장하는 방법은 다음과 같습니다.

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

다음은 변수없이 수행 할 수있는 가장 짧은 호출입니다.

...     -- 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

3 개의 인수가 있거나 2 개의 인수를 사용할 때 하나가 두 번 사용되면 이미 바이트가 생깁니다 a,b=...! :)

거의 사용하지 않는 경우!

if / elseif / if 문을 사용하는 데 3 원 미만의 비용이 드는 경우는 거의 없습니다. 그러한 진술의 상용구는 실제로 무겁습니다.

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

간단한 예제를 사용하면 이미 12 바이트를 절약 할 수 있습니다. 다른 ifif를 수행해야하는 경우 점점 더 중요해 지므로주의하십시오!

또한 루아의 삼항은 특별 합니다. 작동 방식에는 몇 가지 조건이 있습니다. 관심있는 사람들을 위해 아래에서 설명하겠습니다.

루아의 제국은 형태입니다 <condition> and <case true: have to be a true value> or <case false: can be anything>

우선,의 진리표를 보자 or. A or는 함수로 간주 될 수 있습니다. 항상 값을 반환합니다. 다음은 반환되는 값입니다.

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

그것이 우리가 삼항을 구성 할 수있게 해주는 것입니다.

and항상 반환, 우리가 조건을 평가할 수 것입니다 y경우에 x and y평가하여 true로.

그것의 문제는 우리가 원하는 경우 실패 할 것입니다 nil또는 false조건이 때 반환 할 false. 예를 들어, 조건이 true 임에도 불구하고 다음은 항상 5를 반환합니다.

v = true and false or 5

다음은 삼항에 대한 단계별 평가로 작동 방식을 설명합니다 (이를 중첩해야 할 때 유용합니다 :))

-- 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

답변 당 하나의 팁을 부탁드립니다.
ATaco

"가능한 한 적은 공간 사용"트릭은 Lua 5.2 이상에서만 작동합니다.
Adriweb

4

나는 또한 몇 가지 팁을 편집했습니다. 나는 나의 일부가 이미 언급 한 것들과 겹칠 것이라 확신하지만, 더 완전한 답변을 만드는 데는 어떤 식 으로든 포함시킬 것이다.


반복되는 함수를 변수에 할당

Lua를 사용하면 함수를 변수에 할당 할 수 있습니다. 하나의 문자 변수조차도. 즉, 함수를 string.sub(x, y)두 번 이상 반복하면 해당 변수를 변수에 할당하면 이점을 얻을 수 있습니다.

변수에 할당하지 않으면 (69 자) :

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

변수에 지정 (51 자) :

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

이 단계를 더 진행할 수있는 경우가 있습니다. 루아과 같이, 문자열 조작에 OOP를 할 수 있습니다 : str:sub(x, y)또는 str.sub(x, y)이것은 우리의 코드에 대한 새로운 옵션을 엽니 다. 표시된대로 참조에 의해 함수에 변수를 할당 할 수 있습니다 (46 자).

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

문자열을 구문 분석하는 가장 효율적인 방법을 사용하십시오.

루아에서 for루프 string.sub를 사용하고 문자별로 문자를 반복 할 수 있습니다 . 때로는 필요에 따라 가장 잘 작동하지만 때로는 string.gmatch가 더 적은 문자로 작동합니다. 다음은 두 가지 예입니다.

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

그리고 골프를 칠 때 차이가 더 두드러집니다.

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

공백을 최적화하기위한 할당 재구성

Lua에서는 닫힌 괄호 나 따옴표와 다음 문자 사이에 공백 문자를 넣을 필요가 없습니다. 지금까지이를 염두에두고 재구성하면 캐릭터가 잘릴 수있는 두 가지 사례가 있습니다.

  • 변수 할당 :

     x,y=io.read(),0 print(x)
     vs.
     y,x=0,io.read()print(x)
    
  • if 문 :

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

가능한 가장 적은 문자를 반환

true 또는 false 값을 반환해야하는 경우 반환 값으로 5 자 이상을 사용해야합니다. 실제로 다음과 같이 작동합니다.

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

좋은 팁, 나는 당신의 게시물에 대한 편집을 제안하기 위해 자유를 가져 왔습니다. 만 nilfalse교체에 대한 귀하의 팁 있도록 평가하여 루아에서 false로, 다른 모든 것들은, 사실 x==0, x==""그리고 x==''에 의해이 xfalse입니다. 나는 현재 그것을 nil:)로 바꾸고있다 .
Katenkyo

아 맞아. 고쳐 주셔서 감사합니다!
Skyl3r

2

이것들은 Lua 전용 (제 생각에는) 최적화입니다.

문자열은 산술 연산을 수행 할 때 자동으로 숫자로 변환됩니다. 조건문을주의해서 살펴보면 자동으로 변환되지 않습니다. 공간을 절약하면서 사용자 입력을 숫자로 취하는 데 좋습니다.

두 변수의 내용을 전환하는 데 임시 변수가 필요하지 않습니다. a,b=b,aa와 b의 값을 바꿉니다.

또한, 위에서 말한 것을 확장하기 위해, 임의의 영숫자는 영숫자가 아닌 문자를 만질 수있다. 그래서 a,b=io.read():match"(.+)/(.+)"u,v=a,b심지어 공백의 부족으로, 스크립트를 작업, 완벽한입니다.


2

지역 변수 할당 결합

대신에:

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

병렬 할당을 사용하십시오.

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

각 변수에 대해 6 바이트가 절약되었습니다!

사용하지 않는 함수 매개 변수를 통해 지역 변수 선언

대신에:

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

용도

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

6 바이트 저장 (복제 될 수있는 각 변수에 대해 1-2 바이트).


1
local다른 이름을 사용해야하기 때문에 골프를 칠 때 사용 이 정당화되는 경우가 없기 때문에 하향 투표되었습니다 . 지역 이름을 사용하여 이익을 얻을 수있는 무언가를 치기 전에 최대 7 개의 문자와 최대 7 개의 문자 조합을 가진 테이블을 모두 사용할 수 있습니다.
Katenkyo

1

가변 함수

문제가 될 주요 가변 변수는 print()입니다. 예를 들어, 함께 사용 String.gsub()하면 수정 한 문자열과 gsub트리거 된 횟수가 인쇄됩니다 .

두 번째 출력을 억제하려면 gsub하나의 값만 반환하도록 parens를 캡슐화하십시오 .

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

1

출력 방법을 알고

루아에서 출력하는 두 가지 주요 방법이 있습니다

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

여러 번 연결해야하는 io.write()경우 표준 연결 연산자 대신 하나의 문자 변수에 할당하여이를 단축 할 수 있습니다..

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

선불을 지불하면서 각 통화마다 2 바이트를 얻습니다.

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

당신은 세 번째 연결에 있고, 네 번째에 바이트를 얻기 시작합니다.


3
그것은 print아니다 printf!
val은

@val 와우, 나는 그 실수를 어떻게 할 수 있는지조차 모른다. 지적 해 주셔서 감사합니다. 편집
하겠습니다.

1

특별한 순서가없는 팁 :

  • string꽤 긴 이름입니다. 효율적 ('').char으로와 같습니다 string.char. 변수에 세미콜론과 함께 사용하면 더 나은 결과를 얻을 수 a=...; print(a:sub(1, 5))있지만 일부 string함수는 문자열을 입력으로 사용하지 않습니다.
  • 루아는 그래서, 대부분의 경우 문자열과 숫자 사이의 자동 변환을 보유 tonumber하고 +0종종 바이트를 낭비.
  • load'your function code here'대신에 항상 사용하십시오 function()your function code here end. ...내부를 사용하여 함수 인수에 액세스하십시오 .
  • Lua의 일부 문자열 함수는 의도하지 않은 방식으로 사용될 수 있습니다! 예를 들어 a:gsub('.',load'my function')문자열에서 문자를 반복하는 가장 짧은 방법 인 것 같습니다
  • 스트링 엔진은 강력하지만 사용자 입력을 패턴으로 사용할 때 그 힘에주의하십시오! 따라서이 a:find('.',1,1)문제를 테스트하기 위해 %입력의 다양한 위치에 포함 시켜 결과를 확인해야합니다. 루아 (Lua)가 입력을 패턴으로 해석하려고 시도했기 때문에 수많은 아이디어가 깨졌습니다.
  • nil3 바이트, _1입니다 (아마도 존재하지 않는 임의의 이름 일뿐입니다). 또한 모든 숫자는 진실한 가치로 작용합니다.
  • 당신의 논리를 알고 있습니다 x and i or o. 그것은 단지 삼항 연산자가 아니라 완전한 논리적 표현입니다. 실제로는 다음을 의미합니다. " x진실한 경우 시도하십시오 i. x 또는 i가 거짓 인 경우 o를 반환하십시오." 따라서 i진실이 아닌 경우 결과는 o입니다. 또한 둘 다 and또는 or부분을 ​​생략 할 수 있습니다 ( x and i, x or o).
  • math.floor: 대신에 1로 정수 나누기를 사용하십시오 5.3//1==5.0. 결과 숫자는 항상 입력 유형 (정수 / 부동)의 유형을 따릅니다.

1
"또한 모든 숫자는 진실한 가치로 작용할 것입니다." C / C ++ 배경의 일부 코더에게는 직관적이지 않을 수있는 0이 포함되어 있음을 자세히 설명하고 싶었습니다.
ouflak
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.