GolfScript mendapatkan caranya sendiri terlalu sering dan saya merasa bahwa repositori petunjuk praktis untuk bermain golf di J dapat membantu dalam perang melawan kekaisaran jahat. Kiat apa yang Anda miliki untuk membuat bahasa yang sudah singkat ini lebih pendek?
Bagi mereka yang ingin belajar J, tempat yang jelas untuk memulai adalah situs jsoftware dan khususnya kosakata , panduan Learning J dan panduan programmer J untuk C.
GolfScript gets its own way far too often
pada tahun 2019.Jawaban:
Ada beberapa seluk-beluk untuk memeras beberapa karakter terakhir dalam J. Untuk yang berikut, asumsikan bahwa setiap huruf kapital adalah kata kerja primitif (yaitu saya menghilangkan spasi yang seharusnya diperlukan untuk membatasi nama).
Ketika Anda memiliki kereta pergi, dan Anda perlu menerapkan fungsi di atas bagian lain,
([:FLGR)
dan(LF@:GR)
memiliki jumlah karakter yang sama, tetapi(LF@GR)
menyimpan satu. Jika kerangka G lebih besar dari atau sama dengan peringkat monad F, ini adalah transformasi yang valid. Khususnya, semua kereta memiliki peringkat yang tak terbatas, seperti halnya, ,. ,: ~. /: \: [ ]
dan sebagian besar menggunakan#
dan|.
.Jika Anda harus memilih string dari daftar, dan string ini tidak memiliki spasi, gunakan
>i{ab`cd`ef
. Itu kotor, tetapi menyimpan karakter untuk setiap string baru yang harus Anda tangani, kecuali Anda hanya menarik karakter tunggal, dan bahkan kemudian charlist harus panjang 4 agar lebih pendek. Apa yang terjadi adalah bahwa nama-nama yang tidak didefinisikan diperlakukan sebagai referensi untuk kata kerja, dan ketika Anda mengambil gerunds dari kata kerja itu Anda mendapatkan string kotak nama. Setiap nama yang sudah didefinisikan memiliki noun type, kata keterangan, atau kata sambung tidak dapat digunakan dengan cara ini, karena nama-nama itu diselesaikan sebelum`
dapat memiliki mereka.Jika Anda cukup beruntung untuk memiliki ekspresi untuk bekerja dengan dan bukan hanya kata kerja diam-diam, itu hampir selalu layak untuk menetapkan bit yang Anda gunakan kembali ke variabel, baik itu kata benda, kata kerja, atau kata keterangan. Para orangtua kadang-kadang akan membayar sendiri dengan memasukkan tepat ke tempat Anda memiliki ruang sebelumnya, dan sebagian besar definisi seperti itu layak jika mereka digunakan kembali bahkan sekali lagi.
Konjungsi seperti
(FGH)^:(u`v`w)
dapat ditulis ulangu`v`w(FGH^:)
. Ini bisa digunakan untuk semua lamanya kereta, bahkan 1, meskipun Anda hanya menyimpan apa pun jika trik ini menghilangkan parens dari argumen yang benar. Trik ini hanya berfungsi ketika Anda melakukan preload operan kiri. (Tidak tahu apa yang baru saja terjadi? Cari 'tacit adverbs', dan pelajari bagian Parsing and Execution dari J Dictionary.)Jangan gunakan
a.&i.
, gunakanu:
!{&a.
dan3&u:
sama panjangnya, dan yang pertama mungkin lebih berguna dalam konjungsi (tergantung pada konjungsi).Hal-hal seperti
(2%~F)
dan(F%2:)
panjangnya setara. Ini berguna karena kadang-kadang, tergantung pada apa yang tampak seperti sisa kereta Anda, Anda dapat menyusunnya kembali dengan@
trik seperti yang tertulis di poin pertama, untuk menyelamatkan beberapa karakter yang putus asa. (Dan tentu saja, jikaF
ada]
dan kereta api adalah monad, menggunakan%&2
menghemat char, ya.)Kereta seperti kait dengan
]
atau[
sebagai kata kerja paling kiri, mis(]FGH)
.]
memungkinkan Anda memecah aplikasi diad dan hanya menggunakan argumen yang tepat. (Bertukar ke kiri dengan(]FGH)~
, hukuman minimal 1 karakter, mungkin lebih.) Menghemat char(FGH)@]
, dan sangat berguna dalam gerunds![
dalam hook yang diterapkan secara monad memungkinkan Anda melakukan sesuatu untuk efek samping di sisi kanan, lalu kembalikan argumennya. Penggunaan paling umum adalah dengan1!:2
, mungkin dengan memformat sampah.Saya / O menyebalkan. Percepat proses dengan membuat loop dari semua yang Anda bisa.
1!:1
memiliki peringkat0
, dan keduanya1!:2 3
memiliki peringkat_ 0
, misalnya, jadi gunakan ini dengan membuat array 1s dan menabrak1!:1
mereka secara langsung. Perhatikan bahwa".
juga memiliki peringkat 1, jadi Anda biasanya bisa langsung memasukkannya setelah1!:1
itu, dan tidak harus melampirkannya melalui@
atau peringkat shenanigans.Tidak mudah menemukan tempat untuk meletakkan ini, tetapi
::
dapat bermanfaat.::]^:_
adalah kombinasi yang sangat kuat, misalnya, yang memungkinkan Anda melakukan sesuatu yang berbahaya sampai Anda tidak dapat melakukannya lagi. (Tunduk pada^:_
peringatan -as-a-loop biasa.)Ini juga memungkinkan Anda menggunakan
{
daftar yang tidak memiliki indeks yang diinginkan, karena itu membuat kesalahan domain ketika itu terjadi. Berguna untuk misalnya mengambil kepala daftar hanya jika ada (coba gunakan::]
untuk mengembalikan daftar kosong, atau::_1:
untuk mengembalikan kode kesalahan, dan sebagainya).]`($:@u)@.v
biasanya dapat dibuat lebih pendek dariu^:v^:_
, terutama pada definisiu
danv
yang bisa dimainkan. Kasus serupa berlaku untuk bersyarat sepertiu^:(1-v)
vs]`[email protected]
. Pertimbangkan opsi-opsi Anda, terutama ketika Anda memiliki banyak kata kerja bernama mengambang. Ini juga sedikit lebih fleksibel, tetapi ingat, jika menggunakan$:
, ada kedalaman rekursi yang mudah ditabrak. (Biasanya sekitar 1800 iterasi?)sumber
%&2
menghemat char, ya." Dan-:
menyimpan yang lain!Yang paling penting ketika bermain golf di J adalah tidak hanya memahami masalah, tetapi untuk mengurangi masalah menjadi serangkaian transformasi array. Anda perlu memahami cara berpikir ini untuk sukses dengan kode J.
Misalnya, tantangan terbaru diminta untuk memecahkan masalah subarray terbesar . Algoritma stok untuk mengatasi masalah ini adalah algoritma Kadane memiliki uraian informal berikut:
Terjemahan ke dalam kode imperatif sangat mudah:
Algoritma ini tampaknya rumit untuk J secara sekilas karena ada loop eksplisit yang tidak terlihat seperti pengurangan pada awalnya. Jika Anda menyadari apa yang dilakukan algoritma, Anda dapat menguraikan langkah-langkah individual dan melihat bahwa itu benar-benar melakukan dua operasi array sederhana:
Sekarang kedua langkah ini sangat mudah diimplementasikan dalam J. Berikut ini adalah terjemahannya:
(0 >. +)/\. y , 0
- Langkah ini beroperasi dari ujung array agar lebih sesuai dengan paradigma J.0 >. +
adalah diam-diam untuk0 >. x + y
.>./ y
Secara keseluruhan, kami mendapatkan implementasi algoritma yang sangat singkat:
Jika Anda mempelajari cara mendekati penerapan algoritma ini, solusi Anda akan sesingkat kode ini.
Berikut adalah beberapa trik yang saya kumpulkan dari waktu ke waktu. Daftar ini akan diperluas karena saya mendapatkan lebih banyak pengetahuan tentang golf.
=
aneh pada awalnya tetapi sangat berguna dalam tantangan seni ASCII.&
dalam konteks tersembunyi ketika Anda menginginkan konjungsi kekuatan. Kosa kata menyarankanu@[&0
sebagai pengganti diam-diam untuk4 : 'u^:x y
dan aku juga.[:
atau@:
dalam urutan sepertiu@v
dengan memilih varianu
yang memiliki argumen kiri. Misalnya, untuk menghapus item pertama dari hasilv
, gunakan1}.v
alih-alih[:}.v
jika}.@v
tidak mungkin karena alasan tertentu.] v
seringkali lebih pendek daripadav@]
jika Anda ingin menggunakan monadikv
dalam konteks diad. Ini sangat berguna terutama ketikav
kata kerja panjang.m (n v w) y
bukan(n v m&w) y
. Ini memungkinkan untuk menghindari spasi dan tanda kurung.#\
dari pada>:@i.@#
.u &. v
berguna ketikav
memiliki bagian depan. Bila tidak, Anda mungkin ingin menggunakannya[: vinv u & v
atauu & (v :. vinv)
sebagai gantinya.^:_
sangat berguna untuk algoritma di mana Anda ingin mencapai konvergensi, seperti mengisi banjir atau simulasi.=.
dan=:
dapat disematkan di mana saja dalam frasa. Gunakan ini untuk membuat satu baris di mana notasi diam-diam tidak cukup.,
alih-alih beberapa pengurangan saat mengurangi array multi-dimensi.sumber
Berhati-hatilah menggunakan loop.
Sementara J memiliki struktur pengulangan (
for. do. end.
,while. do. end.
dan variasi), jika Anda mendapati diri Anda menggunakannya, ada kemungkinan bahwa algoritme Anda tidak sesuai dengan kekuatan golf J dan ada penghematan karakter yang harus dilakukan.^:
konjungsi kekuatan adalah teman Anda. Untuk menjalankan kata kerjax
kali:Jika Anda membutuhkan hasil setiap iterasi dalam daftar:
Anda juga dapat menggunakan
^:
untuk mengeksekusi kata kerja dengan syarat:Gandakan
+:
jika^:
item lebih besar dari 33<]
("0
perubahan peringkat kata kerja sehingga item bekerja pada suatu waktu).sumber
(i.x)
contoh, yaituf^:(<x)
setara denganf^:(i.x)
.Memasukkan
1!:1[1
akan mengambil satu baris input yang diakhiri dengan menekan tombol enter.1!:1[3
akan mengambil sejumlah baris input (diakhiri oleh Ctrl-D di Mac saya, Ctrl-C di Windows).Jika Anda mencoba memasukkan angka, menggunakan
".
akan mengevaluasi string dan mengembalikan daftar angka yang siap dimanipulasi. Jika Anda menerima satu nomor tetapi harus beroperasi pada digit satu per satu,".,.
(terima kasih atas komentar Jan Dvorak untuk ini) atau"."0
akan membagi string menjadi digit yang terpisah:Jika Anda membaca dalam string, cara terpendek untuk mendapatkan daftar string yang terpisah dari kotak adalah dengan menggunakannya
;:
. Ini berfungsi paling baik untuk string yang dipisahkan ruang:sumber
1!:1[2
berhasil (jika ada)?1!:
halaman (saya bukan ahli J) 2 adalah layar, jadi input dari layar tidak masuk akal.2
tidak valid? Saya tidak punya komputer J saya untuk mencobanya saat ini. Di mana saya melihat2
, tepat di bawah catatan tentang1!:1
, itu untuk1!:2
.".
peringkat 1-xx dan,.
selalu menghasilkan array 2D,".,' ',.
(menjahit dengan spasi, ravel dan evaluasi; 8 karakter) dapat diganti dengan adil".,.
(ravel item dan evaluasi; 4 karakter).Menggunakan iterasi untuk menghitung urutan
Biasanya, menyelesaikan tantangan urutan OEIS akan membutuhkan penggunaan salah satu formula yang diberikan pada halamannya. Beberapa di antaranya beradaptasi dengan baik untuk J, dan yang lain tidak begitu banyak. Rumus rekursif bersifat langsung, namun iterasi mungkin tidak sederhana. Pola yang mulai saya gunakan adalah
di mana
s
adalah nilai pertama dalam urutan,f
adalah kata kerja yang akan menghitung istilah berikutnya yang diberikan istilah sebelumnya, dann
merupakan indeks berbasis nol dari istilah yang ingin Anda hitung. Metode ini bergantung pada fakta bahwa ketika menghitung kekuatan angka dua, LHS terikat pada angka dua untuk membentuk monad baru, dan bahwa monad bersarang pada nilai awal. Angka dua yang diberikan pada keterangan daya adalah sebuah kait di mana(]f)
diberikan indeksn
pada LHS dan nilai suatu istilah dalam urutans
. Hook akan berlakuf
padas
sebagai monad, dan kemudian mengabaikann
untuk mengembalikan hasilf s
.Perpustakaan standar
Terkadang, Anda mungkin menemukan bahwa J akan memiliki dukungan untuk kata kerja di perpustakaan standarnya . Sebagai contoh, sebagian besar operasi integer bitwise terikat pada nama yang lebih pendek daripada menggunakan panggilan primitif.
Tanggal dan waktu bawaan juga tersedia.
Kisaran
Jika Anda memiliki seperangkat nilai
[a, b, c]
dan Anda ingin membentuk rentang berdasarkan pada produk mereka seperti[0, 1, 2, ..., a*b*c-1]
, pendekatan khas akan menemukan produk mereka dan kemudian membentuk rentang yang mungkin[:i.*/
biaya 6 byte. Cara yang lebih pendek adalah,@i.
untuk 4 byte sejak itui.
dapat membentuk array multidimensi sambil tetap menghitung, dan meratakannya akan menghasilkan kisaran yang setara.Mencetak terus menerus
Cara diam-diam untuk mencetak nilai dan terus menggunakannya tanpa loop eksplisit adalah
([echo)
untuk kasus monadik.echo
adalah kata kerja di perpustakaan standar yang mencetak isinya kestdout
dalam format yang sama yang digunakan dalam penerjemah. Pengait kemudian mengeluarkan nilai input yang sama menggunakan[
kata kerja kiri .Basis 10 digit bilangan bulat
Cara standar untuk memperoleh basis 10 digit integer adalah
10#.inv]
yang menghabiskan biaya 8 byte, terlalu banyak! Alternatifnya adalah mengonversinya menjadi string dan menguraikannya pada peringkat 0"."0@":
yang menyimpan byte, tetapi cara yang lebih baik adalah,.&.":
yang menyimpan byte lain yang membuat biaya akhir 6 byte bukannya 8.sumber
Pertimbangkan untuk menggunakan definisi eksplisit alih-alih menulis kata kerja diam-diam; Pastikan
3 :'
dan'
biaya 5 byte, tetapi Anda dapat menyimpan banyak@
,@:
dan dengan[:
cara itu.sumber
Beberapa (cukup) trik umum yang pernah saya lihat
Saya berbagi beberapa hal yang berguna bagi saya. Pada dasarnya semua ini adalah tips yang saya terima sendiri, tetapi saya tidak memiliki kredit untuk sebagian besar.
Jumlah array peringkat satu
Alih-alih menggunakan
+/@:(FGH)
gunakan(1#.FGH)
. Ini berarti merendahkan ke basis 1, yang secara efektif berarti menjumlahkan array. Meskipun lebih panjang dari+/
itu, tidak memerlukan penutup atau komposisi, yang sering membuatnya lebih pendek daripada menggunakan+/
.Menghitung kebenaran yang tertinggal
Jika Anda memiliki daftar boolean dan Anda ingin menghitung jumlah trailing truth, gunakan
#.~
. Lihat di sini . The APL Jawaban memberikan penjelasan yang baik untuk bagaimana ini bekerja. Memang, ini hanya membantu saya dua kali tetapi saya pikir saya akan membagikannya.Dibawah (&.)
Bukan trik khusus, tetapi hanya saran umum: kata keterangan
&.
-di bawahnya sering mengarah pada solusi pendek yang elegan dan (lebih penting). Ingatlah saat Anda bermain golf.Sering kali ini berguna untuk tantangan konversi basis biner dan lainnya, mis. Kode ini yang menghilangkan bit paling signifikan dari suatu angka:
}.&.#:
(konversikan ke daftar digit biner, hapus digit pertama, lalu batalkan konversi ke daftar digit biner dan konversi kembali ke desimal). Solusi sederhana adalah dua byte lagi:#.@}.@#:
.Di bawah juga membantu untuk tantangan di mana Anda perlu bekerja dengan angka desimal, karena Anda dapat menggunakannya
u&.":
. Misalnya, cara singkat mil memberikan untuk membagi ke angka desimal menggunakan di bawah:,.&.":
.Contoh terakhir adalah menemukan besarnya vektor:,
+/&.:*:
perhatikan bahwa Anda perlu mengumpulkan semua hasil dari*:
-square dengan&.:
-di bawah karena*:
-square adalah peringkat nol.sumber
Cara yang lebih pendek untuk mengacaukan barisan
Terkadang, Anda akan memiliki kode seperti
<"0 i.3 3
, di mana Anda ingin menerapkan kata kerjav
di peringkatr
. Namun, jika Anda menggunakan kata benda (seperti0
), Anda harus sering memasukkan spasi. Untuk menghindari ini, Anda dapat menggunakan kata kerja lainu
dengan peringkat yang setara dan menggunakanu"v
sebagai gantinya. Misalnya, karena+
memiliki peringkat0 0 0
, kita dapat menggunakannya<"+
sebagai ganti<"0
.Ini adalah tabel dari semua kata kerja dan peringkatnya (dapat diperoleh dengan menggunakan
v b. 0
):Untuk menggunakan tabel ini, temukan peringkat yang diinginkan
r
di sisi kiri, lalu pilih kata kerja yang sesuaiv
dari sisi kanan. Misalnya, jika saya perlu membuat vektor kata kerjav
di kedalaman2 _ 2
, maka saya menemukan peringkat di sebelah kiri dan memilih%.
dari kanan. Maka saya gunakanv"%.
sebagai gantinyav"2 _ 2
.sumber
strings
perpustakaan: tips golfPerpustakaan string sangat membantu untuk melakukan apa pun dengan manipulasi string. Tentu, dibutuhkan
include'strings'
(yang sangat mahal, mengingat J), tetapi Anda kadang-kadang dapat menuai manfaatnya.stringreplace
Menemukan diri Anda menggunakan ganti string? Amati itu
A stringreplace B
sama denganB rplc A
.Sebenarnya, ini cara
rplc
penerapannya:cuts
Kata kerja tersebut
cuts
menyediakan:Jadi itu benar-benar mengiris string.
sumber
Mendapatkan angka dari 0 hingga 4
Jika ada batasan dalam menggunakan angka dalam kode Anda:
0
%_
: satu dibagi dengan tak terbatas.1
#_
: berapa banyak infinitas?2
#_ _
: dua ketidakterbatasan.3
verb
: ada built-in.4
dyad
: built-in lainnya.Mendapatkan angka dari 10 hingga 35
Literal dasar-inifinity: 11 :
_bb
, 26 :_bq
dllsumber
Pemrograman diam-diam
Dasar-dasar
Kata kerja diad
Kata kerja monadik
Lain-lain
Trik
(F x) G (H y)
Solusi diam-diam:
(G~F)~H
; tergantung pada kata kerja aktual, pertimbangkan menata ulang argumen kiri dan kanan untuk dihapus~
.Penggantian Monadic-Dyadic
sumber
(G~F)~H
adalah kebaikan bergelembung murni!&
adalah temanmu, gunakan dengan bijakv
adalah kata kerja,n
adalah kata benda,x
dany
argumen kiri dan kanan, masing-masing.Monad
&
: Perkenalkan~
rantai kata keterangan / konjungsi di dalamKata keterangan / konjungsi mengevaluasi dari kiri. Jadi sesuatu seperti
_2&+/\&.>
tidak akan berfungsi karena diurai seperti yang(_2&+)/\&.>
kita inginkan_2&(+/\)&.>
. Dalam hal ini, menukar kiri / kanan+/\
dapat menyimpan byte, seperti pada+/\~&_2&.>
karena ini diuraikan sebagai((+/\)~)&_2&.>
. Untuk mengetahui mengapa ini berhasil:Angka dua
&
: Ulangix
kaliApakah Anda tahu bahwa jika Anda memberikan argumen kiri
x
untuk&
, fungsi menerapkannyax
kali untuky
? Cukup banyak tantangan meminta Anda untuk melakukan operasi tertentux
waktu . Ini terutama dapat dicapai dengan dua cara:^:
tanpa operan yang benarJika operasi ini
v
, makav^:
menjadi kereta kata keterangan itu, ketika diberi operan kiri, menjadi kata kerja monadik. Begituv
diterapkany
,x
kali.&
sebagai konjungsi terluarUntuk menggunakan ini, Anda perlu mengidentifikasi
n
kata kerja konstan dan diadu
, sehingga keduanyan u y
atauy u n
setara denganv
. Maka Anda dapat menulisn&u
atauu&n
menyelesaikan seluruh tugas. Bentuk ini paling efektif ketika pilihan konstanta jelas, misalnya 3 in3 u:
(konversi karakter ke nilai ASCII).Juga,
u&n
sedikit lebih disukai daripadan&u
ketika struktur terluaru
adalah konjungsi atau kata keterangan (dalam hal inin&u
harusn&(u)
; Anda dapat melakukanu~&n
sebagai gantinya).Perhatikan bahwa Anda dapat menempatkan diad
&
di mana saja di dalam kereta untuk mencapai fungsi arbitrer berulang ke argumen arbitrer, dalam arti yang sama dengan dinamis^:
.sumber