Tcl打高尔夫球的秘诀


15

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

Answers:



4

在我的答案上 /codegolf//a/107557/29325上,我可以演示:

  1. 通常 set j 0;while \$j<$n;{...;incr j}比同等短for {set j 0} {$j<$n} {incr j} {...}

  2. 当循环变量从1开始时,我们可以将增量作为while测试条件的一部分,避免set i 1不必要地先写:while {[incr i]<=$n} {...}而不是set i 1;while \$i<=$n;{...;incr i}

注意:在外循环的情况下,只能做2个!我无法将其应用于j变量,因为需要在其自己的内部循环外部将其重置为1!并且incr j将获取在内部循环的最后一步设置的值,而不是获取未定义的变量j来假定0并递增为1


4

有时值得在time {script} n哪里使用n迭代次数而不是正常次数whilefor循环次数。虽然time的目的不是循环,但是达到的效果是相同的。

我最近按照这个方向对自己的答案进行了更改。

更新:我刚刚发现了一个容易落入陷阱:你不能取代forwhiletime块,如果它包含一个break或一个continue


3

使用交互式外壳。只要只有1个命令以其余字母开头,就可以缩写命令名称。

例:

  • gets -> ge
  • lassign -> las
  • expr -> exp
  • puts -> pu

交互式解决方案是免费的:P

背景

tclsh使用终端作为输入设备运行时,它将变量设置tcl_interactive1。这将导致unknown(如果找不到命令,则将调用默认过程)搜索以该名称开头的命令。

缺点:它将打印每行的结果,使用;而不是换行符。
哦,它可能会调用外部命令,例如w,这是的很好的缩写while


3

子命令和选项可以(通常)缩写。这样可以节省很多,但是您必须进行测试,因为并非可以用这种方式缩短所有内容(regsub例如,不能使用选项)。

然后,您可以将其与魔术配合使用namespace来做一些真正邪恶的事情。考虑一下:

namespace exp *;namespace en cr -c ?

在那之后,?现在是一个神奇的命令,它使您可以缩写任何全局Tcl命令,并且所有命令都无需弄乱unknown


2

我正在使用Tcl 8.0.5,但我相信以下内容适用于所有最新版本。

  1. 使用rename重命名rename

    rename rename &
    

    &可以是任何标识符; &只是让我想起了C语言中的“引用”。

  2. 使用rename重命名来重命名set

    & set =
    

    同样, =可以是任何标识符;=对我来说只是直觉

  3. 现在,重命名其他值得重命名的命令, 例如

    & regsub R
    & string S
    & while W
    

    如果给定命令的长度n和出现kk(n-1)-(n + 4)> 0,则值得重命名该命令。求解k,公式变为k > (n+4)/(n-1)。这是一个简单的参考表:

    length of       minimum         example(s)
    command         occurrences
    ------------------------------------------------
    2               6               if (consider renaming to "?")
    3               4               for, set (consider renaming to "=")
    4               3               eval, expr, incr (consider renaming to "+"), info, join, proc, puts, scan
    5               3               break, catch, lsort, split, subst, trace, unset, while
    6               3               format, lindex, lrange, regexp, regsub, rename, return, string, switch
    7               2               foreach, lappend, linsert, llength, lsearch, unknown
    .               2               lreplace
    .               2               continue
    .               2               
    
  4. 接下来,压缩常用的子命令,例如

    = I index
    = L length
    

    这样你就可以做

    S $I $x 7
    S $L $x
    
  5. 一些明显的杂项:

    1. lappend 可以设置列表的第一个元素(如果尚不存在)(无需初始化)。
    2. 您可以不使用来设置数组array例如 set doesNotExist(7) 43
    3. 您可以使用字符串("a b c")代替[list a b c]
    4. 您可以在字符串插值像这样:foo${a}bar
    5. 您可以使用two\ words而不是"two words"。(请记住,对于不带空格的连续字符串,可以省略双引号!)
    6. 您几乎总是可以将fors 重写为whiles以保存一个或两个字符,因为a while可以同时检查和递增,而a for使用单独的块。
  6. 对于大型程序,这是我想到但尚未应用的技巧:

    proc unknown {c args} {eval [info commands $c*] $args}
    

    这模拟了交互式命令的缩写!它的成本54个字符,但现在你可以使用jjoinspsplitststringwwhile,等等。


1
如果您想模拟交互式缩写,请使用info script {};set tcl_interactive 1
Johannes Kuhn

太好了,谢谢!我在这里已经把你贷。但是,该技术存在一些我没有在unknown路线上遇到的问题:请参见此处此处
Andrew Cheong

该问题要求提供一些特定于Tcl的技巧。所有语言提示中都包含三元运算符。
彼得·泰勒

@PeterTaylor-谢谢,我已经删除了这个提示。
Andrew Cheong 2014年

2

其他是可选的

就像在manual page上所说的那样,elseif块结构上是隐式的。那是什么

if ... {} else {}

可以变成

if ... {} {}

如您在我的一些答案中所见。


1

也许应该将其集成到另一个答案中,但是它可以解决:

当a proc只有一个参数时,可以写成

proc p a {DO THINGS}

代替

proc p {a} {DO THINGS}

proc使用反斜杠的两个参数也是如此;它可以写成

proc p a\ b {DO THINGS}

代替

proc p {a b} {DO THINGS}

对于更多数量的参数,{}呈现较短的代码。


1

有时值得用set一条lappend语句代替两条语句来连接字符串。在类似的结构上,可以替代

set s ""

loop {
    # ...
    set s $s\X
}

通过

loop {
    # ...
    append s X
}

append命令具有incr类似的行为,它将初始化一个尚未定义的变量。

注意不要误appendlappend


1

如果您要使用一个在语法上交错在每个元素之间的操作来处理列表,则有时您可以让join元素执行特定的操作,而不是遍历它。

/codegolf//a/127042/29325上,有一个示例:

puts \n[expr [join [split [read stdin]] +]]

read stdin给出23 214 52然后拆分将给出列表{23 214 52}之后,[join {23 214 52} +]将返回字符串23+214+52最后expr 23+214+52做总结工作


在这种情况下,您可以省略split
Johannes Kuhn

@JohannesKuhn:谢谢。做完了
sergiol

1

如果您有大量的代码,它是可能避免的多种用途expr使用namespace pat tcl::mathop开头。它提供前缀语法操作作为常规的Tcl功能。例如:

namespace pat tcl::mathop
set sum [+ 1 2 3]
set prod [* {*}{1 2 3 4}]
puts $sum\ $prod

查看官方Mathop文档页面


0

当您set在后续行中包含多个变量时,可以使用一个变量lassign代替多个set指令来达到相同的效果。

一个例子是我自己的答案/codegolf//a/105789/29325

要确定,只需要权衡变量的数量即可(假设1个字母变量,如打高尔夫球时所期望的那样):

  • <5,set是高尔夫球手

  • = 5,setlassign生成相同的字节数

  • > 5,lassign是高尔夫球手

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.