Советы по игре в гольф в Tcl


15

Какие общие советы у вас есть для игры в гольф в Tcl? Я ищу идеи, которые могут быть применены к кодовым проблемам гольфа в целом, которые, по крайней мере, несколько специфичны для Tcl (например, «удалить комментарии» - это не ответ). Пожалуйста, оставьте один совет за ответ.

Ответы:


7

Используйте lmapвместо этого foreach. Это требует Tcl 8.6.

Синтаксис тот же, но lmapвозвращает список с результатом каждого цикла.


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число итераций вместо нормалей whileили forциклов. Хотя timeцель не в цикле, достигнутый эффект тот же.

Я недавно внес изменения в свои ответы, следуя этому направлению.

UPDATE: Я только что обнаружил , легко упасть ловушку: Вы не можете заменить forили whileна timeблок, если он содержит breakили continue.


3

Используйте интерактивную оболочку. Это позволяет сокращать названия команд, если только 1 команда начинается с оставшихся букв.

Пример:

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

А интерактивные решения бесплатны: P

Фон :

Когда tclshработает с терминалом в качестве устройства ввода, он устанавливает переменную tcl_interactiveв 1. Это вызывает 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 и вхождения k , k (n-1) - (n + 4)> 0 . Решая для к , формула становится 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. Вы можете использовать strings ( "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 символов, но теперь вы можете использовать jдля join, spдля split, stдля string, wдля while, и так далее.


1
Если вы хотите эмулировать интерактивные сокращения, используйтеinfo script {};set tcl_interactive 1
Johannes Kuhn

Хорошо, спасибо! Я зачислена вас здесь . Однако с этой техникой были некоторые проблемы, с которыми я не сталкивался на unknownмаршруте: смотрите здесь и здесь .
Эндрю Чонг

Вопрос требует советов, которые являются специфическими для Tcl. Тернарный оператор включен в советы для всех языков .
Питер Тейлор

@PeterTaylor - Спасибо, я удалил этот совет.
Эндрю Чонг

2

еще не является обязательным

Как сказано на странице справочника , elseподразумевается в ifблочных конструкциях. Так что же

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похожее поведение, которое инициализирует еще не определенную переменную.

Позаботьтесь , чтобы не ошибка appendпоlappend


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.
Йоханнес Кун

@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

Чтобы принять решение, нужно просто взвесить количество переменных (при условии, что переменные состоят из одной буквы, как это и ожидается при игре в гольф):

  • <5, setигрок в гольф

  • = 5, setи lassignсгенерировать тот же счетчик байтов

  • > 5, lassignэто игрок в гольф

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.