卢阿打高尔夫球的技巧


21

您在Lua打高尔夫球有哪些一般秘诀?我正在寻找可以应用于编码高尔夫问题的想法,这些想法至少在某种程度上是特定于Lua的(例如,“删除评论”不是答案)。请为每个答案发布一个提示。


6
提示问题应该是社区Wiki。但是,对于那些以“主要基于意见”为基础提交此书的人,“高尔夫语言提示” 问题是我们对该规则的公认例外。这些问题的开放性是为什么它们是社区Wiki版本。
Jonathan Van Matre 2014年

Answers:


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)do str:rep(12)。这样也可以(仅通过这种方式)对非变量起作用:("a"):rep(5)

  • 而不是做的tonumber(str)只是做str+0

  • 对于没有参数的函数function tick() blabla() end,您可以执行:,而不是使用常规方法()定义它们ticks=loadstring"blabla()",根据内容,它可以节省1个或更多字节。另外,如果定义了多个函数,请loadstring在之前将其本地化为1个字符的变量,这样可以节省很多字节;)。感谢这个技巧的吉姆·鲍文斯(Jim Bauwens)。

  • Lua 在条件测试0中将空字符串(与其他语言不同)认为是真实的,因此,例如,与其这样做while 1 do ... end,不如通过写入来节省1个字节while''do ... end


(添加了负载字符串技巧)
Adriweb 2014年

2
0为真实值只是愚蠢
SuperJedi224 '16

另一个str+0等效项是~~str,可以优先使用它
Felipe Nardi Batista

@FelipeNardiBatista但是只有Lua 5.3+支持
Adriweb

5

我已经想到了一个。我不知道它是否可以在其他语言中工作,但是Lua是我所知道的唯一允许您将函数存储在变量中的语言。因此,如果string.sub在程序中多次使用了eg,请使用eg s=string.sub


4
它也可用于许多其他语言,例如Python和Ruby。
nyuszika7h 2014年

4
Javascript和Haskell也可以具有函数值。
自豪的haskeller 2014年

这等效于s=("").sub或包含字符串值的s=a.sub任何变量a
Egor Skriptunoff 2015年

这被称为一流的功能
Redwolf Programs,

5

这是打高尔夫球的一种非常冗长的语言...但是我想到的一些一般性提示是:

  • 尽量避免条件语句,因为if... ... then... ... else... ... end是一大浪费。
  • 相反,请尝试着眼于较短的语言结构,例如for i=1,5 do
  • #运营商对高尔夫非常伟大的(和一般)。

5

缩短无限循环

当您必须使用无限循环时,您可能会想到使用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]

这种方法的每一种都允许我们接受1个输入,而函数是成本最高的函数(但允许我们接受一张表作为输入)

现在我们可以看到,如果您想打高尔夫球,使用命令行参数是必经之路,但请注意:它甚至可以更短

arg[1]
...

...是在LUA有点特殊,它含有的解压缩内容的变量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!

在几乎没有情况下,使用if / elseif / if语句的成本将低于三元组。这样的声明的样板真的很沉重:

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

通过一个简单的示例,您已经节省了12个字节,当您不得不做其他操作时,它变得越来越重要,因此请注意这一点!

另外,lua中的三元是特殊的,它们的工作方式有一定条件,对于那些感兴趣的人,我将在下面进行解释:

lua中的三元形式为 <condition> and <case true: have to be a true value> or <case false: can be anything>

首先,让我们看一下的真值表oror可以将A 视为函数:它总是返回一个值,这是它返回的值:

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

这就是允许我们构造三元组的原因。

and是什么让我们评估条件,它总是返回y如果x and y计算结果为True。

问题是如果条件为,如果我们希望a nilfalse返回,它将失败false。例如,以下条件将始终返回5,即使条件为true。

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

在某些情况下,您可以更进一步。Lua允许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在Lua中逐个字符地进行迭代。有时,这可能效果最好,具体取决于您的需求,但是有时,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 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计算结果为在Lua假的,其他的一切都是真的,所以你对更换的提示x==0x==""x==''通过x是假的。我当前将其更改为nil:)。
Katenkyo '16

啊,你是对的。感谢您解决该问题!
Skyl3r '16

2

这些只是Lua(我认为)优化:

对字符串进行算术运算时,它们会自动转换为数字。只要注意条件语句,它们不会自动转换。这对于将用户输入作为数字同时节省空间非常有用。

切换两个变量的内容不需要临时变量。a,b=b,a将交换a和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的括号以强制其仅返回一个值

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

1

知道如何输出

在lua中有两种主要的输出方法

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哇,我什至不知道该怎么做。感谢您指出,我将编辑
Katenkyo,

1

一堆没有特别顺序的提示:

  • string是很长的名字。有效地,('').char与相同string.char。如果将它与分号一起使用,甚至可以获得更好的结果:a=...; print(a:sub(1, 5)),但是某些string函数不会将字符串作为输入。
  • lua有字符串和数字之间自动转换在大多数情况下,所以tonumber+0往往只浪费字节。
  • 始终使用load'your function code here'代替function()your function code here end。使用...inside 访问函数参数。
  • Lua中的某些字符串函数可能会以意外方式使用!例如,a:gsub('.',load'my function')似乎是迭代字符串中字符的最短方法
  • 尽管字符串引擎功能强大,但是在将用户输入用作模式时要提防它的强大功能!因此,您可能必须使用a:find('.',1,1)(要测试此问题,请尝试%在输入中的各个位置添加并检查结果)。由于Lua尝试将输入解析为模式,因此无数创意破灭。
  • nil是三个字节,_是一个字节(它只是随机名称,很可能不存在)。此外,任何数字都将用作真实值。
  • 了解背后的逻辑x and i or o。它不仅仅是一个三元运算符-它是一个完整的逻辑表达式。实际上,这意味着:“如果x是真实的,请尝试i。如果x或i都是虚假的,则返回o”。因此,如果i不成立,则结果为o。此外,两个andor部件可以被省略(x and ix or o)。
  • 使用整数除法代替math.floor5.3//1==5.0。请注意,结果数字始终遵循输入一的类型(整数/浮点数)。

1
“此外,任何数字都将作为真实值。” 只是想说明一下它包含0,对于C / C ++背景的某些编码人员来说可能不是很直观。
ouflak
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.