Bu yazının amacı, <all languages>
belirli bir yerine kolayca uygulanabilecek tüm golf ipuçlarını toplamaktır .
Yalnızca mantığının dillerin çoğuna uygulanabileceği cevaplarını yayınlayın .
Lütfen cevap başına bir ipucu
<all languages>
Bu yazının amacı, <all languages>
belirli bir yerine kolayca uygulanabilecek tüm golf ipuçlarını toplamaktır .
Yalnızca mantığının dillerin çoğuna uygulanabileceği cevaplarını yayınlayın .
Lütfen cevap başına bir ipucu
<all languages>
Yanıtlar:
Genellikle iki sonuç döngüsünü veya iki iç içe döngüyü bir arada birleştirebilirsiniz.
Önce:
for (i=0; i<a; i++) foo();
for (i=0; i<b; i++) bar();
Sonra:
for (i=0; i<a+b; i++) i<a?foo():bar();
foo
da, a
zamanlar bar
olarak adlandırılır b
. Bunun nedeni, "after" ifadesinde, döngü a+b
zamanlar, ilk a
çağrı foo
, sonraki çağrıdır bar
.
for(y=0;y<Y;++y)for(x=0;x<X;++x)
genellikle for(i=0;i<X*Y;++i)
ile x
değiştirilir i%X
ve y
değiştirilir i/X
.
Sadece açıkça söylemek gerekirse:
Golf oynarken (özellikle daha uzun programlara neden olan daha zor problemler), çoğu zaman diğer temel seçenekleri denemeden ilk seçtiğiniz yola sadık kalabilirsiniz . Tabii ki, bir seferde veya genel fikrin bir parçası olarak bir veya birkaç çizgiyi mikro-golf yapabilirsiniz, ancak genellikle tamamen farklı bir çözüm denemezsiniz.
Bu özellikle Hits 495'te (Kaprekar) fark edildi; burada gerçek algoritmadan sapma ve aynı sonuca ulaşmak için uygulayabileceğiniz kalıpları arama birçok dilde daha kısaydı (sadece J değil).
Dezavantajı, muhtemelen aynı şeyi yarım düzine kez çözmenizdir. Ancak HQ9 + hariç gerçekten tüm dillerde çalışır ( Hello World'ü çıkarmanın başka bir yolunu bulmak biraz boşuna olacaktır).
Kodun çeşitli girişleri işlemesi gerekiyorsa, kapsamlı testler yazın ve hepsini çok hızlı bir şekilde çalıştırmayı kolaylaştırın. Bu, bir seferde bir bebek basamağı riskli dönüşümleri denemenizi sağlar. Golf daha sonra sapık niyeti ile refactoring gibi olur.
Örneğin, eğer A
ve B
boolean ve bir ölçüde numaraları gibi dil davranır mantıksal ifadenin vardır A and (not B)
ve A>B
eşdeğerdir. Örneğin Python'da
if A and not B:
foo()
aynıdır:
if A>B:
foo()
B>A or foo()
Bunu ifade etmek için daha kısa bir yol olurdu, yalnızca gerektiğinde hesaplamaları sağlamak için boolean ifadelerinin tembel değerlendirmesinden yararlanın.
B>A or foo
değerlendirmek istiyorum foo
eğer B==A
biz istemiyor budur. (Sağ?)
Bunun yerine, x=1
zaten 1'e eşit bir şey aramaya çalışın.
Örneğin, bir işlevin dönüş değeri: printf("..");x=0;
-> x=!printf("..");
. 0 ile en kolay olanıdır, çünkü her zaman ihmal edebilirsiniz veya ihtiyacınız olan tek şey doğru gerçek değer olduğunda (ve 1 ya da 19 olması önemli değil).
~
için x+1
vex-1
Bu numara, bir bit bitsel olumsuzlama işleci ~
ve bir düzenli düzenli olumsuzlama işleci olan diller için geçerlidir -
.
Programınız, şans eseri, ifadeyi içeriyorsa, baytları kaydetmek için -x-1
onunla değiştirebilirsiniz ~x
. Bu çok sık gerçekleşmez, ancak -
her iki ifadeyi de negatif edersek ( ) x+1
eşittir -~x
! Benzer şekilde, x-1
eşittir ~-x
. (Tilde hangi yöne işaret ettiğini düşünün: sağ +
, sol -
.)
Bu yararlıdır, çünkü tüm dillerde bu operatörlere sahip olduğunu düşünebiliyorum, çoğu operatörden daha yüksek önceliğe sahipler. Bu parantez içinde kaydetmenize olanak sağlar. Burada dört baytı nasıl kurtardığımızı izleyin:
(x+1)*(y-1) ==> -~x*~-y
Dilinizde boşluk için kuralları bilin. Bazı noktalama işaretlerinin veya diğer karakterlerin etrafındaki beyaz alanlara ihtiyacı olmayabilir. Bu Bourne kabuğu işlevini düşünün :
f () { echo a; echo b; }
Bourne kabuğunda ();
meta karakterlerdir ve çevreleyen boşluklara ihtiyaç duymazlar. Ancak, {}
kelimeler ve meta karakterlerin yanında olmadıkça boşluk gerekir. Yanında 4 boşluk bırakabiliriz ();
, ancak {
ve arasında boşluk bırakmalıyız echo
.
f(){ echo a;echo b;}
In Common Lisp ve PicoLisp , ()
meta karakter olan. İki sayının ortalamasını bulmak için bu kodu göz önünde bulundurun:
(/ (+ a b) 2)
2 alanda golf oynayabiliriz.
(/(+ a b)2)
Bazı dillerin boşluk için tuhaf ve ince kuralları vardır. Bir tamsayı çizgisinin toplamını ve ürününü yazdıran bu Ruby programını düşünün.
#!ruby -an
i=$F.map &:to_i
puts"#{i.reduce &:+} #{i.reduce &:*}"
Her birinin &
kendinden önce bir alana ihtiyacı var. Ruby, i=$F.map &:to_i
anlamına gelir i=$F.map(&:to_i)
burada &
bir blok parametresi geçirir. Ancak, bir ikili işlecin nerede olduğu i=$F.map&:to_i
anlamına gelir .i=$F.map.&(:to_i)
&
Bu tuhaflık, belirsiz noktalama işaretleri kullanan Perl veya Ruby gibi dillerde olur. Şüpheniz varsa, boşluk kurallarını test etmek için bir REPL kullanın veya kısa programlar yazın.
x = SomeLongFunctionName
x(somedata)
x(somemoredata)
etc
x
.
52 tane var; hepsini kullan! Farklı yaklaşımları denemek ve uzunlukları karşılaştırmaktan korkmayın. Dili ve mevcut özel kısayolları / kütüphane işlevlerini öğrenin.
$
ve _
tanımlayıcı olarak kullanılabilir.
@
T-SQL'de geçerli bir değişken adı, yerine kullanın @a
.
Koşullu bir operatör
bool ? condition_true : condition_false
IF ifadesinden daha faydalı, karakter açısından akıllıca .
if(a>b){r=a;}else{r=b;}
olarak yazılabilir
r=a>b?a:b;
a&&b||c
Bunun yerine üçlü olmayan dilleri kullanabilirsiniz . Biraz daha uzun, ama yine de bir daha kısa if
.
Iff
bir işlevi olmasına rağmen, tüm argümanların değerlendirmesine tabi.
if(a ? b : c)
a&&b||c
geri dönebilecek olan not iff yanlıştır, küçük bir dava, ama bunu unutmamalıyız ^^c
a
b
Bir açıklama yazmak, kodunuzun her bir bölümüne tekrar dikkatlice bakmanızı ve belirli bir bölümün yazılmasında düşüncelerinizi ve seçimlerinizi açıkça belirtmenizi sağlar. Bunu yaparken, bazı baytları kurtarabilecek farklı yaklaşımların mümkün olduğunu veya bilinçli bir şekilde zorunlu olmayan varsayımlar yaptığınızı fark edebilirsiniz.
Bu ipucu, algoritma seçiminizi sorgulayın ve tamamen yeni bir şeyler deneyin ; Ancak, aslında her bir parçanın nasıl çalışması gerektiğini yazmanın adımının bazen alternatiflerin farkında olmak için çok önemli olduğunu buldum.
Bir bonus olarak, bir açıklama içeren cevaplar diğer kullanıcılar için daha ilgi çekicidir ve bu nedenle daha fazla puan kazanılması daha olasıdır.
Beyinsiz gibi geliyor, ancak dikkatli olunca, aslında hiçbir şey yapmadan birkaç karakteri "kaydedebilirsiniz"!
Windows kullanıyorsanız \r\n
, tam yerine \r
veya \n
Return tuşuna basıldığında giriyor olabilirsiniz - her satıra fazladan bir bayt ekleyerek! Kontrol karakterlerini sadece bunu yapmadığınızı kontrol etmek için çevirin.
Not Defteri'nde ++ tüm dönüştürebilirsiniz \r\n
sadece satır sonları için \r
giderek Edit > EOL Conversion > UNIX/OSX Format
.
Ayrıca, karakter sayınıza takip eden boşluk bırakmadığınızdan emin olun! Kodunuzdaki alt satırdaki satır besleme de önemsizdir, bu nedenle sayılmaları da gerekmez.
Kod golf (sorulur ve ne değildir sorusunu anlamak hakkında kadar değil sadece sorulan ne tatmin (olabilir) bu kodu üreten olarak başka herhangi bir ortamda zımni görünecek olsa da, sorulan).
Açıkça istenenin dışındaki herhangi bir girişin ele alınması gerekmez. Bazı test durumları varsa ve genel gereklilik yoksa, kodunuz yalnızca bu durumlarda işe yarayabilir. Vb.
Biraz kenar davası olabilir, ama bazen işe yarayabilir. M = 2 n -1 'in uygulandığı tüm sayıların , 1 olarak ayarlanmış en sağdaki bit değerlerine sahip olduğuna dayanır .
Öyleyse, 7 10 == 00000111 2 , 15 10 == 00001111 2 , 31 10 == 00011111 2 vb.
İşin püf noktası x&~m
. Bu her ne zaman doğrudur dönecektir x
olduğunu değil 0 ile arasında m
(dahil) ve yanlış aksi. Bir sonraki en kısa eşdeğer ifadeden 6 bayt kaydeder: x>=0&&x<=m
ancak açıkçası yalnızca m
2 n -1 değerini karşıladığında çalışır .
Yeni değişkenler yerine işlev parametrelerini yeniden kullanın
main(i){...
şimdi sizinle birlikte 1 değeri olmayan bir değişken var Herhangi bir ödevi yap. Orada 2 karakter kaydedildi ..
Rakam kaydetmekten büyük / küçük:
//use:
if(n>9){A}else{B}
//instead of:
if(n<10){B}else{A}
Sadece kod takas hatırlamak if
için else
ve onlar tam olarak aynı şeyi (veya eşitsizlik taraf değiştirmeye) olacak!
Not: Bu, herhangi bir 10'luk güç ve negatifleri ile uygulanabilir:...-100, -10, 10, 100...
if(n>99999)
vsif(n<1e5)
Kodlanmış tamsayı değerlerine karşı kontrol ederken, >
ve <
yerine >=
ve <=
mümkün olan yerlerde kullanın . Örneğin,
if(x>24&&x<51)
Kullanmadan 2 bayt daha kısa
if(x>=25&&x<=50)
<1
yerine ==0
sıfır çek olarak (veya >0
yerine !=0
yansıtılmış kontrolü için).
x
Tam sayı olma konusunda bir not eklememeli misiniz ?
Bir boolean kontrolün 1 veya daha fazla örneğini kontrol etmek için bir döngüden geçiyorsanız, ilk gerçek değerden döngüden çıkmak daha verimli bir program yapabilir. Bununla birlikte, arayı kaldırmak ve tüm yinelemeler boyunca döngü daha kısa kodlara izin verir.
int main() {
bool m = false;
int n = 1000;
for (int i = 0; i < n; i++) {
if (i >= 100) {
m = true;
break; // remove this line
}
}
return 0;
}
if
bu durumlarda uzak deyimi: m|=i>=100
. (Ve ayrıca kolaylaştırabilirsiniz i>=100
için i>99
bu durumda ama bu burada çok alakalı değil)
-
yerine kullanmak!=
sayısal karşılaştırmalar için:
Bir b eşitse, a-b
sonuçlanan 0
falsy olan. 0
Gerçeğinden başka bir şey var ; öyleyse,
eğer bir boole bağlamında kullanılıyorsa, a-b
<=>a!=b
if/else
Üçlü operatörle veya bu operatörle birlikte kullanırsanız , bu eşitlik için size bir bayt kazandırabilir:
a==b?c:d
<=>a-b?d:c
Çoğu dilde, bir dizgiyi, bir tür jetonun etrafındaki dizgilerin dizisine bölme yöntemi vardır. Uzunluk kaçınılmaz bir dil eşiğine ulaştığında bu kaçınılmaz olarak bir dizi değişmezden daha kısa olacaktır, çünkü dize başına ek yük, (en azından) iki dize sınırlayıcıdan ziyade bir tek char token'in bir kopyası olacaktır.
Örneğin, GolfScript'te
["Foo""Bar""Baz""Quux"] # 23 chars
olur
"Foo
Bar
Baz
Quux"n/ # 20 chars
Bazı diller için eşik bir dize kadar düşüktür. Örneğin, Java’da
new String[]{"Foo"} // 19 chars
olur
"Foo".split("~") // 16 chars
%w{Foo Bar Baz Quux}
.
qw(Foo Bar Baz Quux)
bir şey sağlar: dizelerin bir listesi haline gelir.
Eğlenceli olmanın yanı sıra, başkalarının kodunu incelerseniz, bazen düşünmediğiniz iyi bir algoritma veya gözden kaçırdığınız bir numara (bazen açık bir kod) keşfedebilirsiniz.
Bazen başka bir dile çevirebileceğiniz ve diğer dilin özelliklerinden yararlanabileceğiniz bir cevap vardır.
Birkaç ifadeyi ne zaman birleştirirseniz, parantezleri kaydetmek için işleri yeniden düzenleyip düzenleyemeyeceğinizi görmek için operatör öncelik tablosunu kontrol edin.
Örnekler:
(a&b)&&c
parantez gerektirmez: a&b&&c
aynen (a*b)+c
değil.a+(b<<c)
olarak yeniden yazılabilir a+b*2**c
. c
küçük bir tamsayı değişmez ise olacaktır (<14).a<b&&c<d
ile a<b&c<d
(kısa devre değerlendirme gerekmedikçe)Eğer varsa X
ifadeleri {
içine }
sizin için-döngü, hareket edebilir X-1
ifadeleri (
içindeki )
ikinci noktalı virgül sonrası için-döngü for(blah;blah;HERE)
3 bayt kaydedin. (ifadeleri virgül kullanarak ayırın ,
)
Onun yerine
for(int i=0;i<9;){s+=s.length();println(i++);}
ifadelerden birini diğerinin dışına çıkarken for-loop'un (
parantezlerine taşıyabilirsiniz)
for(int i=0;i<9;println(i++))s+=s.length();
ve 3 bayttan tasarruf edin (@ETHProductions sayesinde 1 bayt daha tasarruf edildi)
Basitçe söylemek gerekirse,
onun yerine
for(blah;blah;){blah 1;blah 2;...;blah X}
ifadeleri hareket ettirin, böylece bununla bitin
for(blah;blah;blah 2,...,blah X)blah 1;
ve 3 bayt tasarruf edin
for
son söz ise, ;
isteğe bağlı olur
~
için a-b-1
vea+b+1
Ek olarak @Lynn ilgili 'ın önerileri x+1
→ -~x
; ve x-1
→~-x
, ayrıca golf a-b-1
ve a+b+1
.
a-b-1 // 5 bytes
a+~b // 4 bytes
a+b+1 // 5 bytes
a-~b // 4 bytes
Sık sık kullanmayacağınız bir ipucu gibi görünebilir, ~x
bunun yerine kullanmak yerine -x-1
sık sık olmaz, ama burada yararlı bir ipucu olarak görmek için yeterince zaman kullandım. Özellikle dizi indeksleme ile bazı durumlarda yukarıdakileri kullanabilirsiniz.
Basit bir numara, ands (veya ors, 'bu durumda sadece' all 'yerine' any 'ifadesini kullanırsanız) ile zincirlenmiş uzun bir koşul dizisini sıkmaya çalışırken ortaya çıktım.
Örneğin:
if a>0 and a<10 and a+b==4 and a+3<1:
Oluyor
if all([a>0,a<10,a+b==4,a+3<1]):
all(array-of-Booleans)
?
[a>0,a<10,a+b==4,a+3<1].all?
if 10>a>0 and a+b==4>1>a+3:
Hangi optimizasyonların derleyici tarafından ve hangi optimizasyon seviyelerinde garanti edildiğinden emin olun ve bunları liberal bir şekilde kullanın. Performans kaygılı bir gereksinim olmasa bile , optimizasyonları hala test edebilir ve ardından bir karakter iskonto edebilirsiniz çünkü kodunuz derleyici bayrağı olmadan teknik olarak hala geçerlidir.
2 ^ n'yi hesaplamak için aşağıdaki Haskell işlevini göz önünde bulundurun (Haskell'in zaten yerleşik bir üstel çalıştırma operatörü olduğu gerçeğini göz ardı ederek) (23 karakter):
p 0=1;p x=p(x-1)+p(x-1)
Sorun şu ki - korkunç derecede yavaş, üstel bir zamanda çalışıyor. Bu, kodunuzu test edilemez hale getirebilir veya soru tarafından verilen performans kısıtlamalarını kaldıramaz. Tekrarlanan işlev çağrılarını engellemek için geçici bir değişkeni veya hemen çağrılan bir işlevi kullanmak için cazip olabilirsiniz (25 karakter):
p 0=1;p x=(\y->y+y)$p$x-1
Ancak derleyici bunu sizin için zaten yapabilir, -O
derleyici bayrağı olarak ayarlamanız yeterlidir ! Yaygın olarak kullanılan alt ifadeleri elimine etmek için site başına birkaç fazladan fazla karakter harcamak yerine, derleyiciye tüm program boyunca toplamda bir veya iki karakter toplamı için temel optimizasyonlar yapmasını söyleyin.
p(x-1)*2
mıydı?
Belki biraz açık ama ...
Atama operatörünün bir değer döndürdüğünü unutmayın!
Örneğin, x'e y eklemek ve ardından x'in bir şeyden büyük olup olmadığını kontrol etmek istiyorsanız, yapabilirsiniz
if(25<x+=y)
onun yerine
x+=y;if(x>25)
Ya da kırptıktan sonra dizenin uzunluğunu bulmak istersiniz:
strlen(s=trim(s))
Ziyade
s=trim(s);strlen(s)
a = (b=c)+1;
ayarlar b
için c
ayarlar, sonra ve a
için b+1
.
a=1+b=c
. Ve listenize PHP ve JavaScript ekleyebilirsiniz.
=
Operatöre soldan sağa göre daha yüksek bir öncelik verir , bu yüzden 1+x=2
geçerlidir ve değerlendirir3
Bu özellikle polyglotlar için kullanışlıdır , ancak diğer zorluklara da uygulanabilir. Bazen, bir derleyici hatası bayttan atılabilir, bir uygulama hatası birkaç karakter kaydetmenize izin verebilir veya gerçekten kanama sağlayan bir özellik puanınızı artırabilir.
Mümkünse ve / veya kullanarak kontrol ediyorsanız çoklu / iç içe birleştirin.
yani:
if (a && (b || c)) {
}
onun yerine:
if (a) {
if (b) {
//Do Stuff
} elseif (c) {
//Do same stuff
}
}
&
daha fazla karakter silmek için bitty koşullarını kullanın ( , `|).
&
yönünde kullanmak yerine &&
1 karakteri kaldırsa da bazı durumlarda operatör önceliğini bozar ve çalışması için parantez koymak zorunda kalırsınız. Akıllıca kullanın.
Diğer bazı cevaplar da bunu söylemekten çok yaklaştı, ancak birçok (kesinlikle yazılan?) Dilde, şu x
şekilde boş dize olarak başlatılması daha kısa :
x:=""
veya x
boş rune (char) gibi:
x:=''
göre
var x string
ve
var x rune
Önceden varolan değerleri kullanmak açıkça tercih edilir, ancak bu kadar kolay değildir.