CJam adalah bahasa golf berbasis stack yang terinspirasi dari GolfScript, dibuat oleh pengguna aditsu PPCG .
Jadi, di tengah pertanyaan kiat khusus bahasa lainnya:
Apa tips umum yang Anda miliki untuk bermain golf di CJam? Silakan kirim satu tip per jawaban.
Jawaban:
Modulo yang benar untuk angka negatif
Seringkali menjengkelkan bahwa hasil operasi modulo memberikan tanda yang sama dengan operan pertama. Misalnya
-5 3%
memberi-2
bukan1
. Lebih sering daripada tidak Anda inginkan yang terakhir. Perbaikan naif adalah untuk menerapkan modulo, tambahkan pembagi sekali dan menerapkan modulo lagi:Tapi itu panjang dan jelek. Sebagai gantinya, kita dapat menggunakan fakta bahwa pengindeksan array selalu modular dan tidak bekerja dengan benar dengan indeks negatif. Jadi kami hanya mengubah pembagi menjadi rentang dan mengaksesnya:
Diterapkan untuk
-5
, ini memberi1
seperti yang diharapkan. Dan itu hanya satu byte lebih panjang dari built-in%
!Jika modulus adalah kekuatan 2, Anda dapat menyimpan byte lain menggunakan bitwise arihmetic (yang juga jauh lebih cepat). Membandingkan:
Untuk kasus khusus
65536 == 2^16
byte lain dapat disimpan dengan memanfaatkan perilaku pembungkus tipe karakter:sumber
Mendorong rentang karakter gabungan
String yang berisi semua digit
"0123456789"
dapat ditulis sebagaiHuruf ASCII huruf besar (
A-Z
) dapat didorong sebagaiyang menghasilkan string semua karakter hingga Z , kemudian membuang 65 pertama (hingga @ ).
Semua huruf ASCII (
A-Za-z
) dapat didorong sebagaiyang berfungsi seperti di atas, lalu membuat salinan, mengonversi ke huruf kecil dan menambahkan.
Tetapi ada cara yang lebih singkat untuk melakukannya!
Kemudian sering diabaikan
^
operator (perbedaan simetris untuk daftar) memungkinkan untuk membuat rentang yang sama sambil menghemat tiga byte:'[,
membuat rentang semua karakter ASCII hingga Z ,_el
membuat salinan huruf kecil dan^
hanya menyimpan karakter dari kedua string yang muncul dalam satu tetapi tidak keduanya.Karena semua huruf dalam string pertama adalah huruf besar, semua yang kedua adalah huruf kecil dan semua karakter non-huruf berada di kedua string, yang menghasilkan string huruf.
Alfabet RFC 1642 Base64 (
A-Za-z0-9+/
) dapat didorong menggunakan teknik di atas dan menambahkan non-huruf:Cara yang sama pendeknya untuk mendorong string ini hanya menggunakan perbedaan simetris:
Bagaimana kita dapat menemukan string di awal?
Semua rentang karakter digunakan (
A-Z
,a-z
,0-9
,+
,/
) dapat didorong sebagai perbedaan simetris untuk rentang yang mulai byte null, yaitu'A,'[,^
,'a,'{,^
,'0,':,^
,'+,',,^
dan'/,'0,^
.Karena itu, mengeksekusi
:,:^
pada"A[a{):+,/0"
akan mendorong karakter yang diinginkan, tetapi tidak dalam urutan yang benar.Bagaimana kita menemukan urutan yang benar? Brute force untuk menyelamatkan! Program
iterates atas semua kemungkinan permutasi string, berlaku
:,:^
dan bandingkan hasilnya dengan output yang diinginkan ( permalink ).Alfabet radix-64 yang digunakan, misalnya, oleh crypt (
.-9A-Za-z
) dapat dihasilkan menggunakan metode di atas:Ini adalah metode terpendek yang saya tahu.
Karena semua karakter dalam output yang diinginkan adalah dalam urutan ASCII, iterasi dari permutasi tidak diperlukan.
Tidak semua rentang karakter gabungan dapat didorong dalam urutan yang diinginkan menggunakan
:,:^
.Misalnya, rentang
0-9A-Za-z;-?
tidak dapat didorong dengan mengeksekusi:,:^
pada permutasi dari"0:A[a{;@"
.Namun, kita dapat menemukan variasi yang dirotasi dari string yang diinginkan yang dapat, dengan menggunakan kode
yang akan mencetak ( permalink ) berikut ini:
Ini artinya
memiliki efek yang sama dengan
yang hanya dapat digunakan dengan tumpukan kosong tanpa harus menambahkan
[
.sumber
Hindari {...} {...}?
Asumsikan Anda memiliki bilangan bulat di tumpukan. Jika aneh, Anda ingin mengalikannya dengan 3 dan menambahkan 1; jika tidak, Anda ingin membaginya dengan 2.
Pernyataan "normal" jika / else akan terlihat seperti ini:
Namun, menggunakan blok biasanya bukan cara untuk pergi, karena
{}{}
sudah menambahkan empat byte.?
juga dapat digunakan untuk memilih satu dari dua item di tumpukan:Ini lebih pendek satu byte.
Blok-? dengan pernyataan if kosong selalu merupakan larangan. Sebagai contoh,
dua byte lebih panjang dari
Jika sebaliknya Anda miliki
dan hal yang Anda periksa adalah bilangan bulat non-negatif, yang dapat Anda lakukan
Yang baru
{}&
dan{}|
praktis, tetapi terkadang bermasalah jika Anda tidak dapat mengacaukan tumpukan.Namun, dalam kasus
Anda bisa menggunakan variabel sementara sebagai gantinya:
sumber
!)/
dang)/
lebih pendek dalam contoh.Ganti pernyataan
CJam tidak memiliki pernyataan switch. Bersarang jika pernyataan bekerja dengan baik, tetapi
{{}{}?}{}?
sudah 12 byte ...Jika kita dapat mengubah kondisi menjadi bilangan bulat kecil, non-negatif, kita dapat mengubah semua pernyataan kasus dalam string yang dibatasi dan mengevaluasi hasil yang sesuai.
Sebagai contoh, jika kita ingin mengeksekusi
code0
jika integer stack adalah 0 ,code1
jika itu adalah 1 , dancode2
jika itu adalah 2 , kita dapat menggunakanatau
atau
S/
memisahkan string menjadi["code0" "code1" "code2"]
,=
mengekstrak potongan yang sesuai, dan~
mengevaluasi kode.Klik di sini untuk melihat pergantian pernyataan dalam aksi.
Akhirnya, seperti yang disarankan oleh @ jimmy23013 dan @RetoKoradi, kita dapat lebih mempersingkat sakelar dalam beberapa kasus. Katakan
code0
,code1
dan masing-masingcode2
memiliki panjang L 0 , L 1 dan L 2 .Jika L 0 = L 1 ≥ L 2
dapat digunakan sebagai pengganti, di mana
L
adalah L 0 . Alih-alih membelah pada pembatas,/
pisahkan string menjadi potongan dengan panjang yang sama di sini.Jika L 0 ≥ L 1 ≥ L 2 ≥ L 0 - 1 ,
dapat digunakan sebagai gantinya.
>
menghapus 0, 1 atau 2 elemen dari awal string, dan3%
mengekstrak setiap elemen ketiga (dimulai dengan yang pertama).sumber
"code0code1code2"5/=~
? Tampaknya jauh lebih mudah bagi saya, dan panjangnya sama.Golf array umum dan nilai string
Ada beberapa array atau string pendek yang muncul setiap saat, misalnya untuk menginisialisasi grid. Secara naif, ini bisa memakan biaya 4 byte atau lebih, jadi ada baiknya mencari operasi pada nilai bawaan yang akan memberikan hasil yang sama. Terutama konversi basis sering berguna.
[0 1]
dapat ditulis sebagai2,
.[1 0]
dapat ditulis sebagaiYYb
(yaitu 2 dalam biner).[1 1]
dapat ditulis sebagaiZYb
(yaitu 3 dalam biner).[[0 1] [1 0]]
dapat ditulis sebagai2e!
.[LL]
dapat ditulis sebagaiSS/
(membelah satu ruang dengan spasi)."\"\""
dapat ditulis sebagaiL`
."{}"
dapat ditulis sebagai{}s
.Yang terakhir dapat diperluas ke kasus di mana Anda ingin semua tipe braket menyimpan byte lain:
"[{<()>}]"
dapat ditulis sebagai{<()>}a`
."()<>[]{}"
dapat ditulis sebagai{<()>}a`$
.Terutama trik konversi basis dapat berguna untuk diingat untuk beberapa kasus tidak jelas yang muncul setiap saat. Misalnya
[3 2]
akanE4b
(14 dalam basis 4).Dalam kasus yang bahkan lebih jarang, Anda bahkan mungkin menemukan operator factorisation
mf
berguna. Misalnya[2 7]
adalahEmf
.Silakan memperpanjang daftar ini jika Anda menemukan contoh lain.
sumber
Membersihkan tumpukan
Jika Anda hanya ingin menghapus seluruh tumpukan, bungkus dalam array dan letakan:
Yang sedikit lebih rumit adalah, jika Anda telah melakukan banyak perhitungan, tetapi hanya ingin mempertahankan elemen tumpukan teratas dan membuang semua yang ada di bawahnya. Pendekatan naif adalah menyimpan elemen atas dalam suatu variabel, menghapus tumpukan, mendorong variabel. Tapi ada alternatif yang jauh lebih pendek: bungkus stack dalam array dan ekstrak elemen terakhir:
(Terima kasih kepada Pengoptimal yang menunjukkan ini kepada saya tempo hari.)
Tentu saja, jika hanya ada dua elemen di stack,
\;
lebih pendek.sumber
\;
hanya akan memunculkan elemen di bawah TOS. Apakah maksud Anda;;
?e
dan kekuatan sepuluhSeperti dalam banyak bahasa lain, Anda dapat menulis
1e3
alih-alih1000
dalam CJam.Ini berfungsi untuk basis non-integer dan bahkan untuk eksponen non-integer juga. Misalnya,
1.23e2
mendorong 123.0 dan1e.5
mendorong 3.1622776601683795 (akar kuadrat dari 10 ).Yang tidak segera jelas adalah bahwa
1e3
sebenarnya ada dua token:1
mendorong bilangan bulat 1 pada tumpukan.e3
kalikan dengan 1000 .Mengapa itu penting?
Anda dapat memanggil
e<numeric literal>
sesuatu yang sudah ada di tumpukan.Anda dapat memetakan
e<numeric literal>
melalui array.sumber
Norma Euclidean
Cara langsung menghitung norma Euclidean dari vektor, yaitu, akar kuadrat dari jumlah kuadrat elemen-elemennya, adalah
Namun, ada cara yang jauh lebih pendek.
mh
, operator miring, muncul dua bilangan bulat a dan b dari tumpukan dan mendorong sqrt (a 2 + b 2 ) .Jika kita memiliki vektor x: = [x 1 ... x n ], n> 1 pada stack,
:mh
(kurangi dengan sisi miring) akan mencapai yang berikut:Pertama x 1 dan x 2 didorong dan
mh
dijalankan, meninggalkan sqrt (x 1 2 + x 2 2 ) , di tumpukan.Kemudian, x 3 didorong dan
mh
dieksekusi lagi, meninggalkansqrt (sqrt (x 1 2 + x 2 2 ) 2 + x 3 2 ) = sqrt (x 1 2 + x 2 2 + x 3 2 ) pada stack.
Setelah x n diproses, kita pergi dengan sqrt (x 1 2 + ... x n 2 ) , norma Euclidean dari x .
Jika n = 1 dan x 1 <0 , kode di atas akan menghasilkan hasil yang salah.
:mhz
bekerja tanpa syarat. (Terima kasih kepada @ MartinBüttner karena menunjukkannya.)Saya menggunakan trik ini untuk pertama kali dalam jawaban ini .
sumber
Konversi dari pangkalan n dengan daftar angka yang lebih besar dari n
CJam mengonversi daftar menjadi angka dengan rumus ini: A 0 * n l + A 1 * n l-1 + A 2 * n l-2 + A l * n 0 (dengan tidak negatif
n
).n
adalah dasar danl
panjang daftar. Ini berarti A i dapat berupa bilangan bulat apa pun, yang tidak harus berada dalam kisaran[0,n)
.Beberapa contoh:
0b
mengekstrak item terakhir dan melemparkannya ke integer. Bekerja sepertiW=i
dan menyimpan byte jika bukan bilangan bulat. Tetapi semua hal lain dalam daftar juga harus dapat dimasukkan ke dalam integer.1b
mengembalikan jumlahnya. Bekerja seperti:i:+
dan menyimpan dua byte jika bukan bilangan bulat. Ini juga berfungsi dengan daftar kosong sementara:+
tidak.[i{_1&9 32?_@\m2/}16*;]W%:c
Mengonversi karakter ke string akhiran dan tab, yang dapat dikonversi kembali dengan2bc
. Namun, fungsi pengodean tidak mudah untuk di-golf dalam program kode-golf. Tetapi Anda biasanya tidak membutuhkan itu.Anda dapat menggunakan kode berikut untuk mengubah string menjadi karakter Unicode tidak dalam 16 bit, yang dapat dikonversi kembali dengan
2A#b128b:c
. (Penjelasan akan ditambahkan nanti. Atau mungkin saya akan menulis versi baru nanti.)Metode serupa bekerja dengan set
n
integer yang memiliki mod nilai yang berbedan
, jika Anda dapat menemukan cara untuk menghilangkan digit paling signifikan.sumber
Menggunakan
$
sebagai terner jikaKetika Anda tidak keberatan membocorkan memori, yaitu, meninggalkan elemen yang tidak digunakan pada tumpukan yang nantinya akan Anda bersihkan
];
, operator penyalinan$
dapat menjadi pengganti yang berguna untuk operator ternary?
.?
berfungsi dengan baik jika Anda berhasil menghitung kondisi sebelum mendorong dua item untuk dipilih, tetapi lebih sering daripada tidak, kondisi sebenarnya tergantung pada item-item itu, dan setelah itu hasilnya lebih alami.Jika sudah ada
A B C
di stack, Anda bisa menjalankannyadari pada
untuk menyalin
B
jikaC
itu benar danA
sebaliknya.Jika
C
Boolean sebenarnya (0
atau1
), Anda dapat mengeksekusidari pada
untuk menyalin
A
jikaC
itu benar danB
sebaliknya.sumber
Peta untuk Daftar Bersarang
Katakanlah Anda punya daftar bersarang, seperti sebuah matriks:
Atau serangkaian string:
Dan Anda ingin memetakan blok ke tingkat bersarang (yaitu menerapkannya ke setiap nomor atau setiap karakter). Solusi naif adalah bersarang
%
:Namun, Anda dapat benar-benar mendorong blok bagian dalam ke tumpukan dan kemudian menggunakannya
f%
.f
adalah "map dengan parameter tambahan", sehingga akan memetakan%
ke daftar luar, menggunakan blok sebagai parameter kedua:Menghemat dua byte.
Trik lain yang rapi untuk melakukan sesuatu
for (i=0; i<5; ++i) for (j=0; j<5; ++j) {...}
adalahBagian luar
f
akan memetakan ke rentang pertama, memasok rentang kedua sebagai parameter tambahan. Tapi sekarang, jika Anda menggunakanf
lagi, hanya elemen stack atas adalah array, jadi Andaf
memetakan blok bagian dalam itu, memasok "variabel iterasi" luar sebagai parameter tambahan. Ini berarti blok dalam berjalan dengani
danj
pada tumpukan.Ini memiliki jumlah karakter yang sama dengan hanya memetakan blok ke produk Cartesian (meskipun yang terakhir semakin pendek jika Anda membutuhkan pasangan sebagai array):
Perbedaannya adalah bahwa versi ini menghasilkan satu array hasil untuk semua pasangan, sedangkan double-
f
menghasilkan daftar bersarang, yang dapat berguna jika Anda ingin menyimpan hasil dalam kotak, dengan variabel iterator menjadi koordinat.Terima kasih kepada Dennis karena menunjukkan trik ini kepada saya.
0.6.4 Pembaruan
f
dan:
sekarang telah sangat ditingkatkan dengan mengambil operator lain termasuk mereka sendiri. Ini berarti Anda dapat menyimpan lebih banyak byte sekarang. Memetakan operator ke daftar bersarang menjadi lebih pendek sekarang:Ini tidak terlalu membantu dengan memetakan blok ke daftar bersarang.
Adapun blok atau operator yang menerapkan produk Cartesian, ini juga menjadi lebih pendek sekarang, untuk blok serta operator:
Apa yang baik adalah bahwa Anda sekarang dapat bersarang ini. Jadi, Anda dapat menerapkan operator dengan mudah ke tingkat bawah daftar:
Atau satu blok dengan beberapa tipu daya:
sumber
f~
...f
mengharapkan operator biner,~
tidak waspada; apakah kamu mungkin mau:~
? Juga, kita dapat membahas ini di chatUnhandled char after ':': :
( tautan )Operator vektor untuk seni ASCII
Bagi banyak tantangan seni ASCII, akan berguna untuk menghasilkan dua pola yang berbeda untuk menempatkannya nanti. Operator vektor dapat sangat membantu untuk mencapai berbagai jenis superposisi.
Satu sifat berguna dari vektorisasi operator adalah bahwa operator hanya dieksekusi satu kali untuk setiap elemen string / array yang lebih pendek, sedangkan elemen-elemen yang lebih besar yang tidak memiliki rekanan tetap tidak tersentuh.
.e<
Operator minimum
e<
berfungsi untuk pasangan string, karakter, array dan integer; itu muncul dua item dari tumpukan dan mendorong yang lebih rendah pada e kembali.Karena spasi memiliki titik kode lebih rendah daripada semua karakter ASCII yang dapat dicetak lainnya,
.e<
dapat digunakan untuk "menghapus" bagian-bagian dari pola yang dihasilkan:Untuk contoh lengkap, lihat jawaban saya untuk Me Want Honeycomb .
.e>
Operator maksimum
e>
berfungsi sebagai operator minimum, dengan hasil sebaliknya.Sekali lagi, karena titik kode ruang yang rendah,
.e>
dapat digunakan untuk menyisipkan pola karakter yang dapat dicetak dalam blok ruang:Untuk contoh lengkap, lihat jawaban saya untuk Seven Slash Display .
.e&
Operator logika DAN
e&
mendorong argumen kiri jika argumen palsu dan kanan sebaliknya.Jika tidak ada pola yang mengandung elemen falsy, ini dapat digunakan untuk memaksakan satu pola tanpa syarat:
Sebagai contoh lengkap, lihat jawaban saya untuk Mencetak Bendera Amerika! .
.e|
Operator logika ATAU
e|
dapat digunakan seperti di atas, dengan urutan argumen terbalik:sumber
Gunakan
&
untuk memeriksa apakah suatu item ada dalam daftarUntuk
Anda dapat gunakan
sebaliknya, yang mengembalikan 0/1 dan truthy / falsey masing-masing.
sumber
z
dan array non-persegi panjangOperator pos
z
transposes baris dan kolom dari dua dimensi 1 Array A , yang unsur-unsurnya juga bisa iterables.Untuk array non-persegi panjang - tidak seperti fungsi built-in
zip
di, misalnya, Python (memotong baris dengan panjang yang sama) atau Ruby (bantalan baris dengannil
) - CJam hanya mengubah kolom array menjadi baris, mengabaikan panjangnya dan kesenjangan.Misalnya, zipping array
setara dengan zip array
atau array
karena ketiga tindakan mendorong
di tumpukan.
Meskipun ini berarti bahwa
z
ini bukan suatu involusi (yang akan berguna pada kesempatan tertentu), ini memiliki beberapa aplikasi.Sebagai contoh:
Kita dapat menyelaraskan kolom-kolom array ke atas (yaitu, mengubah array pertama menjadi array kedua) dengan zip dua kali:
Modifikasi kecil dari metode di atas dapat digunakan untuk masalah yang serupa.
Misalnya, untuk menyelaraskan kolom-kolom array ke bawah (yaitu, untuk mengubah array kedua menjadi yang pertama), kita dapat zip dua kali dengan urutan baris terbalik:
Diberikan array string, kita dapat menghitung panjang string terpanjang seperti ini:
Namun, dengan meng-zip dan menghitung jumlah baris dari hasil, kita dapat menyimpan tiga byte:
1 Jika salah satu dari "baris" A tidak dapat diubah,
z
perlakukan mereka sebagai lajang, jadi zipping berfungsi untuk array yang sewenang-wenang.sumber
z
mengubah kolom menjadi baris, sementara nilai kosong dilewati. Pada contoh, kolom pertama pada input adalah 1, 2, 3, kolom kedua adalah 4, 5 (posisi kosong dilewati), dan kolom ketiga adalah 6. Ini adalah baris dari hasil.Pengecualian
Semua pengecualian fatal dalam CJam. Karena output ke STDERR diabaikan secara default , kita dapat menggunakan ini untuk keuntungan kita.
Semua operator di CJam bekerja dengan mengeluarkan nol atau lebih elemen dari stack, melakukan beberapa tugas dan menekan nol atau lebih elemen pada stack. Pengecualian terjadi saat tugas dilakukan, jadi ini masih muncul elemen, tetapi tidak ada yang mendorong balasan.
Berikut beberapa kasus penggunaan:
Membersihkan tumpukan kecil
Untuk menghapus tumpukan yang berisi dua elemen,
@
bisa digunakan.@
mencoba pop tiga elemen stack, tetapi gagal setelah muncul yang kedua.Operator lain yang mengeluarkan tiga elemen akan memiliki tujuan yang sama.
Lihat beraksi di sini .
Menghapus dua atau tiga elemen dari tumpukan
Operator apa pun yang tidak diimplementasikan untuk elemen-elemen khusus ini dapat digunakan untuk mengeluarkan dua atau tiga elemen dari stack tepat sebelum keluar.
Untuk memunculkan dua elemen,
b
berfungsi jika salah satunya adalah karakter atau tidak ada yang bilangan bulat.Untuk memunculkan tiga elemen,
t
berfungsi jika tidak satu pun dari terbawah dua adalah iterable, bawah-iterable paling kosong atau tidak ada yang bilangan bulat.Keluar dari loop
Terkadang, kita perlu keluar dari loop ketika integer menjadi nol atau string menjadi terlalu pendek. Daripada menguji untuk kondisi ini, jika operasi yang terlibat gagal untuk nol, string kosong atau lajang, kita dapat membiarkan program mengambil program alami.
Untuk contoh yang melibatkan aritmatika, lihat di sini .
Untuk contoh yang melibatkan string, lihat di sini .
Eksekusi bersyarat
Jika kode sumber tidak boleh dieksekusi untuk jenis input tertentu, kami kadang-kadang dapat menggunakan operator yang gagal input semacam itu.
Misalnya,
i
akan gagal untuk string yang tidak mengevaluasi ke bilangan bulat danew
akan gagal untuk string dengan panjang 0 atau 1.Lihat beraksi di sini .
sumber
Maks / Min dari array
Ini satu untuk pemula!
Ketika Anda perlu menemukan angka maksimum atau minimum dari sebuah array, cara termudah dan terkecil adalah dengan mengurutkan array dan kemudian mengambil elemen pertama atau terakhir.
Jadi jika array dalam variabel
A
adalah maksimum dan
adalah minimum.
Mendapatkan keduanya sekaligus juga dimungkinkan
Ini mungkin tampak jelas setelah membaca, tetapi upaya pertama siapa pun cenderung mengarah ke penggunaan
e<
ataue>
melalui iterasi melalui array, yang berjalan sepertiyang 2 byte lebih lama, dan bahkan lebih lama jika Anda ingin maks dan min.
sumber
(
dan)
bukannya0=
danW=
.:e<
dan:e>
Gunakan cap waktu untuk jumlah besar
Jika Anda membutuhkan angka yang sangat besar, tetapi sewenang-wenang, Anda biasanya akan menggunakan notasi ilmiah suka
9e9
atau menaikkan salah satu variabel bawaan besar ke kekuatan yang sama, sepertiKK#
. Namun, jika Anda tidak peduli berapa angka sebenarnya, dan tidak perlu secara konsisten sama (misalnya sebagai batas atas untuk angka acak), Anda dapat melakukannya dalam dua byte menggunakansebagai gantinya. Ini memberikan cap waktu saat ini dalam milidetik, dan berada di urutan 10 12
sumber
e9
.Memeriksa bahwa dua string / array tidak sama
Terkadang Anda menginginkan nilai kebenaran ketika dua string atau array tidak sama, dan nilai palsu jika mereka. Solusi yang jelas adalah dua byte:
Periksa kesetaraan, dan balikkan hasilnya. Namun, dalam beberapa kondisi Anda dapat menggunakan
Ketika
#
diterapkan ke dua array itu sebenarnya mencari array kedua sebagai subarray yang pertama (dan memberi Anda indeks di mana subarray dimulai). Jadi, jika kedua array itu sama, subarray akan ditemukan tepat di awal dan memberi0
, yang salah. Tetapi jika array kedua tidak dapat ditemukan, itu akan memberikan-1
mana yang benar.Alasan kita memerlukan beberapa kondisi tambahan pada dua array adalah bahwa ini juga menghasilkan nilai falsy jika array kedua adalah awalan non-sepele dari array pertama, misalnya:
memberi
0
meskipun string tidak sama. Kondisi paling sederhana yang mengesampingkan kasus ini adalah jika Anda tahu bahwa kedua array akan memiliki panjang yang sama - dalam hal ini jika satu adalah awalan dari yang lain, Anda tahu bahwa keduanya sama. Tetapi dalam kondisi tertentu mungkin ada kondisi yang lebih lemah yang juga cukup. Misalnya, jika Anda tahu bahwa string diurutkan, awalan akan selalu menjadi string pertama, bukan yang kedua.sumber
c
dan bilangan bulat 16-bitUntuk menambah (atau mengurangi) bilangan bulat 16-bit yang tidak ditandatangani dengan pembungkus yang tepat, Anda dapat menggunakan
+65536%
atau+2G#%
.Namun,
jauh lebih pendek. Bungkus karakter diseluruh pada 65536 , jadi casting ke Character (
c
) lalu ke Long (i
) memiliki efek yang mirip dengan65536%
, dengan manfaat tambahan bahwa hasilnya tidak akan negatif.Trik yang sama dapat digunakan untuk mendorong 65535 :
sumber
Set daya
Katakanlah Anda memiliki array dan Anda ingin array dengan semua himpunan bagian yang mungkin dari array itu. Caranya adalah mulai dengan array kosong, dan kemudian, untuk setiap elemen, duplikat himpunan bagian yang sudah Anda miliki, dan tambahkan elemen baru ke mereka (menjaga hasil sebelumnya di mana elemen tidak ditambahkan ). Perhatikan bahwa Anda perlu menginisialisasi tumpukan dengan kasing dasar, yaitu array yang hanya berisi array kosong: Itu bisa terlihat seperti ini:
Yang menyenangkan tentang ini adalah, Anda dapat langsung menjalankan beberapa perhitungan pada subset, berpotensi tanpa karakter tambahan. Katakanlah Anda menginginkan produk dari semua himpunan bagian. Dalam hal ini, casing dasar adalah array yang berisi
1
, dan pada setiap langkah, Anda mengambil daftar produk yang mungkin sebelumnya, menduplikasinya, dan melipatgandakan segala sesuatu dalam duplikat dengan elemen baru:sumber
Periksa apakah item dalam daftar semuanya sama
Saya pikir ini juga layak disebutkan. Menggunakan:
Mengembalikan kebenaran jika tidak semua sama, atau daftar kosong jika semuanya sama. Kesalahan jika daftar kosong.
Jika item yang diekstraksi mungkin berupa array (atau string) itu sendiri:
Gunakan
!
atau!!
untuk mendapatkan nilai boolean. Jika item yang diekstraksi mungkin berupa array, dan paling banyak ada dua jenis item yang berbeda, dan Anda ingin 1 jika tidak semuanya sama, ini lebih pendek:sumber
0=
untuk stringUntuk mengambil elemen pertama dari sebuah array, Anda harus menggunakan
0=
(atau(
, jika Anda tidak keberatan meninggalkan sisa array pada stack).Namun, jika array itu adalah string, casting ke karakter sudah cukup.
Contoh
sumber
c
mengekstraksi elemen pertama dari array apa pun, yang akan lebih bermanfaat dan konsisten.Memutar array (atau tumpukan) satu unit ke kiri
CJam memiliki operator rotate left
m<
, yang biasanya apa yang harus Anda gunakan untuk memutar array jumlah unit sewenang-wenang ke kiri.Dalam beberapa kasus, Anda juga dapat menggunakan
(+
untuk menggeser dan menambahkan:Contoh kedua tidak berfungsi karena elemen array pertama juga merupakan iterable, jadi
+
disatukan alih-alih menambahkan.Juga, jika Anda ingin membuang array yang diputar pada stack, Anda dapat menggunakan
:\
(kurangi dengan bertukar) tanpa syarat:Selama Anda tidak memiliki celah terbuka
[
, trik ini juga dapat digunakan untuk merotasi seluruh tumpukan, yaitu untuk membawa item tumpukan paling bawah ke atas:sumber
Mencetak daftar dan membersihkan tumpukan
Katakanlah tumpukan Anda memiliki daftar string / angka / dll. di atas dan beberapa item tambahan lainnya di bawahnya. yaitu
Sekarang Anda tertarik untuk mencetak daftar terakhir saja, begitu juga Anda
output yang mana
Yang tampaknya benar-benar cerdas karena kami menggunakan pembersihan trik tumpukan dan hanya mencetak daftar yang digabungkan dengan spasi (yang mungkin bukan cara yang diinginkan untuk mencetak daftar di kali).
Ini bisa bermain golf lebih lanjut!
Itu 2 byte lebih pendek !
dan jika Anda hanya memiliki 1 item di stack selain dari daftar, itu bahkan lebih pendek!
Keindahannya
p
adalah ia menghilangkan item terbanyak dari stack, merangkai itu (juga menambahkan baris baru di akhir) dan mencetak ke STDOUT secara instan, tanpa menunggu penyelesaian kode.Jadi kode di atas akan ditampilkan
yang merupakan representasi tepat dari daftar ketika berada di tumpukan!
sumber
Produk Cartesian atau semua kombinasi yang mungkin dari dua set atau lebih
CJam memiliki kalkulator produk Cartesian inbuilt
m*
yang mengambil dua daftar / string array di stack dan membuat semua pasangan yang memungkinkan darinya. Sebagai contohDaun-daun
sebagai tumpukan
Tetapi bagaimana jika Anda ingin semua kemungkinan kombinasi dari lebih dari 2 daftar / string. Anda menggunakannya
m*
berkali-kali? Sebagai contohakan meninggalkan yang berikut di tumpukan
Perhatikan bahwa produk masih berpasangan, di mana salah satu itemnya adalah pasangan itu sendiri. Ini tidak diharapkan dan kami ingin kombinasi rata.
Ada cara mudah untuk melakukan itu. Hanya membungkus setiap daftar yang Anda inginkan untuk produk kartesius Anda dalam sebuah array, buat secara berpasangan buat produk Cartesius dan ratakan setiap kali:
Ini pergi
di tumpukan.
Ingin pesanan tetap terjaga? , cukup tukar sebelum menambahkan item yang muncul kembali ke array. yaitu
Ingin hanya permutasi?
Ingin hanya elemen unik dalam kombinasi?
Itu semua orang. untuk sekarang .
sumber
]:m*:e_
, dengan sejumlah arrayBeroperasi dengan string
Terkadang jika Anda bekerja dengan struktur data yang kompleks, sementara item di dalamnya sederhana, mengonversi ke string dapat membantu.
Misalnya, jika Anda ingin mendapatkan item pertama atau terakhir dalam array 2D bit, dan tidak peduli dengan tipe yang dikembalikan,
sA<
simpan satu byte dari0=A<
atau:+A<
.Atau jika Anda ingin memodifikasi beberapa bit dalam input, Anda dapat memodifikasi string sebelum mengevaluasinya.
Atau jika Anda mendapatkan struktur ini dan ingin mengubahnya menjadi daftar sederhana:
Anda dapat melakukannya dengan banyak karakter dengan cara lain:
Tetapi bisa jauh lebih pendek dengan string:
Ini lebih pendek bahkan jika mungkin memiliki angka dengan lebih dari satu digit:
Atau:
Jika Anda tidak memerlukan array lain yang mengandung banyak array seperti itu.
sumber
e_
sekarangs
masih bekerja lebih baik.Menggunakan
N
bukanLa
Dalam banyak kasus, Anda memerlukan sesuatu yang diinisialisasi ke array yang berisi array kosong sebagai satu-satunya elemen, yang
La
sepertinya 1 byte lebih lama tidak perlu.Dalam banyak kasus, Anda juga perlu menambahkan baris baru setelah setiap elemen sebelum mencetak, yang akan menjadi seperti
No
atauN*
.Tetapi jika keduanya benar, kadang-kadang Anda mungkin menemukan bahwa Anda bisa menginisialisasi array dengan
N
, yang memiliki karakter baris baru sebagai satu-satunya elemen. Pastikan Anda hanya menambahkan beberapa hal ke elemen dalam sisa kode Anda, dan hal pertama yang bergantung pada selalu karakter atau array. Atau hanya menambahkan, jika suatu baris baru dapat diterima dan itu membuatnya lebih pendek.Terkadang
S
juga berfungsi jika Anda perlu memisahkan output dengan spasi.Dalam kasus yang lebih jarang, elemen awal harus berupa string. Tetapi Anda masih bisa menggunakan
Na
yang mungkin lebih pendek daripada menambahkan baris baru sesudahnya.sumber
Membagi satu kejadian atau lebih
Katakanlah Anda memiliki string
"abbcdbbfghbdbb"
dan Anda ingin membaginyab
Ini meninggalkan tumpukan:
Perhatikan senar kosong? Mereka ada di sana karena dua
b
bersama dan tidak ada di antara mereka. Terkadang, Anda ingin menghindari ini. Anda dapat melakukannya denganatau memfilter string kosong
tapi itu 3 byte tambahan.
Operator yang kurang dikenal untuk kasus penggunaan khusus ini adalah
%
. Selain melakukan mod dan memetakan dan pemisahan berdasarkan nomor ("abcd"2%
="ac"
),%
juga dapat dibagi pada string / array. Jadi untuk use case di atas:akan meninggalkan
di tumpukan.
Terima kasih atas @ user23013 karena menunjukkan ini dalam salah satu jawaban saya hari ini.
sumber
Gunakan lipat / kurangi sebagai infix masing-masing
Kami memiliki
:x
singkatan untuk{x}%
dan atau{x}*
(tergantung pada apakahx
unary atau binary). Sayangnya, tidak ada operator infiks yang setara untuk dipersingkat{x}/
. Namun, sangat sering ketika kita melakukannya{x}/
,x
sebenarnya adalah operator biner yang berulang kali memodifikasi item yang berada di bawah tumpukan. Jika itu yang terjadi, dan item tersebut bukan array, kita dapat menyimpan byte dengan menyalahgunakan flip / kurangi sebagai foreach:Ini berfungsi karena lipatan selalu membuat elemen pertama tidak tersentuh. Sayangnya, itu tidak menyimpan byte, ketika elemen yang diubah adalah sebuah array, karena menambahkannya akan membuka bungkusnya. Namun, kadang-kadang Anda cukup beruntung bahwa array Anda sudah mengandung elemen itu di depan, dalam hal ini pengurangan harus diingat (alih-alih menghapus elemen secara manual sebelum digunakan
{}/
pada sisanya).sumber
cetak dan println
CJam memiliki
print
Operator:o
. Ini bekerja tetapi tumpukan mencetak segera setelah semua kode dijalankan. Anda dapat menghentikannya jika Anda menghapus tumpukan di akhir program. Sederhananya di akhir:Untuk mencetak, Anda dapat menggunakan
oNo
ataup
(berfungsi sebagai`oNo
)sumber
o
danp
.p
dimulai dengan mengonversi item yang akan dicetak ke representasi string yang tidak ambigu.p
setara untuk dieksekusi`oNo
.