Tcl'de golf için ipuçları


15

Tcl'de golf yapmak için hangi genel ipuçlarınız var? Ben genel olarak en az biraz Tcl özgü (örneğin "yorumları kaldırmak" bir cevap değildir) kod golf sorunlarına uygulanabilecek fikirler arıyorum. Lütfen cevap başına bir ipucu gönderin.

Yanıtlar:


7

lmapBunun yerine kullanın foreach. Bunun için Tcl 8.6 gerekir.

Sözdizimi aynıdır, ancak lmapher döngünün sonucunu içeren bir liste döndürür.


4

Cevabımda /codegolf//a/107557/29325 Gösterebilirim:

  1. Genellikle set j 0;while \$j<$n;{...;incr j}eşdeğerden daha kısadırfor {set j 0} {$j<$n} {incr j} {...}

  2. Döngü değişkeni 1'de başladığında, artışı gereksiz yere daha whileönce yazmaktan kaçınarak test koşulunun bir parçası olarak yapabiliriz set i 1:while {[incr i]<=$n} {...} yerineset i 1;while \$i<=$n;{...;incr i}

DİKKAT : Bir dış döngü durumunda sadece 2. yapılabilir! jKendi iç döngüsünün dışında 1'e sıfırlanması gerektiğinden değişkenime uygulayamadım ! Ve tanımlamak ve arttırmak için tanımlanmamış bir değişkeni tutmak incr jyerine, iç döngünün son adımında ayarlanan değeri elde ederdi !j01


4

Bazen normal veya döngü yerine yineleme sayısının time {script} nnerede nolduğunu kullanmaya değer . Amacı döngü olmamasına rağmen , elde edilen etki aynıdır.whilefortime

Son zamanlarda bu yönü takip ederek kendi cevaplarımda değişiklikler yaptım.

GÜNCELLEME: Ben sadece kolay bir tuzak düşmeye keşfettim: Bir yerini alamaz forveya whilebir tarafından timebir içeriyorsa, bloğun breakveya continue.


3

Etkileşimli kabuğu kullanın. Bu, kalan harflerle yalnızca 1 komut başladığı sürece komut adlarını kısaltmanıza olanak tanır.

Misal:

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

Ve interaktif çözümler ücretsiz: P

Arkaplan :

Bir tclshterminal ile giriş cihazı olarak çalıştığında, değişkeni tcl_interactiveolarak ayarlar 1. Bu unknown, bu adla başlayan komutları aramaya neden olur (bir komut bulunamazsa çağrılacak varsayılan yordam).

Dezavantajı: Her satırın sonucunu ;basar, yeni satırlar yerine kullanın .
Ohh, ve bu gibi wiyi bir kısaltma olan harici komutları çağırabilir while.


3

Alt komutlar ve seçenekler (genellikle) kısaltılabilir. Bu biraz tasarruf edebilir, ancak her şeyin bu şekilde kısaltılamayacağı için test etmelisiniz ( regsubörneğin seçenekleri olamaz).

Daha sonra namespacebunu gerçekten şeytani şeyler yapmak büyüsü ile kullanabilirsiniz . Bunu düşün:

namespace exp *;namespace en cr -c ?

Bundan sonra ?, şimdi herhangi bir küresel Tcl komutunu kısaltmanıza izin veren büyülü bir komut ve hepsi ile uğraşmanın kötü belirsizliği olmadan unknown.


2

Tcl 8.0.5 kullanıyorum, ancak aşağıdakilerin tüm son sürümler için geçerli olduğuna inanıyorum.

  1. Yeniden renameadlandırmak için kullanın rename:

    rename rename &
    

    &Herhangi bir tanımlayıcı olabilir; &bana C'deki "referansları" hatırlatıyor.

  2. Yeniden adlandırmak renameiçin yeniden adlandırılmış olanı kullanın set:

    & set =
    

    Yine, =herhangi bir tanımlayıcı olabilir; =benim için sadece sezgisel.

  3. Şimdi, yeniden adlandırılmaya değer diğer komutları yeniden adlandırın, ör.

    & regsub R
    & string S
    & while W
    

    Bir komut, uzunluğu n ve k , k (n-1) - (n + 4)> 0 olması durumunda yeniden adlandırılmaya değer . K için çözüldüğünde formül olur k > (n+4)/(n-1). İşte bunu kolaylaştıran bir referans tablosu:

    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. Daha sonra, kompakt sık kullanılan alt komutlar

    = I index
    = L length
    

    böylece böyle şeyler yapabilirsiniz

    S $I $x 7
    S $L $x
    
  5. Bazı açık çeşitli:

    1. lappend henüz mevcut değilse bir listenin ilk öğesini ayarlayabilir (başlatmaya gerek yoktur).
    2. Dizileri array, örneğin kullanmadan ayarlayabilirsiniz. set doesNotExist(7) 43 .
    3. Bunun "a b c"yerine dizeleri ( ) kullanabilirsiniz [list a b c].
    4. Öyle gibi dizeleri interpole edebilir: foo${a}bar.
    5. Bunun two\ wordsyerine kullanabilirsiniz "two words". (Genel olarak boşluk içermeyen bitişik dizeler için çift tırnak işareti atlanabilir!)
    6. Bir ya da iki karakteri kaydetmek için hemen hemen her zaman fors olarak yeniden yazabilirsiniz while, çünkü ayrı bloklar kullanılırken whileaynı anda kontrol edebilir ve artırabilir for.
  6. Daha büyük programlar için, düşündüğüm ancak henüz uygulamadığım bir numara var:

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

    Bu, etkileşimli komut kısaltmalarını taklit eder! Bu 54 karakter maliyeti, ama şimdi kullanabilirsiniz jiçin join, spiçin split, stiçin string, wiçin while, vb.


1
Etkileşimli kısaltmaları taklit etmek istiyorsanız, kullanıninfo script {};set tcl_interactive 1
Johannes Kuhn

Harika, teşekkürler! Seni buraya yatırdım . Bununla birlikte, bu teknikle ilgili olarak unknownrota ile karşılaşmadığım bazı sorunlar vardı : buraya ve buraya bakın .
Andrew Cheong

Soru, Tcl'ye biraz özgü ipuçları istiyor. Üçlü operatör, tüm diller için ipuçlarına dahil edilmiştir .
Peter Taylor

@PeterTaylor - Teşekkürler, bu ipucunu kaldırdım.
Andrew Cheong

2

başka isteğe bağlıdır

O söyledi gibi eğer kılavuz sayfasını , elseüzerinde örtülü olan ifblok yapılarında. Öyleyse ne

if ... {} else {}

olabilir

if ... {} {}

bazı cevaplarımda görebileceğiniz gibi.


1

Belki başka bir cevaba entegre edilmelidir, ama işte gidiyor:

A procyalnızca bir parametreye sahip olduğunda ,

proc p a {DO THINGS}

onun yerine

proc p {a} {DO THINGS}

Aynı durum procters eğik çizgi kullanan iki parametre için de geçerlidir ; olarak yazılabilir

proc p a\ b {DO THINGS}

onun yerine

proc p {a b} {DO THINGS}

Daha fazla sayıda parametre için {}daha kısa kod oluşturun.


1

Bazen setdizeleri yalnızca bir deyimle birleştirmek için iki ifadeyi değiştirmeye değer lappend. Gibi bir inşaat, biri yerine

set s ""

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

tarafından

loop {
    # ...
    append s X
}

appendKomut bir sahip incrbir henüz tanımlı değişken başlatır gibi davranış.

Değil yanlışlıkla özen gösterin appendtarafındanlappend


1

Her öğe arasında sözdizimsel olarak serpiştiren bir işlemle bir liste işliyorsanız, bazen joinöğeleri çapraz işlemek yerine belirli bir işlemi yapmak için kullanabilirsiniz.

On /codegolf//a/127042/29325 bir örnek vardır:

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

O read stdinverir 23 214 52ardından listeyi verecektir bölünmüş {23 214 52}. Sonra [join {23 214 52} +]dizeyi döndürür 23+214+52. Sonunda expr 23+214+52toplama işi


Bu durumda split,.
Johannes Kuhn

@JohannesKuhn: teşekkürler. Bitti.
sergiol

1

Büyük kodları varsa, birden fazla kullanımlarını önlemek mümkündür exprkullanarak namespace pat tcl::mathopbaşında. Düzenli bir Tcl fonksiyonu olarak önek-sözdizimi işlemi sağlar. Örneğin:

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

Resmi mathop doc sayfasına bakın


0

setSonraki satırlarda olan birkaç değişkeniniz olduğunda , aynı efekti elde etmek için lassignbirkaç settalimat yerine bir değişken kullanabilirsiniz .

Örnek olarak kendi cevabım /codegolf//a/105789/29325

Karar vermek için, sadece değişkenlerin ağırlığını koyması gerekir (golf yaparken beklendiği gibi 1 harfli değişkenler varsayarak):

  • <5, setgolfçü

  • = 5 setve lassignaynı bayt sayısını oluştur

  • > 5, lassigngolfçüdür

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.