Tclでのゴルフのヒント


15

Tclでゴルフをするための一般的なヒントは何ですか?私は、少なくともゴルフの問題をコード化するのに適用できる、Tclに少なくともある程度固有のアイデアを探しています(たとえば、「コメントを削除する」は答えではありません)。回答ごとに1つのヒントを投稿してください。

回答:



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場所を使用する価値があります。が、目的がループしていないの、得られる効果は同じです。nwhilefortime

この指示に従って、最近自分の回答に変更を加えました。

UPDATE:私はちょうど落ちやすい落とし穴を発見した:あなたは置き換えることができないforwhileによってtime、それが含まれている場合は、ブロックbreakまたはcontinue


3

対話型シェルを使用します。これにより、残りの文字で始まるコマンドが1つだけである限り、コマンド名を短縮できます。

例:

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

インタラクティブなソリューションは無料です:P

背景

ときにtclsh入力装置としての端末で実行され、それは、変数を設定tcl_interactiveします1。これにより、unknown(コマンドが見つからない場合に呼び出されるデフォルトの手順)その名前で始まるコマンドを検索します。

欠点:すべての行の結果を印刷し、;改行の代わりに使用します。
ああ、それはのような外部コマンドを呼び出すかもしれません。wこれはの略語ですwhile


3

サブコマンドとオプションは(通常)省略できます。これはかなり節約できますが、すべてをこのように短縮できるわけではないのでテストする必要があります(regsubたとえば、 'sオプションはできません)。

その後、これを魔法で使用して、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で、オカレンスがkである場合、k(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"代わりにstring()を使用できます[list a b c]
    4. 次のように文字列を補間できますfoo${a}bar
    5. two\ wordsではなくを使用できます"two words"。(一般に、スペースのない連続した文字列の場合、二重引用符は省略できることに注意してください!)
    6. を個別にブロックを使用している間にチェックとインクリメントを同時に行うことができるため、ほとんどの場合forwhilesをsとして書き換えて1つまたは2つの文字を保存whileできforます。
  6. 大規模なプログラムの場合、私が考えていたがまだ適用されていないトリックがあります:

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

    これは、対話型コマンドの省略形をエミュレートします!54文字ですが、今ではjfor joinspfor splitstfor stringwfor while、などを使用できます。


1
あなたはインタラクティブな略語をエミュレートしたい場合は、使用info script {};set tcl_interactive 1
ヨハネス・クーン

クール、ありがとう!ここであなたを信用しました。ただし、この手法にはいくつかの問題があり、unknownルートには遭遇しませんでした:こちらこちらをご覧ください。
アンドリューチョン14

質問では、Tclにある程度固有のヒントを求めています。三項演算子は、すべての言語のヒントに含まれています
ピーターテイラー14年

@PeterTaylor-ありがとう、私はそのヒントを削除しました。
アンドリューチョン14年

2

その他はオプションです

マニュアルページで述べられているようにelseifブロック構造では暗黙的です。だから何ですか

if ... {} else {}

になることができる

if ... {} {}

あなたが私の答えのいくつかを見ることができるように。


1

別の答えに統合する必要があるかもしれませんが、ここにそれがあります:

procパラメータが1つしかない場合、次のように記述できます。

proc p a {DO THINGS}

の代わりに

proc p {a} {DO THINGS}

procバックスラッシュを使用する2つのパラメーターにも同じことが当てはまります。次のように書くことができます

proc p a\ b {DO THINGS}

の代わりに

proc p {a b} {DO THINGS}

パラメータの数が多い{}ほど、コードは短くなります。


1

場合によっては、2つのsetステートメントを置き換えて、1つのlappendステートメントのみでストリングを連結することもできます。のような構造では、1つを置き換えることができます

set s ""

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

沿って

loop {
    # ...
    append s X
}

appendコマンドがありincr、まだ定義されていない変数を初期化するような挙動を、。

ない間違いに注意してくださいappendことにより、lappend


1

構文的に各要素間でインターリーブしている操作でリストを処理している場合joinは、要素を走査する代わりに、特定の操作を実行できる要素がある場合があります。

/codegolf//a/127042/29325例があります:

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

それread stdinが与えると23 214 52、splitはリストを与えます{23 214 52}後に、[join {23 214 52} +]文字列を返します23+214+52最後expr 23+214+52に合計の仕事をします


この場合、を省略できますsplit
ヨハネ

@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命令の代わりに1つの変数を使用して同じ効果を得ることができます。

1つの例は私自身の答えです/codegolf//a/105789/29325

決定するには、変数の数に重みを付けるだけです(ゴルフで予想されるように、1文字の変数を想定しています)。

  • <5、setゴルファーです

  • = 5、同じバイトカウントsetlassign生成

  • > 5、lassignゴルファーです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.