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.
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:
Cevabımda /codegolf//a/107557/29325 Gösterebilirim:
Genellikle set j 0;while \$j<$n;{...;incr j}
eşdeğerden daha kısadırfor {set j 0} {$j<$n} {incr j} {...}
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! j
Kendi 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 j
yerine, iç döngünün son adımında ayarlanan değeri elde ederdi !j
0
1
Bazen normal veya döngü yerine yineleme sayısının time {script} n
nerede n
olduğunu kullanmaya değer . Amacı döngü olmamasına rağmen , elde edilen etki aynıdır.while
for
time
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 for
veya while
bir tarafından time
bir içeriyorsa, bloğun break
veya continue
.
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 tclsh
terminal ile giriş cihazı olarak çalıştığında, değişkeni tcl_interactive
olarak 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 w
iyi bir kısaltma olan harici komutları çağırabilir while
.
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 namespace
bunu 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
.
Tcl 8.0.5 kullanıyorum, ancak aşağıdakilerin tüm son sürümler için geçerli olduğuna inanıyorum.
Yeniden rename
adlandırmak için kullanın rename
:
rename rename &
&
Herhangi bir tanımlayıcı olabilir; &
bana C'deki "referansları" hatırlatıyor.
Yeniden adlandırmak rename
için yeniden adlandırılmış olanı kullanın set
:
& set =
Yine, =
herhangi bir tanımlayıcı olabilir; =
benim için sadece sezgisel.
Ş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
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
Bazı açık çeşitli:
lappend
henüz mevcut değilse bir listenin ilk öğesini ayarlayabilir (başlatmaya gerek yoktur).array
, örneğin kullanmadan ayarlayabilirsiniz. set doesNotExist(7) 43
."a b c"
yerine dizeleri ( ) kullanabilirsiniz [list a b c]
.foo${a}bar
.two\ words
yerine kullanabilirsiniz "two words"
. (Genel olarak boşluk içermeyen bitişik dizeler için çift tırnak işareti atlanabilir!)for
s olarak yeniden yazabilirsiniz while
, çünkü ayrı bloklar kullanılırken while
aynı anda kontrol edebilir ve artırabilir for
.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 j
için join
, sp
için split
, st
için string
, w
için while
, vb.
unknown
rota ile karşılaşmadığım bazı sorunlar vardı : buraya ve buraya bakın .
O söyledi gibi eğer kılavuz sayfasını , else
üzerinde örtülü olan if
blok yapılarında. Öyleyse ne
if ... {} else {}
olabilir
if ... {} {}
bazı cevaplarımda görebileceğiniz gibi.
Belki başka bir cevaba entegre edilmelidir, ama işte gidiyor:
A proc
yalnızca bir parametreye sahip olduğunda ,
proc p a {DO THINGS}
onun yerine
proc p {a} {DO THINGS}
Aynı durum proc
ters 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.
Bazen set
dizeleri 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
}
append
Komut bir sahip incr
bir henüz tanımlı değişken başlatır gibi davranış.
Değil yanlışlıkla özen gösterin append
tarafındanlappend
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 stdin
verir 23 214 52
ardı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+52
toplama işi
split
,.
Büyük kodları varsa, birden fazla kullanımlarını önlemek mümkündür expr
kullanarak namespace pat tcl::mathop
başı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
set
Sonraki satırlarda olan birkaç değişkeniniz olduğunda , aynı efekti elde etmek için lassign
birkaç set
talimat 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, set
golfçü
= 5 set
ve lassign
aynı bayt sayısını oluştur
> 5, lassign
golfçüdür
info script {};set tcl_interactive 1