Tips umum apa yang Anda miliki untuk bermain golf di Julia? Saya mencari ide yang dapat diterapkan pada masalah kode golf secara umum yang setidaknya agak spesifik untuk Julia (mis. "Hapus komentar" bukan jawaban).
Tips umum apa yang Anda miliki untuk bermain golf di Julia? Saya mencari ide yang dapat diterapkan pada masalah kode golf secara umum yang setidaknya agak spesifik untuk Julia (mis. "Hapus komentar" bukan jawaban).
Jawaban:
CATATAN: Di bawah ini mungkin berisi beberapa tips yang sudah ketinggalan zaman, karena Julia belum cukup stabil dalam hal struktur, belum.
Beberapa trik untuk menyimpan beberapa karakter
\ =div, dan Anda kemudian dapat mengetik a\bbukan div(a,b). Perhatikan ruang - ini diperlukan untuk menghindari penguraian sebagai operator "\ =". Juga perhatikan bahwa, jika kelebihan beban pada level REPL prompt, gunakan (\)=Base.(\)atau \ =Base. \untuk meresetnya. CATATAN: beberapa fungsi memiliki operator UTF-8 yang sudah ditentukan sebelumnya, seperti ÷untuk div, seperti yang dicatat oleh Alex A.a>0?"Hi":"", gunakan "Hi"^(a>0)untuk menyimpan satu byte, atau untuk boolean a, gunakan "Hi"^auntuk menyimpan tiga byte.a=split("Hi there"," "), Anda mungkin dapat menghindari a[1]dan a[2]menggunakan a,b=split("Hi there"," "), yang dapat dirujuk sebagai adan b, menghemat tiga byte untuk setiap penggunaan, dengan biaya hanya dua karakter tambahan saat penugasan. Jelas, jangan lakukan ini jika Anda dapat bekerja dengan operasi vektor.[] - untuk array, ekspresi A[]sama dengan A[1]. Perhatikan bahwa ini tidak berfungsi untuk Strings jika Anda ingin mendapatkan karakter pertama, atau untuk Tuples.==[]untuk array dan ==()untuk tuple; sama halnya, untuk yang negatif, gunakan !=[]dan !=(). Untuk string, gunakan ==""untuk kosong, tetapi gunakan >""untuk tidak-kosong, karena "" secara leksikografis sebelum string lain.x<=1&&"Hi"dapat ditulis sebagai x>1||"Hi", menyimpan karakter (selama kembalinya boolean tidak penting).in('^',s)daripada contains(s,"^"). Jika Anda dapat menggunakan karakter lain, Anda dapat menyimpan sedikit lebih banyak dengan '^'∈s, tetapi perhatikan bahwa ∈3 byte di UTF-8.minimum(x)atau maximum(x), menggunakan min(x...)atau max(x...), untuk mencukur satu karakter dari kode Anda, jika Anda tahu xakan memiliki setidaknya dua elemen. Atau, jika Anda tahu semua elemen xakan non-negatif, gunakan minabs(x)ataumaxabs(x)r"(?m)match^ this", mengetik r"match^ this"m, menyimpan tiga karakter.reverse(x)lebih panjang satu byte daripada flipud(x)dan akan melakukan operasi yang sama, sehingga yang terakhir lebih baik.{[1,2]}, tidak {1,2}) - untuk Julia 0.4, Anda perlu Any[[1,2]].enddalam pengindeksan array, secara otomatis akan dikonversi ke panjang array / string. Jadi alih-alih k=length(A), gunakan A[k=end]untuk menyimpan 3 karakter. Perhatikan bahwa ini mungkin tidak bermanfaat jika Anda ingin segera menggunakan k. Ini juga berfungsi dalam kasus multidimensi - A[k=end,l=end]akan mendapatkan ukuran setiap dimensi A- namun, (k,l)=size(A)lebih pendek satu byte dalam kasus ini, jadi gunakan hanya jika Anda ingin segera mengakses elemen terakhir pada saat yang sama.A[k=1:end], dalam hal ini kakan memegang pencocokan iterator 1:length(A). Ini bisa berguna ketika Anda ingin juga menggunakan array Apada saat yang bersamaan.collect(A), gunakan [A...], yang akan melakukan hal yang sama dan menyimpan 4 byte."$(s[i])"atau dec(s[i])untuk ekspresi atau variabel multi-karakter, dan "$i"untuk variabel-karakter tunggal.?:alih-alih &&atau ||untuk penugasan bersyarat - yaitu, jika Anda ingin melakukan penugasan hanya pada kondisi tertentu, Anda dapat menyimpan satu byte dengan menulis cond?A=B:1daripada cond&&(A=B), atau cond?1:A=Bbukannya cond||(A=B). Perhatikan bahwa 1, di sini, adalah nilai dummy.unionatau ∪bukannyaunique - union(s)akan melakukan hal yang sama seperti unique(s), dan menyimpan byte dalam proses. Jika Anda dapat menggunakan karakter non-ASCII, maka ∪(s)akan melakukan hal yang sama, dan ∪hanya biaya 3 byte, bukan 5 byte union.split("Hi there")karena argumen pola default ke spasi.
Mendefinisikan ulang operator dapat menyimpan banyak byte dalam tanda kurung dan koma.
Sebagai contoh unary, bandingkan implementasi rekursif dari urutan Fibonacci berikut:
F(n)=n>1?F(n-1)+F(n-2):n # 24 bytes
!n=n>1?!~-n+!(n-2):n # 20 bytes
!n=n>1?!~-n+!~-~-n:n # 20 bytes
Operator yang didefinisikan ulang mempertahankan prioritas awal.
Perhatikan bahwa kita tidak bisa sekadar bertukar !demi ~, karena ~sudah ditentukan untuk bilangan bulat, sementara !hanya ditentukan untuk Boolean.
Bahkan tanpa rekursi, mendefinisikan ulang operator lebih pendek daripada mendefinisikan fungsi biner. Bandingkan definisi tes keterpisahan sederhana berikut.
f(x,y)=x==0?y==0:y%x==0 # 23 bytes
(x,y)->x==0?y==0:y%x==0 # 23 bytes
x->y->x==0?y==0:y%x==0 # 22 bytes
x\y=x==0?y==0:y%x==0 # 20 bytes
Berikut ini menggambarkan cara mendefinisikan ulang operator biner untuk menghitung fungsi Ackermann:
A(m,n)=m>0?A(m-1,n<1||A(m,n-1)):n+1 # 35 bytes
^ =(m,n)->m>0?(m-1)^(n<1||m^~-n):n+1 # 36 bytes
| =(m,n)->m>0?m-1|(n<1||m|~-n):n+1 # 34 bytes
m\n=m>0?~-m\(n<1||m\~-n):n+1 # 28 bytes
Perhatikan bahwa ^ini lebih lama daripada menggunakan pengenal biasa, karena prioritasnya terlalu tinggi.
Seperti disebutkan sebelumnya
m|n=m>0?m-1|(n<1||m|~-n):n+1 # 28 bytes
tidak akan berfungsi untuk argumen integer, karena |sudah ditentukan dalam kasus ini. Definisi untuk bilangan bulat dapat diubah dengan
m::Int|n::Int=m>0?m-1|(n<1||m|~-n):n+1 # 38 bytes
tapi itu terlalu lama. Namun, tidak bekerja jika kita melewati pelampung sebagai argumen kiri dan integer sebagai argumen yang tepat.
Jangan terlalu mudah tergoda oleh faktor (n) Fungsi pustaka basis yang menggoda factor(n)memiliki kelemahan fatal: ia mengembalikan faktorisasi bilangan bulat Anda dalam Dicttipe yang tidak berurutan . Dengan demikian, itu memerlukan biaya collect(keys())dan collect(values())dan berpotensi juga a catdan a sortuntuk mendapatkan data yang Anda inginkan. Dalam banyak kasus, mungkin lebih murah untuk hanya faktor dengan pembagian percobaan. Sedih, tapi benar.
Gunakan peta map adalah alternatif yang bagus untuk perulangan. Waspadai perbedaan antara mapdan map!dan manfaatkan fungsionalitas in-place yang terakhir ketika Anda bisa.
Gunakan mapreduce mapreduce memperluas fungsionalitas peta lebih jauh dan bisa menjadi byte-saver yang signifikan.
Fungsi anonim sangat bagus! ..terutama ketika diteruskan ke mapfungsi yang disebutkan di atas .
Fungsi array kumulatif cumprod , cumsum, yang beraroma cummindan fungsi lainnya bernama sama memungkinkan operasi kumulatif sepanjang dimensi tertentu dari sebuah array n-dimensi. (Atau * tidak * ditentukan jika arraynya 1-d)
Notasi singkat untuk Apa saja Ketika Anda ingin memilih semua dimensi tertentu dari array multi-dimensi (atau Diktik), misalnya A[Any,2], Anda dapat menyimpan byte dengan menggunakanA[:,2]
Gunakan notasi satu-baris untuk fungsi, alih-alih function f(x) begin ... endAnda sering dapat menyederhanakannyaf(x)=(...)
Gunakan operator ternary. Ini bisa menjadi penghemat ruang untuk konstruksi ekspresi If-Then-Else ekspresi tunggal. Peringatan: Meskipun mungkin dalam beberapa bahasa lain, Anda tidak dapat menghilangkan bagian setelah titik dua di Julia. Selain itu, operator adalah level ekspresi dalam Julia, jadi Anda tidak dapat menggunakannya untuk eksekusi kode blok secara keseluruhan.
if x<10 then true else false endvs.
x<10?true:false
Ini juga dimungkinkan dalam bahasa lain, tetapi biasanya lebih lama dari metode yang sederhana. Namun, kemampuan Julia untuk mendefinisikan kembali operator unary dan biner membuatnya cukup golf.
Misalnya, untuk menghasilkan tabel penambahan, pengurangan, perkalian, dan pembagian untuk bilangan asli dari 1 hingga 10, orang dapat menggunakan
[x|y for x=1:10,y=1:10,| =(+,-,*,÷)]
yang telah mengubah biner Operator |sebagai +, -, *dan ÷, kemudian menghitung x|yuntuk setiap operasi dan xdan ydalam rentang yang diinginkan.
Ini juga berfungsi untuk operator unary. Misalnya, untuk menghitung bilangan kompleks 1 + 2i , 3-4i , -5 + 6i dan -7-8i , negatifnya, konjugat kompleksnya dan inversi multiplikatifnya, orang dapat menggunakan
[~x for~=(+,-,conj,inv),x=(1+2im,3-4im,-5+6im,-7-8im)]
yang telah mengubah unary operator yang ~sebagai +, -, conjdan inv, kemudian menghitung ~xuntuk semua bilangan kompleks yang diinginkan.
Urutan Perempuan dan Laki-laki (biner)
Permutasi Kasus (unary)
Kata kunci terkadang dapat langsung mengikuti konstanta tanpa perlu spasi atau titik koma. Sebagai contoh:
n->(for i=1:n n-=1end;n)
Perhatikan kurangnya ruang antara 1dan end. Ini juga berlaku untuk endterjadi setelah paren dekat, yaitu )end.
Lakukan pembagian integer menggunakan ÷alih - alih div()atau kelebihan operator. Perhatikan bahwa ÷bernilai 2 byte dalam UTF-8.
Gunakan vec()atau A[:](untuk beberapa larik A) daripada reshape()bila memungkinkan.
Buat fungsi daripada program lengkap bila diizinkan dalam aturan tantangan. Lebih pendek untuk mendefinisikan fungsi yang menerima input daripada mendefinisikan variabel dengan membaca dari stdin. Sebagai contoh:
n->(n^2-1)
n=read(STDIN,Int);n^2-1Variabel dapat ditambahkan di dalam argumen ke fungsi. Misalnya, berikut ini adalah jawaban saya untuk tantangan Find the Binary Number 1-Sparse Next :
n->(while contains(bin(n+=1),"11")end;n)
Ini lebih pendek daripada menambah nbagian dalam loop.
Diperkenalkan di Julia 0.5. Itu seperti peta, tetapi menggunakan lebih sedikit karakter, dan tidak menyiarkan perilaku di atas itu args - yang berarti Anda dapat menulis lebih sedikit lambda untuk menangani hal-hal.
Daripada:
map(f,x) - 8 karakter.f.(x) - 5 karakterLebih baik lagi:
map(a->g(a,y),x) - 16 karakterg.(x,[y]) - 9 karakter