朱莉娅打高尔夫球的秘诀


20

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

Answers:


19

注意:以下内容可能包含一些过时的技巧,因为Julia在结构上还不太稳定。

一些保存一些字符的技巧

  1. 具有常用二进制函数的重载运算符。例如,如果您需要进行很多整数除法,而无需进行逆除法,请使用\ =div,然后键入即可a\b代替div(a,b)。请注意空格-这是避免将其解析为“ \ =”运算符所必需的。另请注意,如果在REPL提示级别过载,请使用(\)=Base.(\)\ =Base. \重置它。注意:一些功能已预先定义了现有的UTF-8运算符,例如÷for div,如Alex A所指出。
  2. 对字符串使用^作为条件输出。也就是说,不是a>0?"Hi":"",使用"Hi"^(a>0),保存一个字节,或者一个布尔值,使用"Hi"^a保存3个字节。
  3. (有时)将固定大小的小向量存储为单独的变量。例如,而不是a=split("Hi there"," "),你可能能够避免a[1]a[2]利用a,b=split("Hi there"," "),它可以作为引用ab,节省了每次使用三个字节,在短短两年多的字符在分配成本。显然,如果可以使用向量运算,则不要这样做。
  4. 使用[] -用于数组访问Array的第一个元素,表达式A[]等效于A[1]。请注意,如果您想获取第一个字符,则此方法不适用于String或Tuples。
  5. 不要对数组,元组或字符串使用isempty-而是==[]对数组和==()元组使用;同样,对于负数,请使用!=[]!=()。对于字符串,请将其==""用于空值,但将其>""用于非空值,因为按字母顺序,“”在任何其他字符串之前。
  6. 使用正确的短路布尔运算符代替“ if”。它可能不是特定于Julia的,但值得牢记。x<=1&&"Hi"可以写成x>1||"Hi",以保存字符(只要返回布尔值并不重要)。
  7. 不要使用contains来检查字符串中的字符 -如果限于基本ASCII,请使用in('^',s)而不是contains(s,"^")。如果可以使用其他字符,则可以使用节省更多'^'∈s,但请注意,UTF-8 中为3个字节。
  8. 在数组中寻找最小值/最大值?如果您知道至少有两个元素,请不要使用最小值或最大值 -而不要使用minimum(x)maximum(x),使用min(x...)max(x...)来从代码中删除一个字符x。另外,如果您知道的所有元素x都是非负数,请使用minabs(x)maxabs(x)
  9. 在可能的情况下,并且在挑战允许的情况下,使用实际的换行符代替\ n-请注意,这将使您的代码更难阅读,并且可能意味着您需要提供一个“未合并的”版本,以使人们可以真正理解它。
  10. 在正则表达式字符串后放置选项 -如果要在多行模式下使用正则表达式字符串,例如,请勿键入r"(?m)match^ this",键入r"match^ this"m,并保存三个字符。
  11. 使用flipud的反向一维数组 - reverse(x)比长度长一字节,flipud(x)并且将执行相同的操作,因此后者更好。
  12. 尽可能使用数组串联,而不要使用push!,unshift!,append!或prepend!。-对于普通阵列,这可以轻松完成。对于具有数组元素的Any类型的数组,您将需要在添加的数组周围加上大括号(即{[1,2]},不是{1,2})-对于Julia 0.4,则需要Any[[1,2]]
  13. 使用数组索引获取数组或字符串的大小 - end在数组索引中使用时,它会自动转换为数组/字符串的长度。因此,不要k=length(A)使用A[k=end]来保存3个字符。请注意,如果您想立即使用k,这可能没有好处。这在多维情况下也适用- A[k=end,l=end]将获得- 的每个维度的大小,A但是(k,l)=size(A)在这种情况下将缩短一个字节,因此仅当您要立即访问最后一个元素时才使用它。
  14. 使用数组索引获取索引迭代器 -与13相似,您还可以使用来获得与数组长度匹配的迭代器A[k=1:end],在这种情况下,k该迭代器将保留匹配的迭代器1:length(A)。当您想同时使用数组A时,这可能会很有用。
  15. 不要使用collect将字符串转换为char数组 -而不是collect(A)使用use [A...],它会做同样的事情并节省4个字节。
  16. 需要将数字转换为字符串吗?"$(s[i])"dec(s[i])用于表达式或多字符变量,以及"$i"用于单字符变量。
  17. 使用?:替代的&&||有条件的任务 -那是,如果你想只在某些条件下执行任务,你可以通过编写保存一个字节cond?A=B:1,而不是cond&&(A=B),或cond?1:A=B不是cond||(A=B)。请注意1,此处是一个虚拟值。
  18. 使用union代替unique - union(s)将执行与相同的操作unique(s),并在该过程中保存一个字节。如果可以使用非ASCII字符,∪(s)则将执行相同的操作,并且仅花费3个字节,而不是中的5个字节union

2
哦,我多么喜欢Python中的第一个技巧。
seequ 2014年

您可以简单地使用空格分割,split("Hi there")因为pattern参数默认为空格。
Alex A.

@AlexA。-我知道,但这不是小费的要点,无论哪种方式,小费都同样适用。
Glen O

点12已更改为0.5。
Lyndon White

@Oxinabox-我并不感到惊讶,我敢肯定其中一些已经过时了。我认为我最初为0.3编写了大多数技巧。
Glen O

15

重新定义运算符以定义函数

重新定义运算符可以在括号和逗号中节省很多字节。

递归一元运算符

举一个简单的例子,比较斐波那契数列的以下递归实现:

F(n)=n>1?F(n-1)+F(n-2):n # 24 bytes
!n=n>1?!~-n+!(n-2):n     # 20 bytes
!n=n>1?!~-n+!~-~-n:n     # 20 bytes

在线尝试!

重新定义的运算符保留其初始优先级。

请注意,我们不能简单地换出!赞成的~,因为~已经为整数定义,而!只对布尔定义。

二元运算符

即使没有递归,重新定义运算符也比定义二进制函数要短。比较简单除数测试的以下定义。

f(x,y)=x==0?y==0:y%x==0 # 23 bytes
(x,y)->x==0?y==0:y%x==0 # 23 bytes
x->y->x==0?y==0:y%x==0  # 22 bytes
x\y=x==0?y==0:y%x==0    # 20 bytes

在线尝试!

递归二进制运算符

下面说明了如何重新定义二进制运算符以计算Ackermann函数:

A(m,n)=m>0?A(m-1,n<1||A(m,n-1)):n+1    # 35 bytes
^ =(m,n)->m>0?(m-1)^(n<1||m^~-n):n+1   # 36 bytes
| =(m,n)->m>0?m-1|(n<1||m|~-n):n+1     # 34 bytes
m\n=m>0?~-m\(n<1||m\~-n):n+1           # 28 bytes

在线尝试!

注意,这^比使用常规标识符更长,因为其优先级太高。

正如先前所说

m|n=m>0?m-1|(n<1||m|~-n):n+1           # 28 bytes

对于整数参数将不起作用,因为|在这种情况下已经定义了。整数的定义可以

m::Int|n::Int=m>0?m-1|(n<1||m|~-n):n+1 # 38 bytes

但这太长了。但是,如果我们将float作为左参数传递而将整数作为右参数传递,则它确实起作用。


11
  1. 不要轻易被factor(n)所吸引诱人的库函数factor(n)具有致命缺陷:它以无序Dict类型返回整数的因式分解。因此,要从中获取所需的数据,将需要付出昂贵的代价collect(keys())collect(values())并且可能还需要a cat和a sort。在许多情况下,按审判分庭考虑可能更便宜。伤心,但真实。

  2. 使用映射 map是循环的一种很好的选择。请注意和之间的区别,mapmap!在可能的情况下利用后者的就地功能。

  3. 使用mapreduce mapreduce可以进一步扩展map的功能,并且可以节省大量字节。

  4. 匿名功能很棒!..尤其是传递给上述map功能时。

  5. 累积数组函数 cumprodcumsum中,美味cummin和其它类似命名的功能使沿着n维阵列的规定尺寸的累积操作。(或* un *指定数组是否为1-d)

  6. 任何的简称当您要选择多维数组(或Dict)的所有特定维时,例如A[Any,2],可以使用以下命令保存字节A[:,2]

  7. 使用单行符号表示功能function f(x) begin ... end通常,您可以简化为f(x)=(...)

  8. 使用三元运算符对于单表达式If-Then-Else构造,它可以是一个空间节省程序。注意事项:尽管在某些其他语言中可能会出现,但您不能忽略Julia中冒号之后的部分。另外,运算符在Julia中是表达式级的,因此您不能将其用于有条件地执行整个代码块。
    if x<10 then true else false end
    x<10?true:false


3
“使用三元运算符”到底在茱莉亚身上如何?它与拥有它的每种语言有关。
彼得·泰勒

5
拥有它是相关的。许多语言还具有地图,匿名或纯函数,某种形式的任意/全部速记,累积函数等。如果我们将每个提示线程减少为仅该语言绝对独特的功能,则提示内容将很少。
Jonathan Van Matre 2014年

3
天哪,对于初学者来说只有所有功能性的东西,所有东西都返回一个值,所以三元运算将是多余的。如果您必须有特定的示例:Go,Haskell,Scala,Lua,VB,Prolog,PL / SQL ...甚至Python都没有很多版本。在提示线程中提到其三元运算符的近六种语言中,是否有某些原因使您仅选择在我的省级语言中使用呢?
乔纳森·范·马特雷

3
好吧,嘿,至少您是机会均等的策划者。ヘ( ̄ー ̄ヘ)
乔纳森·范·马特雷

1
我可能会建议调整技巧3?mapreduce比mapfoldl或mapfoldr长,并且根据实现的不同,行为可能有所不同。mapfoldl和mapfoldr始终是左和右关联的,因此是更好的选择。这通常也适用于减少(使用foldl或foldr)。
Glen O

9

遍历函数

在其他语言中也可以这样做,但是通常比直接方法更长。但是,Julia重新定义其一元和二进制运算符的能力使其颇具挑战性。

例如,要生成从1到10的自然数的加,减,乘和除表,可以使用

[x|y for x=1:10,y=1:10,| =(+,-,*,÷)]

该重新定义的二进制运算符|+-*÷,然后计算x|y每个操作和xy在所期望的范围。

一元运算符也适用。例如,要计算复数1 + 2i3-4i-5 + 6i-7-8i,它们的负数,它们的复共轭和它们的乘法逆,可以使用

[~x for~=(+,-,conj,inv),x=(1+2im,3-4im,-5+6im,-7-8im)]

其中重新定义了一元运算符~+-conjinv,然后计算~x所有所需复数。

实际比赛中的例子


6
  1. 关键字有时可以立即跟随常量,而无需使用空格或分号。例如:

    n->(for i=1:n n-=1end;n)

    请注意,1和之间没有空格end。这对于end在封闭括号之后发生也是如此)end

  2. 使用÷而不是div()或重载运算符执行整数除法。请注意,÷在UTF-8中值得2个字节。

  3. 使用vec()A[:](对于某些数组A)而不是reshape()尽可能使用。

  4. 当挑战规则允许时,创建函数而不是完整程序。定义一个接受输入的函数比通过从stdin读取来定义变量要短。例如:

    n->(n^2-1)
    n=read(STDIN,Int);n^2-1
  5. 变量可以在函数的参数内递增。例如,以下是对“ 查找下一个1-稀疏二进制数”挑战的答案

    n->(while contains(bin(n+=1),"11")end;n)

    这比n在循环内部递增要短。


6
  1. 不输入return f(x)=x+4等于但短于f(x)=return x+4。Julia始终返回最后一条语句的结果。
  2. 使用=代替in[x for x in 1:4]比3个字符长,但等于[x for x=1:4]

5

使用广播功能调用。

在Julia 0.5中引入。它就像地图,但是使用更少的字符,并且确实在参数上广播行为-这意味着您可以编写更少的lambda来处理事物。

而不是:

  • map(f,x) -8个字符。
  • f.(x) -5个字符

更好的是:

  • map(a->g(a,y),x) -16个字符
  • g.(x,[y]) -9个字符
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.