CJam'de golf oynamak için ipuçları


43

CJam , PPCG kullanıcısı aditsu tarafından oluşturulan GolfScript'ten ilham alan bir yığın tabanlı golf dilidir .

Bu nedenle, dile özgü diğer ipuçlarıyla ilgili sorular konusunda:

CJam'da golf oynamak için hangi genel ipuçlarınız var? Lütfen cevap başına bir ipucu gönderin .


4
Ayrıca bkz . GolfScript'te golf oynamak için ipuçları ; diller, birçok hilenin her iki şekilde de adapte edilebileceği kadar benzer.
Ilmari Karonen

2
@IlmariKaronen Bu sorunun cevaplarını okuduktan sonra, dillerin sözdizimsel veya mantıksal farklılıkları nedeniyle bunların sadece yarısının CJam'a başvurduğunu söyleyebilirim.
Doktor,

Yanıtlar:


23

Negatif sayılar için doğru modülo

Modulo işleminin sonucunun ilk işlenen ile aynı işareti vermesi sık sık can sıkıcıdır. Örneğin yerine -5 3%verir . İkincisi istememenizden daha sık. Saf düzeltme, modulo uygulamak, bölücüyü bir kez eklemek ve tekrar modulo uygulamaktır:-21

3%3+3%

Ama bu uzun ve çirkin. Bunun yerine, dizi indeksleme daima modüler olup gerçeğini kullanabilirsiniz yapar negatif endeksleri ile düzgün çalışması. Böylelikle böleni bir menzile dönüştürüyor ve şu noktalara erişiyoruz:

3,=

Uygulandığında -5, bu 1beklendiği gibi verir . Ve bu yerleşikten daha uzun sadece bir bayt %!

Modül 2'nin gücü ise, bitsel aritmetik kullanarak başka bir bayttan tasarruf edebilirsiniz (ki bu çok daha hızlıdır). Karşılaştırmak:

32,=
31&

65536 == 2^16Başka bir baytın özel durumu için karakter tipinin sarma davranışından yararlanılarak tasarruf edilebilir:

ci

13

Birleştirilmiş karakter aralıklarını iterek

  • Tüm basamakları içeren dize "0123456789"olarak yazılabilir.

    A,s
    
  • Büyük harf ASCII harfleri ( A-Z) olarak itilebilir

    '[,65>
    

    Z'ye kadar tüm karakterlerin dizgisini oluşturur , sonra ilk 65'i (en fazla @ ) atar .

  • Tüm ASCII harfleri ( A-Za-z) olarak basılabilir

    '[,65>_el+
    

    Yukarıdaki gibi çalışır, sonra bir kopya oluşturur, küçük harfe dönüştürülür ve eklenir.

    Ama bunu yapmanın daha kısa bir yolu var!

    Ardından, genellikle gözden kaçan ^operatör (listeler için simetrik farklar), üç baytı kaydederken aynı aralıkları oluşturmaya izin verir:

    '[,_el^
    

    '[,kadar tüm ASCII karakter aralığını oluşturur Z , _elbir küçük harf kopyasını oluşturur ve ^biri ancak ikisini görünür hem dizeleri sadece karakterleri tutar.

    İlk dizgideki tüm harfler büyük harf olduğundan, ikincisinde tümü küçük harfli ve tüm harf dışı karakterler her iki dizgededir, sonuçta harf dizesi olur.

  • RFC 1642 Base64 alfabesi ( A-Za-z0-9+/), yukarıdaki teknik kullanılarak ve harf olmayan harflerin eklenmesiyle basılabilir:

    '[,_el^A,s+"+/"+
    

    Bu ipi itmenin eşit derecede kısa bir yolu sadece simetrik farklılıklardan yararlanır:

    "+,/0:[a{A0":,:^
    

    İpi başlangıçta nasıl bulabiliriz?

    Bütün kullanılan karakter aralıkları ( A-Z, a-z, 0-9, +, /) boş bayt, yani başlamak aralığına simetrik farkı olarak itilebilir 'A,'[,^, 'a,'{,^, '0,':,^, '+,',,^ve '/,'0,^.

    Bu nedenle, yürütme :,:^üzerinde "A[a{):+,/0"ancak doğru sırada, istenen karakterler itecektir.

    Doğru sırayı nasıl buluruz? Kurtarma için kaba kuvvet! Program

    '[,_el^A,s+"+/"+:T;"0:A[a{+,/0"e!{:,:^T=}=
    

    dizenin tüm olası permütasyonları üzerinde yinelenir :,:^, sonucu istenen çıktıya uygular ve karşılaştırır ( permalink ).

  • Kullanılan crypt ( .-9A-Za-z) tarafından kullanılan radix-64 alfabesi , yukarıdaki yöntem kullanılarak oluşturulabilir:

    ".:A[a{":,:^
    

    Bu bildiğim en kısa yöntem.

    İstenilen çıktıdaki tüm karakterler ASCII sırasına göre olduğundan, permütasyonları tekrarlamak gerekmez

  • Tüm birleştirilmiş karakter aralıkları kullanılarak istenen sırada basılamaz :,:^.

    Örneğin, aralık herhangi bir permütasyon için 0-9A-Za-z;-?çalıştırılarak :,:^itilemez "0:A[a{;@".

    Bununla birlikte, kodu kullanarak istenen dizgenin döndürülmüş bir varyasyonunu bulabiliriz.

    A,'[,_el^'@,59>]s2*:T;"0:A[a{;@"e!{:,:^T\#:I)}=Ip
    

    aşağıdakileri yazdıracak ( kalıcı ):

    10
    0:@[a{A;
    

    Bu şu demek

    "0:@[a{A;":,:^Am>
    

    aynı etkiye sahiptir

    A,'[,_el^'@,59>]s
    

    hangi hazır olmadan sadece boş bir yığınla kullanılabilir [.


11

Önlemek {…}{…}?

Yığında bir tamsayı olduğunu varsayalım. Tuhafsa 3 ile çarpmak ve 1 eklemek istersiniz; Aksi takdirde, 2'ye bölmek istersiniz.

Eğer "else" if / else ifadesi şöyle görünür:

_2%{3*)}{2/}?

Ancak, {}{}zaten dört bayt eklediğinden blokları kullanmak genellikle gitmek için bir yol değildir . ?Yığındaki iki öğeden birini seçmek için de kullanılabilir:

_2%1$3*)@2/?

Bu bir bayt daha kısa.


Blok-? ifadesi her zaman no-go ise boş. Örneğin,

{}{2/}?

iki bayttan daha uzun

{2/}|

Eğer yerine

{2/}{}?

ve kontrol ettiğiniz şey negatif olmayan bir tamsayıdır.

g)/

Yeni {}&ve {}|kullanışlıdır, ancak yığını karıştırmazsanız bazen problemlidir.

Yine de durumunda

_{…}{;}?

bunun yerine geçici bir değişken kullanabilirsiniz:

:T{T…}&

1
!)/ve g)/örneklerde daha kısadır.
jimmy23013

11

İfadeleri değiştir

CJam'in anahtar ifadeleri yok. İfadeler de aynı şekilde çalışıyorsa, ancak {{}{}?}{}?zaten 12 byte uzunluğunda iç içe geçmişse ...

Durumu küçük, negatif olmayan bir tamsayıya dönüştürebilirsek, tüm vaka ifadelerini ayrılmış bir dizgede dönüştürebilir ve karşılık gelen sonucu değerlendirebiliriz.

Örneğin, yürütmek istiyorum code0yığının tamsayı ise 0 , code1bu ise 1 ve code2o ise 2 , biz ya kullanımı can

_{({code2}{code1}?}{;code0}?

veya

[{code0}{code1}{code2}]=~

veya

"code0 code1 code2"S/=~

S/dizesi böler ["code0" "code1" "code2"], =karşılık gelen yığın özler ve ~kod değerlendirir.

Anahtar ifadelerini çalışırken görmek için burayı tıklayın .

Son olarak, @ jimmy23013 ve @RetoKoradi tarafından önerildiği gibi, bazı durumlarda anahtarı daha da kısaltabiliriz. Ki code0, code1ve code2sahip uzunlukları L 0 , L 1 ve L 2 , sırasıyla.

Eğer L 0 = L 1 ≥ L 2

"code0code1code2"L/=~

yerine kullanılabilir, burada Lbir L 0 . Sınırlayıcıda bölmek yerine /, dizgiyi burada eşit uzunlukta parçalara böler.

Eğer L 0 ≥ L 1 ≥ L 2 ≥ L 0 - 1 ise

"cccooodddeee012">3%~

yerine kullanılabilir. >dizenin başındaki 0, 1 veya 2 öğeyi kaldırır ve 3%her üç öğeyi (ilkinden başlayarak) ayıklar.


Son örnek için, bunun herhangi bir avantajı var "code0code1code2"5/=~mı? Bana çok daha basit görünüyor ve aynı uzunluktadır.
Reto Koradi

@RetoKoradi Tüm snippet'lerin uzunluğu aynıysa, hiçbir avantajı yoktur. Farklı uzunluk için, yönteminiz modül yönteminden hem daha kısa hem de daha uzun olabilir.
Dennis,

11

Ortak dizi ve karakter değerlerini golf

Her zaman ve daha sonra, örneğin ızgaraları başlatmak için ekin yapan bazı kısa diziler veya dizgiler vardır. Doğal olarak, bunlar 4 veya daha fazla bayta mal olabilir, bu yüzden aynı sonucu verecek dahili değerler üzerinde işlem aramaya değer. Özellikle temel dönüşüm genellikle yararlıdır.

  • [0 1]olarak yazılabilir 2,.
  • [1 0]olarak yazılabilir YYb(örneğin ikili olarak 2).
  • [1 1]olarak yazılabilir ZYb(örneğin ikili olarak 3).
  • Matris [[0 1] [1 0]]olarak yazılabilir 2e!.
  • [LL] şeklinde yazılabilir SS/(tek bir alanı boşluklara ayırarak).
  • "\"\""olarak yazılabilir L`.
  • "{}"olarak yazılabilir {}s.

İkincisi, tüm braket türlerinin başka bir bayttan tasarruf etmesini istediğiniz durumlara genişletilebilir:

  • "[{<()>}]"olarak yazılabilir {<()>}a`.
  • "()<>[]{}"olarak yazılabilir {<()>}a`$.

Özellikle temel dönüşüm hilesi, şimdi ve sonra ortaya çıkan bazı belirsiz vakalar için akılda tutulması yararlı olabilir. Örneğin [3 2], E4b(4 numaralı kaidede 14) olacaktır.

Nadir durumlarda bile, çarpanlara ayırma operatörünü bile mffaydalı bulabilirsiniz . Ör [2 7]olduğunu Emf.

Başka bir örnekle karşılaşırsanız, lütfen bu listeyi genişletmekten çekinmeyin.


10

Yığını temizleme

Tüm yığını temizlemek istiyorsanız, bir diziye sarın ve pop:

];

Çok daha zor olan şey ise, çok fazla hesaplama yaptınız, ancak yalnızca üst yığın öğesini tutmak ve altındaki her şeyi elden çıkarmak istiyorsanız. Saf yaklaşım, üst elemanı bir değişkende saklamak, yığını temizlemek, değişkeni itmek olacaktır. Ancak çok daha kısa bir alternatif var: yığını bir diziye sarın ve son elemanı çıkarın:

]W=

(Geçen gün bana bunu gösteren Optimizer'a teşekkürler.)

Tabi, eğer yığında sadece iki element varsa \;, daha kısadır.


\;yalnızca TOS'un altındaki öğeyi açar. Bunu mu demek istediniz ;;?
CalculatorFeline

1
@CalculatorFeline, cevabın ikinci yarısı TOS hariç her şeyi temizlemektir.
Martin Ender

9

e ve on yetkileri

Diğer pek çok dilde 1e3olduğu 1000gibi CJam yerine de yazabilirsiniz.

Bu tamsayı olmayan bazlar ve hatta tamsayı olmayan üsler için de geçerlidir. Örneğin, 1.23e2iter 123.0 ve 1e.5iter 3,1622776601683795 (karekökünü 10 ).

Hemen açık olmayan şey 1e3, aslında iki belirteç:

  • 11 tamsayısını yığında iter .

  • e31000 ile çarpar .

Bu neden önemli?

  • e<numeric literal>Zaten yığında olan bir şeyi arayabilirsiniz .

    2 3 + e3 e# Pushes 5000.
    
  • e<numeric literal>Bir dizi üzerinde eşleyebilirsiniz .

    5 , :e3  e# Pushes [0 1000 2000 3000 4000].
    

9

Öklid normları

Bir vektörün Öklid normunu hesaplamanın en basit yolu, yani elemanlarının karelerinin toplamının kareköküdür.

2f#:+mq

Ancak, çok daha kısa bir yol var.

mh, Hipotenüs operatörü iki tamsayı açılan bir ve b istiften ve kesmeler (a sqrt 2 + B 2 ) .

Bir vektörümüz varsa x: = [x 1 … x n ], yığında n> 1 , :mh(hipotenüsle azalır) aşağıdakileri elde eder:

  • İlk önce x 1 ve x 2 itilir ve yığında sqrt (x 1 2 + x 2 2 )mh bırakılarak yürütülür .

  • Daha sonra, x 3 itilir ve mhbırakarak yeniden çalıştırılır
    sqrt (sqrt (x 1 2 + x 2 2 ) 2 + x 3 2 ) = sqrt (x 1 2 + x 2 2 + x 3 2 ), yığında.

  • Sonra x n işleme konuldu biz kalacaksın (x sqrt 1 2 + ... x n 2 ) , Öklid normunu x .

Eğer , n = 1 ve X 1 <0 , yukarıdaki kodu hatalı bir sonuç üretecektir. :mhzkoşulsuz çalışır. (Bunu işaret ettiği için @ MartinBüttner'e teşekkürler.)

Bu numarayı ilk defa bu cevapta kullandım .


2
Elbette, bunun programınızın sayısal analizi için çıkarımları var ...
Peter Taylor

8

N tabanından n'den büyük bir sayı listesiyle dönüştürme

CJam bir listeyi bu formüle sahip bir sayıya dönüştürür: A 0 * n l + A 1 * n l-1 + A 2 * n l-2 + A l * n 0 (negatif n). ntaban ve lliste uzunluğu. Bu demektir ki bir ı aralığında olmak zorunda değildir, herhangi bir tamsayı olabilir [0,n).

Bazı örnekler:

  • 0bSon öğeyi çıkarır ve tamsayıya dönüştürür. W=iTamsayı değilse, gibi çalışır ve bir bayt kaydeder. Ancak listedeki diğer her şey tamsayıya da girebilmelidir.
  • 1btoplamı döndürür. :i:+Tamsayı olmasaydı iki bayt gibi çalışır ve kaydeder. Aynı zamanda boş listeler ile çalışır, ancak :+değildir.
  • [i{_1&9 32?_@\m2/}16*;]W%:cBir karakteri, ile geri dönüştürülebilen bir satır sonları ve sekmeler dizisine dönüştürür 2bc. Kodlama işlevi, bir kod golf programında golf oynamak için kolay değildir. Ama genelde buna ihtiyacın olmaz.
  • Bir dizeyi, geri dönüştürülebilen 16 bitlik olmayan Unicode karakterlerine dönüştürmek için aşağıdaki kodu kullanabilirsiniz 2A#b128b:c. (Açıklamalar daha sonra eklenecektir. Veya daha sonra yeni bir versiyon yazarım.)

    128b2A#b         " Convert to base 1024. ";
    W%2/)W%\:+       " Convert to two base 1024 digit groups. ";
    [0X@
    {
      _54+
      @I+_Am>@\-
      _Am<@+ 0@-@1^
    }fI
    ]);)
    @\+[~+]2A#b_2G#<!{2A#b}*
    \W%+:c
    

Benzer yöntem n, farklı değerlerde mod olan herhangi bir tamsayı dizisi ile çalışır n, eğer en önemli basamaktan kurtulmanın bir yolunu bulursanız.


8

Kullanılması $üçlü sanki

Belleği sızdırmakta sakıncayacağınız zaman, yani, daha sonra temizleyeceğiniz yığında kullanılmayan öğeleri bırakmak ];, kopyalama operatörü $üçlü operatör için kullanışlı bir alternatif olabilir ?.

? Seçilecek iki öğeyi zorlamadan önce koşulu hesaplamayı başarırsanız, ancak koşulu gerçekte bu maddelere dayanır ve bunların üstüne koymak çok daha doğal sonuçlara neden olur.

Yığınınız varsa A B C, uygulayabilirsiniz

!$

onun yerine

\@?

kopyasına Beğer Ctruthy ve olduğunu Aaksi.

Eğer Cgerçek bir Boole ise ( 0veya 1),

$

onun yerine

@@?

kopyasına Aeğer Ctruthy ve olduğunu Baksi.


Ön görüşte, bu oldukça açık bir numaradır, ama daha önce hiç düşünmemiştim. Bu cevabı ilk defa kullandım .
Dennis,

7

Yuvalanmış Listeler Haritası

Diyelim ki matris gibi iç içe geçmiş bir listeniz var:

[[0 1 2][3 4 5][6 7 8]]

Veya bir dizi dizgi:

["foo""bar"]

Ve bir bloğu iç içe seviyeye eşlemek istiyorsunuz (yani her bir sayıya veya her karaktere uygulayın). Saf çözüm bir iç içe %:

{{...}%}%

Bununla birlikte, aslında iç bloğu yığının üzerine itebilir ve sonra kullanabilirsiniz f%. f"ek parametreli harita" dır, bu nedenle %ikinci parametre olarak bloğu kullanarak dış listeye eşlenir:

{...}f%

İki bayt kaydeder.

Başka temiz hile böyle bir şey yapmak for (i=0; i<5; ++i) for (j=0; j<5; ++j) {...}DİR

5,_f{f{...}}

Dış f, ikinci menzile ek bir parametre olarak beslenerek birinci menzile eşlenir. Fakat şimdi, ftekrar kullanırsanız , sadece üst yığın elemanı bir dizidir, böylece fdış bloğu "yineleme değişkeni" ek bir parametre olarak sağlayarak iç bloğu eşlersiniz. Bu, iç bloğun istif ile birlikte ive jüzerinde çalıştığı anlamına gelir .

Bu, sadece bir bloğun Kartezyen ürün üzerine eşlenmesiyle aynı sayıda karaktere sahiptir (her ne kadar diziler olarak çiftlere ihtiyacınız olursa kısalır):

5,_m*{~...}%

Aradaki fark, bu sürümün tüm çiftler için tek bir sonuç dizisi oluşturmasıdır; oysa, çiftleyiciler f, sonuçları yineleyici değişkenleri koordinatlar olacak şekilde bir ızgarada saklamak için faydalı olabilecek, iç içe geçmiş bir liste sunar.

Bu numarayı bana gösterdiği için Dennis'e teşekkür ederim.

0.6.4 Güncellemesi

fve :şimdi kendileri de dahil olmak üzere başka bir operatörü alarak son derece geliştirildi. Bu, şimdi daha da fazla bayt kaydedebileceğiniz anlamına gelir. Bir işlecin yuvalanmış bir listeyle eşlenmesi şimdi daha da kısaldı:

{:x}%
{x}f%
::x

Bu gerçekten de iç içe listelerde blokları eşleme ile yardımcı olmuyor.

Kartezyen ürüne uygulama blokları veya operatörleri gelince, bu işlem şimdi blokların yanı sıra operatörler için de kısalmıştır:

5,_f{f{...}}
5,_ff{...}

5,_f{fx}
5,_ffx

Güzel olan şimdi bunları yuvalayabilmeniz. Böylece bir işletmeciyi listedeki üçüncü seviyeye kolayca uygulayabilirsiniz:

:::x

Ya da aldatmaca içeren bir blok:

{...}ff%

Harika güncelleme Ama hala yok f~...
jimmy23013

@ user23013 fbir ikili operatör bekliyor ~, tekli; belki istedin :~mi Ayrıca, bunu sohbette
aditsu

Bu 0.6.4 güncellemesi hakkında bir şey mi eksik? Hala hata iletileri gibi, bu hile yapıyor olsun Unhandled char after ':': :( bağlantı )
Runer112

2
@ Runer112 Benim için çalışıyor. Düzgün yeniden yüklediğinizden emin olun (örn. Önbellekten değil). Tarayıcınıza bağlı olarak Ctrl + F5 çalışmalıdır.
Martin Ender,

@ MartinBüttner Gerçekten aptalca önbellekleme nedeniyle oldu. Teşekkürler.
Runer112

7

ASCII sanatı için vectorized operatörleri

Pek çok ASCII sanat mücadelesi için, daha sonra onları üst üste getirmek için iki farklı model üretmek faydalıdır. Vectorized operatörler, farklı tiplerde üst üste binme elde etmek için çok yardımcı olabilirler.

Operatör vektörelemesinin kullanışlı bir özelliği, operatörün daha kısa dizenin / dizinin her elemanı için sadece bir kez yürütülmesidir; daha büyük olanın ise karşılığı olmayan büyük elemanlara dokunulmadan kalmasıdır.

  • .e<

    Minimum operatör e<, dizi, karakter, dizi ve tamsayı çiftleri için çalışır; yığından iki öğe çıkar ve altını e arkaya iter.

    Bir boşluk diğer tüm yazdırılabilir ASCII karakterlerinden daha düşük bir kod noktasına sahip olduğundan, .e<oluşturulan bir desenin bölümlerini "silmek" için kullanılabilir:

    "\/\/\/\/\/" "    " .e<
    
    e# This pushes "    \/\/\/".
    

    Tam bir örnek için Me Want Honeycomb'a cevabımı görün .

  • .e>

    Maksimum operatör e>, minimum sonuç olarak ters sonuçla asgari operatör olarak çalışır.

    Yine, boşluğun düşük kod noktası nedeniyle, bir boşluk .e>bloğuna yazdırılabilir bir karakter deseni eklemek için kullanılabilir:

    [[" " " " " " " "] [" " " " " " " "]][["+" "" "-" ""]["" "*" "" "/"]] ..e>
    
    e# This pushes [["+" " " "-" " "] [" " "*" " " "/"]].
    

    Tam bir örnek için Seven Slash Display'e cevabımı görün .

  • .e&

    Mantıksal AND operatörü e&, eğer yanlış ise sol argümanını, aksi takdirde sağ argümanını zorlar.

    Her iki desen de sahte öğeler içermiyorsa, bu, bir deseni diğerine koşulsuz olarak dayatmak için kullanılabilir:

    "################" " * * * *" .e&
    
    e# This pushes " * * * *########".
    

    Tam bir örnek için Amerikan Bayrağını Basma cevabımı görün ! .

  • .e|

    Mantıksal OR operatörü e|, ters argüman sırasına göre yukarıdaki gibi kullanılabilir:

    " * * * *" "################" .e|
    
    e# This pushes " * * * *########".
    

6

&Bir öğenin listede olup olmadığını kontrol etmek için kullanın

İçin

1 [1 2 3] #W>
1 [1 2 3] #)

Kullanabilirsiniz

1 [1 2 3] &,
1 [1 2 3] &

bunun yerine, sırasıyla 0/1 ve truthy / falsey döndürür.


6

z ve dikdörtgen olmayan diziler

Fermuar operatörü , elemanları aynı zamanda yinelenebilen ziki boyutlu 1 dizinin A dizilerini ve sütunlarını iletir.

Dikdörtgen olmayan diziler için - zipörneğin Python (satırları aynı uzunlukta keser) veya Ruby'deki yerleşik işlevlerin aksine (satırları alt eder nil) - CJam, dizinin sütunlarını uzunluklarını görmezden alarak satırlara dönüştürür ve boşluklar.

Örneğin, diziyi sıkıştırmak

[
  [1]
  [2 4]
  [3 5 6]
]

diziyi sıkıştırmaya eşdeğerdir

[
  [1 4 6]
  [2 5]
  [3]
]

veya dizi

[
  [1]
  [2 4 6]
  [3 5]
]

Üç eylemin tümü itilirken

[
  [1 2 3]
  [4 5]
  [6]
]

Yığında

Bu z, bunun bir icra olmadığı anlamına gelse de (bazı durumlarda faydalı olacaktır), birkaç uygulaması vardır.

Örneğin:

  • Bir dizinin sütunlarını en üste hizalayabiliriz (yani ilk diziyi ikinciye çevirin) iki kez sıkıştırarak:

    zz
    
  • Yukarıdaki yöntemin küçük modifikasyonları benzer problemler için kullanılabilir.

    Örneğin, bir dizinin sütunlarını en alta hizalamak (yani, ikinci diziyi ilk sıraya getirmek için), ters satır sırası ile iki kez zip yapabiliriz:

    W%zzW%
    
  • Bir dizi dizge verildiğinde, bunun gibi en uzun dizenin uzunluğunu hesaplayabiliriz:

    :,:e>
    

    Ancak, sonucun satır sayısını sıkıştırıp hesaplayarak üç bayt kaydedebiliriz:

    z,
    

1 A'nın "satırlarından" herhangi biri yinelenemezse, bunları tekil olarak kabul eder, bu nedenle sıkıştırma, rasgele diziler için çalışır.z


1
Aynı şeyi görselleştirmenin sadece farklı bir yolu, ancak zboş değerler atlanırken, benim için, sütunları satırlara dönüştürürken resim çizersem davranış benim için çok daha mantıklı olur . Örnekte, girdideki ilk sütun 1, 2, 3, ikinci sütun 4, 5'tir (boş konum atlanır) ve üçüncü sütun 6'dır. Bunlar daha sonra sonucun satırlarıdır.
Reto Koradi

@RetoKoradi Bunu tarif etmenin çok daha iyi bir yolu.
Dennis,

6

İstisnalar

Tüm istisnalar CJam'da ölümcüldür. Yana standart hataya çıkış varsayılan olarak göz ardı edilir , bizim için avantaj kullanabilirsiniz.

CJam'deki tüm operatör, yığından sıfır veya daha fazla öğe çıkartarak çalışır, bazı işler gerçekleştirir ve yığına sıfır veya daha fazla öğe iter. Görev gerçekleştirilirken istisnalar ortaya çıkar, bu nedenle bu öğeler hala açılır, ancak karşılığında hiçbir şey zorlanmaz.

İşte birkaç kullanım durumu:

  • Küçük bir yığını temizleme

    İki eleman içeren bir yığını temizlemek @için kullanılabilir. @üç yığın öğesi çıkarmaya çalışır, ancak ikincisini kapattıktan sonra başarısız olur.

    Üç eleman atan diğer herhangi bir operatör aynı amaca hizmet eder.

    Burada çalışırken görün .

  • İki veya üç öğeyi yığından çıkarma

    Bu özel elemanlar için uygulanmayan herhangi bir operatör, çıkmadan hemen önce yığından iki veya üç eleman çıkarmak için kullanılabilir.

    İki öğeyi patlatmak için b, bunlardan biri karakter veya hiçbiri tam sayı değilse işe yarar.

    Üç öğeyi taçmak için, en alttaki ikisinin hiçbiri yinelenebilir değilse, en alttaki en yinelenebilir boş değilse veya hiçbiri bir tamsayı değilse çalışır.

  • Döngüden çıkma

    Bazen, bir tamsayı sıfır olduğunda veya bir dize çok kısa olduğunda bir döngüden çıkmamız gerekir. Bu koşullar için yapılan testlerden ziyade, ilgili işlemler sıfır, boş dize veya singletonlar için başarısız olursa, programın doğal yoluna girmesine izin verebiliriz.

    Aritmetik içeren bir örnek için, buraya bakın .

    Dizeleri içeren bir örnek için, buraya bakın .

  • Koşullu yürütme

    Kaynak kodunun belirli giriş türleri için çalıştırılmaması gerekiyorsa, bazen bu tür girişlerde başarısız olan bir operatör kullanabiliriz.

    Örneğin, ibir tamsayı için değerlendirme ewyapmayan dizeler için başarısız olur ve 0 veya 1 uzunluktaki dizeler için başarısız olur.

    Burada çalışırken görün .


5

Bir diziden Maks / Min

İşte yeni başlayanlar için bir tane!

Bir diziden maksimum veya minimum sayıyı bulmanız gerektiğinde, en kolay ve en küçük yol diziyi sıralamak ve ardından ilk veya son öğeyi çıkarmaktır.

Yani dizi değişken ise A

A$W=

maksimum ve

A$0=

asgaridir.

Her ikisini de aynı anda alın

A$)\0=

Bu okuduktan sonra açık gözükebilir, ancak herhangi birinin ilk girişimi, kullanımına devam eden diziyi yinelemeye e<ya da tekrar etmeye meyillidir.e>

A{e<}*

2 bayt daha uzun ve hem max hem de min isterseniz daha uzun.


Eğer yığın kalan dizinin geri kalanını sakıncası yoksa tabii, aslında kullanabilirsiniz (ve )yerine 0=ve W=.
Martin Ender

Şimdi var :e<ve:e>
aditsu

@aditsu Yine de, yukarıdaki uçtan daha kısa değiller.
Doktor

5

Büyük sayılar için bir zaman damgası kullanın.

Çok büyük, ancak keyfi bir sayıya ihtiyacınız varsa, genellikle ya gibi 9e9büyük bilimsel değişkenleri kullanır ya da büyük yerleşik değişkenlerden birini benzer bir güce yükseltirsiniz KK#. Ancak, asıl sayının ne olduğu umrunda değilse ve sürekli olarak aynı olması gerekmez (örneğin, rastgele bir sayının üst sınırı gibi), bunu kullanarak iki baytta yapabilirsiniz.

es

yerine. Bu, geçerli zaman damgasını milisaniye cinsinden verir ve 10 12 düzeyindedir.


3
Ayrıca büyük bir rasgele sayı istiyorsanız ve birlikte bir pozitif sayıyı silmek istiyorsanız, kullanabileceğinizi unutmayın e9.
jimmy23013

5

İki dizenin / dizinin eşit olmadığını kontrol etmek

Bazen, iki dize veya dizi eşit olmadığında bir truthy değeri ve eğer öyleyse sahte bir değer istersiniz. Açık bir çözüm iki bayttır:

=!

Eşitliği kontrol edin ve sonucu ters çevirin. Ancak, bazı koşullar altında kullanabilirsiniz.

#

Ne zaman #ilk bir alt dizisinde ikinci dizi için iki dizide aslında aramalar uygulanan (ve size endeksi altdizilim başlar verir) olduğunu. Böylece, iki dizi aynıysa, alt dizi hemen başlangıçta bulunacak ve vermeyecektir 0. Fakat ikinci dizi bulunamazsa, -1hangisinin gerçek olmadığını verir.

İki dizide ek koşullara gereksinim duymamızın nedeni, ikinci dizi birincinin önemsiz bir öneki ise, bunun da sahte bir değer vermesidir.

"abc""ab"#

0dizeleri aynı olmasa da verir . Bu olayı dışlayan en basit koşul, her iki dizinin de aynı uzunlukta olacağını bilmenizdir - bu durumda biri diğerinin öneki ise, onların eşit olduğunu bilirsiniz. Ancak belirli durumlarda, yeterli olan daha zayıf koşullar da olabilir. Örneğin, dizelerin sıralandığını biliyorsanız, önek ikinciden değil her zaman ilk dize olur.


5

c ve 16 bit tam sayılar

Düzgün sarma ile işaretsiz 16 bitlik tamsayıları eklemek (veya çıkarmak) için +65536%veya kullanabilirsiniz +2G#%.

Ancak,

+ci

çok daha kısa. Karakterler 65536'da etrafa sarılır , bu yüzden Karakter ( c) 'e, sonra Long ( i)' a benzer bir etkiye sahip olur 65536%, bunun da ekli avantaj, sonucun negatif olmayacağıdır.

Aynı numara 65535'i itmek için de kullanılabilir :

Wci

4

Güç setleri

Bir diziniz olduğunu ve bu dizinin tüm olası altkümelerini içeren bir dizi istediğinizi söyleyin. İşin püf noktası boş bir dizi ile başlamak ve sonra, her öğe için, sahip olduğunuz alt kümeleri çoğaltın ve onlara yeni öğe ekleyin (öğenin eklenmemiş olduğu önceki sonucu koruyarak ). Yığını temel durumla, yani yalnızca boş bir dizi içeren bir dizi ile başlatmanız gerektiğini unutmayın: Bu şöyle görünebilir:

[1 2 3 4 5]La\{1$f++}/

Bu konuda iyi bir şey, potansiyel olarak eklenmiş karakterler olmadan derhal bazı hesaplamaları alt kümede çalıştırabilirsiniz. Tüm altkümelerin ürünlerini istediğinizi söyleyin. Bu durumda, temel durum içeren bir dizidir 1ve her adımda, önceki olası ürünler listesini alır, çoğaltır ve kopyadaki her şeyi yeni öğeyle çarpın:

[1 2 3 4 5]1a\{1$f*+}/

4

Listedeki öğelerin tamamen aynı olup olmadığını kontrol edin

Bunun da söylemeye değer olduğunu düşünüyorum. kullanın:

)-

Hepsi aynı değilse gerçeği, aynı ise boş listeyi döndürür. Liste boşsa hatalar.

Çıkarılan öğenin kendisi bir dizi (veya dize) olabilirse:

)a-

Boole değerleri almak için !veya !!düğmesini kullanın . Çıkarılan öğenin bir dizi olması ve en fazla iki tür farklı öğe olması durumunda ve bunların hepsi aynı değilse, 1 olmasını istersiniz, bu daha kısadır:

_|,(

4

0= dizeler için

Bir dizinin ilk elemanını almak için, kullanmanız gerekir 0=(veya (dizinin geri kalanını yığında bırakmaktan çekinmezseniz).

Bununla birlikte, bu dizi bir dizge ise, karaktere döküm yapmak yeterlidir.

Örnek

"xyz"c e# Pushes 'x.

CJam'ın neden cherhangi bir dizinin ilk elemanını çıkarmaya izin vermediğini anlamıyorum , ki bu daha faydalı ve tutarlı olacaktır.
Esolanging Fruit

4

Bir diziyi (veya yığını) bir birim sola döndürme

CJam, sola döndürme operatörüne sahiptir m<; bu, normalde bir diziyi sola rastgele birimler sayısı döndürmek için kullanmanız gereken şeydir.

Gelen bazı durumlarda, ayrıca kullanabilirsiniz (+vardiya ve eklerine:

[1 2 3]       (+ e# Pushes [2 3 1].
[[1] [2] [3]] (+ e# Pushes [[2] [3] 1].

İkinci örnek işe yaramadı çünkü dizilerin birinci elemanı aynı zamanda yinelenebilir, bu yüzden +eklemek yerine birleştirildi.

Ayrıca, döndürülmüş diziyi yığına atmak istiyorsanız, :\koşulsuz olarak kullanabilirsiniz (değiştirerek azaltabilirsiniz):

[1 2 3]       :\ e# Pushes 2 3 1.
[[1] [2] [3]] :\ e# Pushes [2] [3] [1].

Açık olmadığın sürece [, bu numara tüm yığını döndürmek, yani en alttaki yığın öğesini en üste getirmek için kullanılabilir:

]:\

3

Liste yazdırma ve yığını temizleme

Diyelim ki yığında dizge / sayılar / etc listesi var. Üstte ve altındaki diğer bazı ekstra öğeler. yani

123 "waste" ["a" "b" "rty" "print" "me" "please"]

Şimdi sadece son listeyi yazdırmakla ilgileniyorsunuz, yani

S*]W=

hangi çıktılar

a b rty print me please

Yığın temizleme hilesini kullanırken ve yalnızca boşluklarla birleştirilmiş listeyi yazdırırken (zaman zaman liste yazdırmanın istenen yolu olmayabilir) gerçekten akıllı görünüyor.

Bu daha fazla golf oynayabilir!

p];

Bu 2 bayt daha kısa !

ve listeden başka bir yığında yalnızca 1 öğeniz varsa, bu bile daha kısadır!

p;

Bunun güzelliği, pen üstteki öğeyi yığından çıkarması, dizgeye koyması (sonunda yeni bir satır ekler) ve kodun tamamlanmasını beklemeden anında STDOUT'a yazdırmasıdır.

Yani yukarıdaki kod çıkacak

["a" "b" "rty" "print" "me" "please"]

yığındayken bir listenin tam temsilidir!


3

Kartezyen ürünler veya iki veya daha fazla setin olası tüm kombinasyonları

CJam, yığındaki m*en iyi iki arylist / dizgiyi alan ve ondan tüm olası çiftleri yaratan dahili bir Kartezyen ürün hesaplayıcısına sahiptir. Örneğin

[1 2 3 4]"abc"m*

yapraklar

[[1 'a] [1 'b] [1 'c] [2 'a] [2 'b] [2 'c] [3 'a] [3 'b] [3 'c] [4 'a] [4 'b] [4 'c]]

yığın olarak

Ancak, 2 listeden / dizeden tüm olası kombinasyonları istiyorsanız. Bunu m*defalarca mı kullanıyorsun ? Örneğin

[1 2 3 4][5 6]"abc"m*m*

aşağıdakileri istifte bırakacak

[[1 [5 'a]] [1 [5 'b]] [1 [5 'c]] [1 [6 'a]] [1 [6 'b]] [1 [6 'c]] [2 [5 'a]] [2 [5 'b]] [2 [5 'c]] [2 [6 'a]] [2 [6 'b]] [2 [6 'c]] [3 [5 'a]] [3 [5 'b]] [3 [5 'c]] [3 [6 'a]] [3 [6 'b]] [3 [6 'c]] [4 [5 'a]] [4 [5 'b]] [4 [5 'c]] [4 [6 'a]] [4 [6 'b]] [4 [6 'c]]]

Ürünlerin, eşlerden birinin bir çiftin kendisi olduğu çiftlerin olduğuna dikkat edin. Bu beklenmiyor ve düzleştirilmiş kombinasyonlar istiyoruz.

Bunu yapmanın kolay bir yolu var. Kartezyen ürününüz için istediğiniz her listeyi bir diziye sarın, çift olarak Kartezyen ürünleri oluşturun ve her seferinde yassılaştırın:

[1 2 3 4][5 6]"abc"]{m*{(+}%}*

Bu yapraklar

[['a 5 1] ['b 5 1] ['c 5 1] ['a 6 1] ['b 6 1] ['c 6 1] ['a 5 2] ['b 5 2] ['c 5 2] ['a 6 2] ['b 6 2] ['c 6 2] ['a 5 3] ['b 5 3] ['c 5 3] ['a 6 3] ['b 6 3] ['c 6 3] ['a 5 4] ['b 5 4] ['c 5 4] ['a 6 4] ['b 6 4] ['c 6 4]]

Yığında

Siparişin korunmasını ister misiniz? , sadece popped öğesini tekrar diziye eklemeden önce değiştir. yani

{m*{(\+}%}*

Sadece permütasyonlar ister misiniz?

{m*{(+$}%_&}*

Kombinasyonlarda sadece benzersiz elemanlar ister misiniz?

{m*{(+_&}%}*

Hepsi bu kadar millet. Şimdilik .


1
Artık ]:m*:e_, herhangi bir dizi ile de yapabilirsiniz
aditsu

3

Tellerde çalışma

Bazen karmaşık bir veri yapısıyla çalışıyorsanız, içindeki öğeler basitken dizelere dönüştürmek yardımcı olabilir.

Örneğin, 2B bit dizisindeki ilk veya son birkaç öğeyi elde etmek istiyorsanız ve döndürülen sA<türle ilgilenmiyorsanız , 0=A<veya baytından tasarruf edin :+A<.

Veya girdideki bazı bitleri değiştirmek isterseniz, değerlendirmeden önce dizeyi değiştirebilirsiniz.

Veya bu yapıya sahipseniz ve basit bir listeye dönüştürmek istiyorsanız:

[[[[[[[[[1]2]3]4]5]6]7]8]9]

Başka şekillerde birçok karakterle yapabilirsiniz:

[a{~)\}h;]W%

Ancak dizelerle daha kısa olabilir:

s:~

Birden fazla rakam içeren rakamlar olsa bile daha kısadır:

[`La`-~]

Veya:

`']-~]

Bu tür dizilerin çoğunu içeren başka bir diziye ihtiyacınız yoksa.


Orada e_şimdi
aditsu

@Aditsu Bu cevabı ve yorumu görün . Bazen shala daha iyi çalışıyor.
jimmy23013

Elbette, bir dizeyle doğrudan çalışabiliyorsanız, daha kısa olur.
aditsu

3

Kullanma NyerineLa

Çoğu durumda, boş bir dizi içeren tek bir dizi için başlatılan bir şeye ihtiyacınız vardır, yani La, görünüşte gereksiz yere 1 bayt daha uzundur.

Çoğu durumda, yazdırmadan önce her elemanın arkasına yeni bir satır eklemeniz gerekir; bu, Noveya benzeri bir şey olur N*.

Ancak her ikisi de doğruysa, bazen Nnewline karakterinin tek öğesi olan diziyi başlatabileceğinizi öğrenebilirsiniz . Şeyleri yalnızca kodunuzun geri kalan kısmındaki öğelere hazırladığınızdan emin olun ve hazırlamak için ilk şey her zaman bir karakter veya dizidir. Ya da sadece, eğer yeni bir satırsonu kabul edilebilirse ve bu durum onu ​​kısaltırsa ekleyiniz.

Bazen Sçıktıyı boşluklarla ayırmanız gerekirse de çalışır.

Nadir durumlarda, ilk eleman bir dize olmalıdır. Ancak, Nadaha sonra newline'ı eklemekten daha kısa olanı kullanabilirsiniz .


2

Bir veya daha fazla oluşumda bölme

Bir dize olduğunu "abbcdbbfghbdbb"ve ayırmak istediğini söyle .b

"abbcdbbfghbdbb"'b/

Bu yığında bırakır:

["a" "" "cd" "" "fgh" "d" "" ""]

Boş dizeleri fark? Oradalar çünkü ikisi bbirlikteydi ve aralarında hiçbir şey yoktu. Bazen bundan kaçınmak istersiniz. Bunu yapabilirsin

"abbcdbbfghbdbb"'b/La-

veya boş dizgileri filtrelemek

"abbcdbbfghbdbb"'b/{},

ama bu 3 ekstra bayt.

Bu özel kullanım durumu için az bilinen bir operatör %. Mod ve harita yapmak ve sayıya ( "abcd"2%= "ac") göre %bölmek dışında dizgelerde / dizilerde de bölebilirsiniz. Yani yukarıdaki kullanım durum için:

"abbcdbbfghbdbb"'b%

ayrılacak

["a" "cd" "fgh" "d"]

Yığında

@ User23013 için bugün verdiğim yanıtlardan birinde bunu gösterdiğiniz için teşekkür ederiz.


Bunun "belgelemede daha iyi örnekler içeren GolfScript'i de öğren" olarak adlandırılması gerektiğini düşünüyorum.
jimmy23013

@ user23013, ancak GS'ye neyin benzer ve neyin benzer olduğundan asla emin değiliz.
Doktor

2

Katlama / azaltma için forix forix kullanın

Ve :xiçin bir kısayolumuz var ( {x}%ya da tekli ya da ikili {x}*olmasına bağlı olarak x). Ne yazık ki, kısaltılacak eşdeğer bir infix operatörü yoktur {x}/. Ancak, çok sık yaptığımız zaman {x}/, xtekrar tekrar yığın madde yatan derini değiştiren bir ikili operatör aslında. Bu durumda ve bahsedilen öğe bir dizi değilse, foreach olarak katla / azaltarak kötüye kullanarak bir bayt kaydedebiliriz:

5 [1 2 3 4]{-}/  e# Gives -5
5 [1 2 3 4]+:-

Bu işe yarar, çünkü kıvrım her zaman ilk elemanı el değmeden bırakır. Ne yazık ki, değiştirilmiş eleman bir dizi olduğunda bayt kaydetmez, çünkü onu eklemek onu açacaktır. Ancak, bazen dizinizin önünde zaten o öğeyi içerdiği için şanslısınız , bu durumda azaltma işlemi akılda tutulmalıdır ( {}/kalanı kullanmadan önce öğeyi elle kaldırmak yerine ).


2

yazdır ve yazdır

CJam vardır printoperatörünü: o. Çalışıyor ancak yığın tüm kod çalıştırıldıktan hemen sonra yazdırıyor. Program sonunda yığını temizlerseniz durdurabilirsiniz. Basitçe şunu sonuna koy:

];

Kullanabileceğiniz println için oNoveya p(aynı eser `oNo)


3
oVe arasında daha büyük bir fark var p. pYazdırılacak öğeyi açık bir dize temsiline dönüştürerek başlar. pyürütmeye eşdeğerdir ​`oNo.
Dennis,
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.