Apa tips umum yang Anda miliki untuk bermain golf di Mathematica? Saya mencari ide yang dapat diterapkan pada masalah kode golf secara umum yang setidaknya agak spesifik untuk Mathematica (mis. "Hapus komentar" bukan jawaban).
Kiat di bawah ini bervariasi dari yang paling ekonomis hingga yang paling sering digunakan:
Gunakan perintah tingkat tinggi Mathematica jika memungkinkan, bahkan yang besar:
MorphologicalComponents
: Code-Golf: Count Islands
Kemampuan manipulasi gambar: mis. Hari ini (24 September) adalah ulang tahun HONDA
Subsets
IntegerPartitions
Ukuran Jarak dan Kesamaan: misalnya EuclideanDistance
bisa menjadi byte saver. Namun perlu dicatat, bahwa biasanya lebih pendek untuk menulis Total@Abs[a-b]
daripada a~ManhattanDistance~b
dan Max@Abs[a-b]
bukan a~ChessboardDistance~b
.
Gunakan Graphics and
Text
untuk seni Ascii: mis. Pemrograman bintang!
dan Bangun jam analog
Simbol khusus:
logika dan tetapkan simbol operasi alih-alih nama panjangnya: ⋂, ⋃, ∧, ∨
Map
dan Apply
: /@
, //@
. @@
,@@@
Awalan dan infiks notasi:
Print@"hello"
di tempat Print["hello"]
a~f~b
di tempat f[a,b]
Ketika suatu fungsi hanya digunakan sekali, fungsi murni dapat menghemat satu atau dua karakter.
Menggabungkan string dalam daftar. ""<>{"a","b","c"}
dari padaStringJoin@{"a","b","c"}
Memanfaatkan fungsi yang dapat didaftarkan. Semakin lama daftar semakin baik.
{a, b, c} + {x, y, z}= {a+x, b+y, c+z}
{2, 3, 4} {5, 6, 7}= {10, 18, 28}
{{a, b}, {c, d}}^{2, 3} = {{a^2, b^2}, {c^3, d^3}}
(Norm[#-#2]&)
daripada menulisEuclideanDistance
.Beberapa fungsi bawaan dengan nama panjang dapat diganti dengan ekspresi yang lebih pendek.
Sebagai contoh:
Total
=>Tr
Transpose
=>Thread
atau\[Transpose]
True
=>1<2
False
=>1>2
Times
=>1##&
Alternatives
=>$|##&
IntegerQ
=>⌊#⌋==#&
a[[1]]
=>#&@@a
a[[All,1]]
=>#&@@@a
ConstantArray[a,n]
=>Array[a&,n]
atauTable[a,{n}]
Union@a
=>{}⋃a
ataua⋃a
ToExpression@n
=>FromDigits@n
jikan
adalah angkaDivisible[n,m]
=>m∣n
FromDigits[n,2]
=>Fold[#+##&,n]
jikan
daftar0
s dan1
sComplex@z
=> di{1,I}.z
manaz
daftar formulir{x,y}
sumber
Thread[{{a,b},{c,d}}]
==Thread[List[{a,b},{c,d}]]
=={List[a,c],List[b,d]}
=={{a,c},{b,d}}
==Transpose[{{a,b},{c,d}}]
Fold
trik Anda untukFromDigits
juga berfungsi untuk pangkalan lain kecuali10
. MisalnyaFromDigits[n,5]
->Fold[4#+##&,n]
(dengan bonus menyimpan byte tambahan untuk basis100
dan1000
).U+F3C7
.Echo
itu pilihan, karena ia mencetak>>
(dan spasi) untuk STDOUT sebelum mencetak string yang sebenarnya.Complex[x,y] => {1,I}.{x,y}
, saya pikirx+y*I
jauh lebih pendek dengan efek yang sama?Daftar dengan nilai berulang
Ini adalah vektor yang cukup umum untuk digunakan:
Ternyata ini dapat disingkat dengan byte:
Bahkan lebih banyak byte disimpan jika vektor lebih panjang dari dua nol. Ini juga dapat digunakan untuk menginisialisasi nol matriks, misalnya yang berikut ini memberikan matriks 2x2 nol:
Ini juga dapat digunakan untuk nilai-nilai non-nol jika cukup besar atau cukup banyak atau negatif. Bandingkan pasangan berikut:
Tetapi ingat bahwa mulai dari 6 nilai, Anda lebih baik
1~Table~6
dalam hal ini (berpotensi lebih awal, tergantung pada persyaratan diutamakan).Alasan ini berhasil adalah yang
,
memperkenalkan dua argumen ke daftar, tetapi argumen yang dihilangkan (di mana saja di Mathematica) adalahNull
s implisit . Selanjutnya, perkalianListable
, dan0*x
merupakan0
untuk hampir semuax
(kecuali untuk hal-hal sepertiInfinity
danIndeterminate
), jadi di sini adalah apa yang terjadi:Untuk daftar
1
s, Anda dapat menggunakan trik serupa dengan memanfaatkan aturan eksponensial. Ada dua cara berbeda untuk menghemat byte jika Anda memiliki setidaknya tiga1
s dalam daftar:sumber
1^{,,,}
satu byte lebih kecil dari0{,,,}+1
.{,,}^0
. Saya akan mengedit posting.Ketahui argumen fungsi murni Anda
Saat kode golf, Anda akan sering menggunakan pendekatan fungsional, di mana Anda menggunakan fungsi anonim (murni) dengan
&
sintaks steno. Ada banyak cara berbeda untuk mengakses argumen dari fungsi seperti itu, dan Anda sering dapat memotong beberapa byte dengan memiliki pemahaman yang baik tentang kemungkinan.Mengakses argumen tunggal
Anda mungkin tahu ini jika Anda pernah menggunakan fungsi murni sebelumnya. The n Argumen th disebut sebagai
#n
, dan#
bertindak sebagai alias untuk#1
. Jadi jika, katakanlah, Anda ingin menulis fungsi yang mengambil parameter fungsi lain dan argumennya (untuk meneruskan argumen ke fungsi itu), gunakanIni tidak berfungsi dengan angka negatif (seperti yang mungkin Anda gunakan saat mengakses daftar).
Mengakses argumen bernama (baru dalam V10)
Salah satu fitur utama bahasa baru di Mathematica 10 adalah
Association
s, yang pada dasarnya adalah peta nilai-kunci dengan jenis kunci acak, ditulis sepertiJika asosiasi seperti itu diteruskan sebagai argumen pertama ke fungsi murni, Anda dapat mengakses beberapa jika argumennya sebagai parameter bernama:
Perhatikan bahwa
#
masih merujuk ke seluruh asosiasi seperti yang diharapkan. Agar parameter yang dinamai berfungsi, kunci harus berupa string (tidak akan berfungsi jika Anda menggunakan variabel yang tidak ditentukan misalnya), dan string tersebut harus dimulai dengan huruf dan hanya berisi huruf dan angka.Argumen "diri"
#0
Fitur yang kurang dikenal adalah yang
#0
juga ada, dan memberi Anda objek fungsi itu sendiri. Ini bisa sangat berguna dalam quines dan quines umum. Bahkan, Quine Mathematica terpendek (saya tahu) adalahYang sedikit menjengkelkan adalah bahwa itu tidak akan memberi Anda karakter tepat yang Anda masukkan. Misalnya jika digunakan
@
untuk aplikasi fungsi, masih akan di-render[...]
dan spasi akan dimasukkan di beberapa tempat. Ini biasanya akan membuat quine sedikit lebih lama dari yang Anda inginkan, tetapi akan selalu berhasil, dengan mem-golf quine terlebih dahulu, dan kemudian hanya menyalin outputnya - yang sekarang seharusnya menjadi quine nyata.Terlepas dari quines, ini juga berarti bahwa Anda dapat menulis kode rekursif tanpa harus menyebutkan nama fungsi Anda. Bandingkan tiga implementasi Fibonacci (naif tapi golf) ini:
Urutan argumen
Sekarang di sinilah keajaiban yang sebenarnya dimulai. Urutan tidak sering digunakan dalam bermain golf, karena nama
Sequence
itu terlalu panjang untuk menjadi layak untuk sebagian besar waktu. Tetapi dalam fungsi murni adalah di mana mereka bersinar. Jika Anda tidak terbiasa dengan urutan, mereka pada dasarnya seperti percikan dalam beberapa bahasa lain, jika Anda menggunakan urutan dalamList
atau daftar argumen fungsi, elemen-elemennya akan secara otomatis diperluas ke slot yang terpisah. BegituSekarang, dalam fungsi murni
##
atau##1
merupakan urutan dari semua argumen. Demikian juga,##2
merupakan urutan semua argumen mulai dari kedua,##3
semua argumen mulai dari dll Jadi ketiga untuk memulai, kita hanya bisa reimplementSequence
sebagai##&
, tabungan 5 byte. Sebagai contoh penggunaan, ini memberi kami alternatif untukJoin@@list
(lihat tip ini ), yang tidak menyimpan byte apa pun, tetapi bagaimanapun juga baik untuk diketahui:Ini secara efektif meratakan tingkat pertama dari daftar bersarang. Apa lagi yang bisa kita lakukan dengan ini? Berikut adalah alternatif 2 byte lebih pendek untuk
RotateLeft
:Untuk hal-hal ini saja, ada baiknya mengingat fitur ini. Namun, kita bisa berbuat lebih baik! Urutan menjadi sangat menarik ketika mempertimbangkan bahwa operator sebenarnya diimplementasikan sebagai fungsi di bawah kap. Misalnya
a+b
sebenarnya mengevaluasiPlus[a,b]
. Jadi jika kita memberi urutan ...Trik ini telah digunakan dalam tip ini untuk menghemat byte
Times
, karena penjajaran secara teknis juga hanya operator:Anda juga dapat menggunakannya untuk menyimpan byte
Unequal
jika Anda memiliki nilai karakter tunggal atau variabel yang Anda tahu tidak ada dalam argumen Anda (N
mungkin akan bekerja di 99% kasus):Ini menjadi lebih menarik dengan operator yang tidak dikenal dan
-
dan/
- dua yang terakhir sebenarnya diimplementasikan dalam hal penggandaan dan eksponensial. Berikut adalah daftar hal-hal yang dapat Anda lakukan, di mana kolom terakhir mengasumsikan bahwa fungsi telah melewati argumena, b, c
:Operator umum lainnya adalah
!=
,==
,&&
,||
. Yang kurang umum untuk diingat adalah|
,@*
,/*
. Untuk menyimpulkan, berikut adalah trik bonus kecil:Terus bereksperimen dengan ini, dan beri tahu saya jika Anda menemukan aplikasi lain yang bermanfaat atau sangat menarik!
sumber
Sqrt@2
atau2^.5
=>√2
a[[1]]
=>a〚1〛
#+#2&
=>+##&
Flatten@a
=>Join@@a
(terkadang)Function[x,x^2]
=>xx^2
atau#^2&
a〚1;;-1;;2〛
=>a〚;;;;2〛
a〚2;;-1 ;;2〛
=>a〚2;;;;2〛
a〚All,1〛
=>a〚;;,1〛
{{1}}〚1,1〛
=>Tr@{{1}}
0&~Array~10
=>0Range@10
Range[10^3]
=>Range@1*^3
sumber
〚
dan〛
mengambil masing-masing 3 byte (asumsikan UTF8)Operator sebagai Fungsi
Terinspirasi oleh penemuan Dennis untuk Julia baru-baru ini, saya pikir saya akan mencari di dalam untuk Mathematica. Saya sadar bahwa Mathematica mendefinisikan sejumlah besar operator yang tidak digunakan, tetapi tidak pernah memperhatikannya.
Untuk referensi, daftar semua operator dapat ditemukan di sini dalam bentuk tabel prioritas. Segitiga pada kolom terakhir menunjukkan apakah operator memiliki makna bawaan atau tidak. Meskipun tidak semua dari mereka yang tidak dapat didefinisikan dengan mudah, kebanyakan dari mereka bisa.
Mudahnya, ada dua operator yang tidak digunakan dengan codepoint kurang dari 256, sehingga mereka dapat digunakan sebagai byte tunggal dalam file sumber yang disandikan ISO 8859-1:
±
(0xB1) dapat digunakan sebagai operator awalan unary atau operator infiks biner.·
(0xB7) dapat digunakan sebagai operator infiks variadic atau n-ary, untuk n> 2.Namun ada satu lagi tangkapan: untuk beberapa alasan aneh ketika mendefinisikan operator ini Anda perlu satu ruang di depan mereka, atau Mathematica mencoba mengurai perkalian. Saat menggunakannya, Anda tidak memerlukan spasi:
Bandingkan ini dengan:
Jadi ini menghemat satu byte saat mendefinisikan fungsi dan dua byte saat menggunakannya. Perhatikan bahwa definisi
·
tidak akan menghemat byte untuk empat operan dan akan mulai menentukan biaya byte untuk lebih banyak operan, tetapi penggunaannya mungkin masih menyimpan byte, tergantung pada prioritas operator yang digunakan dalam argumen. Ini juga baik untuk dicatat bahwa Anda dapat dengan murah mendefinisikan fungsi variadic yang kemudian dapat disebut lebih efisien:Tetapi perhatikan bahwa tidak mudah untuk memanggil fungsi variadic ini dengan satu argumen. (Anda bisa melakukannya
CenterDot[x]
atau##&[]·x
tetapi jika Anda benar-benar membutuhkannya, ada peluang bagus Anda lebih baik dengan solusi yang berbeda.)Tentu saja, ini tidak menyimpan apa pun untuk solusi di mana fungsi yang tidak disebutkan namanya mencukupi, tetapi kadang-kadang Anda perlu mendefinisikan fungsi pembantu untuk digunakan nanti, dan kadang-kadang lebih pendek untuk menentukan fungsi yang disebutkan misalnya untuk mengatur definisi yang berbeda untuk parameter yang berbeda. Dalam kasus tersebut, menggunakan operator sebagai gantinya dapat menghemat jumlah byte yang layak.
Perhatikan bahwa menggunakan file yang disandikan ISO 8859-1 ini
$CharacterEncoding
harus diatur ke nilai yang kompatibel, seperti standar WindowsWindowsANSI
. Pada beberapa sistem, default iniUTF-8
tidak dapat membaca poin kode ini dari satu byte.sumber
Memilih nilai berdasarkan integer
Pendekatan naif untuk memilih antara
y
danz
, tergantung pada apakahx
adalah0
atau1
merupakanNamun, ada cara yang lebih singkat:
Ini berfungsi karena
[[0]]
memberikanHead
ekspresi, dalam hal iniy
, sedangkan[[1]]
hanya memberikan elemen pertama - dalam hal ini argumen pertamaz
,.Anda bahkan dapat menggunakan ini untuk memilih antara lebih dari dua nilai:
Perhatikan bahwa ini tidak akan berfungsi jika
u
fungsi yang sebenarnya mengevaluasi sesuatu. Penting agar Mathematica tetapu[v,w]
seperti itu. Namun, ini berfungsi dalam kebanyakan kasus, termasuk jikau
adalah angka, string atau daftar.Penghargaan untuk trik ini diberikan ke alephalpha - Saya menemukan ini dalam salah satu jawabannya.
Jika
x
berbasis 1 dan bukan berbasis nol, gunakan sajaatau
Dalam beberapa kasus yang jarang terjadi, Anda bahkan dapat menggunakan fakta bahwa perkalian tidak dievaluasi untuk beberapa nilai:
Catat bahwa Mathematica sebenarnya akan menyusun ulang argumen, dari perkalian jika tetap tidak dievaluasi, sehingga hal di atas identik dengan
sumber
Alternatif untuk
Length
Ini sepenuhnya ditulis ulang dengan beberapa saran dari LegionMammal978 dan Misha Lavrov. Terima kasih banyak untuk mereka berdua.
Dalam banyak kasus,
Length
dapat dipersingkat sedikit dengan memanfaatkanTr
. Ide dasarnya adalah mengubah input menjadi daftar1
s, sehinggaTr
meringkasnya yang kemudian akan sama dengan panjang daftar.Cara paling umum untuk melakukan ini adalah menggunakan
1^x
(untuk daftarx
). Ini bekerja karenaPower
merupakanListable
dan1^n
untuk sebagian besar nilai-nilai atomn
hanya1
(termasuk semua nomor, string dan simbol). Jadi kita sudah bisa menyimpan satu byte dengan ini:Tentu saja, ini mengasumsikan bahwa
x
ini adalah ekspresi dengan prioritas lebih tinggi daripada^
.Jika
x
hanya berisi0
s dan1
s, kita dapat menyimpan byte lain menggunakanFactorial
(dengan asumsix
memiliki prioritas lebih tinggi daripada!
):Dalam beberapa kasus yang jarang terjadi,
x
mungkin memiliki prioritas lebih rendah daripada^
tetapi masih lebih tinggi daripada multiplikasi. Dalam hal ini juga akan memiliki prioritas lebih rendah daripada@
, jadi kita benar-benar perlu membandingkanLength[x]
. Contoh dari operator tersebut adalah.
. Dalam kasus tersebut, Anda masih dapat menyimpan byte dengan formulir ini:Akhirnya, beberapa komentar tentang jenis daftar ini berfungsi:
Seperti disebutkan di atas, ini berfungsi pada daftar datar yang hanya berisi angka, string, dan simbol. Namun, ini juga akan bekerja pada beberapa daftar yang lebih dalam, meskipun sebenarnya menghitung sesuatu yang sedikit berbeda. Untuk array n -D persegi panjang, menggunakan
Tr
memberi Anda dimensi terpendek (bukan yang pertama). Jika Anda tahu bahwa dimensi terluar adalah yang terpendek, atau Anda tahu mereka semua sama, daripadaTr
-ekspresi masih setaraLength
.sumber
Length@x == Tr[1^x]
. Harus bekerja dengan sebagian besar daftar.Tr[x!]
alih-alihTr[1^x]
menyimpan satu byte dalam kasus khusus di manax
hanya berisi nol dan satu.Jelajahi solusi rekursif - Mathematica adalah multi-paradigma, tetapi pendekatan fungsional sering kali paling ekonomis.
NestWhile
bisa menjadi solusi yang sangat kompak untuk mencari masalah,NestWhileList
danFoldList
sangat kuat ketika Anda perlu mengembalikan atau memproses hasil iterasi menengah.Map (/@)
,Apply (@@, @@@)
,MapThread
, Dan benar-benar segala sesuatu di Wolfram Pemrograman Fungsional halaman dokumentasi adalah hal yang ampuh.Formulir singkat untuk kenaikan / penurunan - Misalnya, alih-alih
While[i<1,*code*;i++]
yang dapat Anda lakukanWhile[i++<1,*code*]
Jangan lupa Anda bisa melakukan pra-kenaikan / penurunan - Misalnya,
--i
alih-alihi--
. Ini kadang-kadang dapat menghemat beberapa byte dalam kode di sekitarnya dengan menghilangkan operasi persiapan.Akibat wajar terhadap David Carraher's # 5: Ketika fungsi yang sama digunakan berkali-kali, menetapkan simbol untuk itu dapat menghemat byte. Misalnya, jika Anda menggunakan
ToExpression
4 kali dalam suatu solusi,t=ToExpression
memungkinkan Anda untuk menggunakannyat@*expression*
setelahnya. Namun, sebelum Anda melakukan ini pertimbangkan apakah aplikasi berulang dari fungsi yang sama menunjukkan peluang untuk pendekatan rekursif yang lebih ekonomis.sumber
MapThread
sering dapat diganti dengan\[Transpose]
. TIO .Jangan gunakan
{}
jika Anda menggunakan@@@
.Dalam beberapa kasus, Anda mungkin menemukan ekspresi seperti:
Dimungkinkan untuk mengurangi byte dengan menulis:
Alternatives
memiliki prioritas yang sangat rendah, jadi biasanya tidak apa-apa untuk menulis ekspresi (pengecualian penting adalah fungsi murni; Anda dapat menggunakannya hanya di elemen paling kiriAlternatives
).Perhatikan bahwa
f@@a|b|c
(bukannyaf@@{a,b,c}
) tidak berfungsi karenaApply
memiliki prioritas lebih tinggi daripadaAlternative
.Dalam hal ini, Anda cukup menggunakan
f@@{a,b,c}
.sumber
Matematika 10 saja
Formulir operator
Mathematica 10 mendukung apa yang disebut "bentuk-bentuk operator", yang pada dasarnya berarti beberapa fungsi dapat dijelajahi. Currying suatu fungsi adalah membuat fungsi baru dengan memperbaiki salah satu operatornya. Katakanlah, Anda menggunakan
SortBy[list, somereallylongfunction&]
banyaklist
s berbeda . Sebelumnya, Anda mungkin akan ditugaskanSortBy
untuks
dan fungsi murni untukf
jadiSekarang Anda bisa menjilat
SortBy
, yang artinya sekarang bisa Anda lakukanKarya-karya yang sama untuk banyak fungsi lainnya, yang mengambil daftar atau fungsi argumen, termasuk (namun tidak terbatas pada)
Select
,Map
,Nearest
, dllybeltukov ke atas di Mathematica.SE mampu menghasilkan daftar lengkap ini :
Komposisi dan Komposisi Kanan
Ada singkatan baru untuk
Composition
(@*
) danRightComposition
(/*
). Contoh yang jelas dibuat di mana ini dapat menyimpan karakter terlihat dalam tiga baris setara berikutsumber
Jangan menulis fungsi 0-argumen
Tidak perlu kode seperti ini:
Anda cukup menggunakan variabel dengan
:=
untuk memaksa evaluasi ulang dari sisi kanan:Ini juga berarti bahwa Anda dapat alias tindakan apa pun yang sering Anda lakukan (bahkan jika itu hanya sesuatu seperti
n++
) ke satu karakter dengan biaya 5 byte. Jadi dalam kasusn++
itu membayar kembali setelah penggunaan keempat:sumber
Gunakan
%
untuk mendapatkan variabel gratisTip ini hanya berlaku jika lingkungan REPL Mathematica dapat diasumsikan.
%
tidak ditentukan ketika kode dijalankan sebagai skrip.Saat Anda dapat menggunakan fitur REPL, jangan lakukan ini:
Sebagai gantinya, ingatlah bahwa Mathematica menyimpan ekspresi yang terakhir dievaluasi (diakhiri baris) di
%
:Baris baru yang ditambahkan biaya satu byte, tetapi Anda menyimpan dua dengan menghapus
a=
, jadi secara keseluruhan ini menghemat satu byte.Dalam beberapa kasus (mis. Ketika Anda ingin mencetak nilai
a
toh), Anda bahkan dapat mengabaikannya;
, menghemat dua byte:Satu atau dua byte mungkin terlihat agak kecil, tetapi ini merupakan kasus penting, karena itu membuat ekstraksi ekspresi berulang (yang merupakan teknik yang sangat umum) jauh lebih berguna ketika bermain golf:
Teknik normal mengekstraksi ekspresi berulang menghabiskan empat byte overhead, yang perlu dihemat dengan penggunaan ekspresi lebih lanjut. Berikut adalah tabel pendek dari jumlah minimum penggunaan ekspresi (dengan panjang ekspresi) untuk ekstraksi ke variabel bernama untuk menyimpan apa pun:
Dengan menggunakan variabel yang tidak disebutkan namanya, akan lebih mungkin untuk menyimpan beberapa byte lebih sering:
Saya tidak berpikir
%%
atau tidak%n
bisa digunakan untuk bermain golf, karena jika Anda tidak menggunakannya setidaknya dua kali, Anda bisa meletakkan ekspresi tepat di tempat yang dibutuhkan. Dan jika Anda menggunakannya dua kali, karakter tambahan dalam nama variabel membatalkan penghematan dari menghilangkan beberapax=
.sumber
Memeriksa apakah daftar diurutkan
Ini pada dasarnya adalah akibat wajar dari tip ini, tetapi ini adalah tugas yang cukup umum yang saya pikir itu menjamin jawabannya sendiri.
Cara naif untuk memeriksa apakah suatu daftar harus digunakan
Kita dapat melakukan satu byte dengan lebih baik
Namun, ini tidak berfungsi jika kita belum memiliki hal yang ingin kita periksa di variabel. (Kami membutuhkan sesuatu
Sort[a=...]==a
yang panjangnya tidak perlu.) Namun, ada opsi lain:Yang terbaik adalah ini dapat digunakan untuk memeriksa apakah input diurutkan terbalik untuk jumlah byte yang sama:
Satu byte lagi dapat disimpan jika a) kita tahu bahwa elemen daftar berbeda dan b) kita tahu batas bawah antara 0 dan 9 (termasuk; atau batas atas untuk urutan diurutkan terbalik):
Untuk mengetahui mengapa ini berhasil, lihat "Urutan argumen" di ujung yang ditautkan di atas.
sumber
##>0&@@a
. Mirip untuk batas atas untuk diurutkan.Mengulang sebuah string
Alih-alih
StringRepeat[str,n]
digunakan(0Range[n]+str)<>""
. Atau jikastr
tidak bergantung pada argumen slot mana pun, bahkan lebih baikArray[str&,n]<>""
sesuai tip ini .sumber
StringRepeat[s,n+1]
digunakanArray[s&,n]<>s
(bahkan saat Anda sudah memilikin+1
variabel juga).Table[str,n]<>""
Jika Anda membutuhkan daftar angka yang diurutkan secara terbalik, jangan gunakan
tapi
untuk menghemat enam byte. Menyortir berdasarkan nilai negatif juga berguna untuk
SortBy
skenario:sumber
-Sort@-x
?Anda dapat menempel ekspresi di
Break
mana dapat menyimpan satu atau dua karakter. Contoh ( detail lain yang tidak di-golf untuk kejelasan ):bisa diubah menjadi
untuk menyimpan satu karakter. Jika ekspresi yang dipermasalahkan tidak memiliki prioritas lebih rendah dari aplikasi fungsi, Anda bahkan dapat menyimpan karakter lain:
bisa diubah menjadi
Meskipun tidak berdokumen, argumen untuk
Break
tampaknya dikembalikan oleh lingkaran di sekitarnya, yang berpotensi dapat menyebabkan penghematan lebih banyak lagi.sumber
Untuk menghapus semua spasi putih dari string
s
, gunakanArtinya, gunakan
StringSplit
default (dipecah menjadi komponen non-spasi putih) dan cukup bergabung kembali. Hal yang sama mungkin masih terpendek jika Anda ingin menghilangkan karakter atau substring lain:sumber
Alternatif untuk
Range
Tugas yang sangat umum adalah menerapkan semacam fungsi pada semua angka dari 1 hingga a
n
(biasanya diberikan sebagai input). Pada dasarnya ada 3 cara untuk melakukan ini (menggunakan fungsi identitas yang tidak disebutkan namanya sebagai contoh):Saya cenderung memilih yang pertama (untuk alasan apa pun), tetapi ini jarang merupakan pilihan terbaik.
Menggunakan
Array
sebagai gantinyaContoh di atas menunjukkan bahwa menggunakan
Array
memiliki jumlah byte yang sama. Namun, itu memiliki keuntungan bahwa itu adalah ekspresi tunggal. Secara khusus, jika Anda ingin memproses lebih lanjut hasil dengan fungsif
Anda dapat menggunakan notasi awalan, yang menyimpan byte lebih dariRange
:Selain itu, Anda mungkin dapat menghilangkan tanda kurung di sekitar fungsi yang tidak disebutkan namanya yang mungkin Anda perlukan
Range
, misalnyaJika Anda tidak ingin menggunakannya lebih lanjut (atau dengan operator yang memiliki prioritas lebih rendah), Anda dapat menulis
Array
sendiri dalam notasi infiks dan juga menyimpan byte:Karenanya,
Array
hampir pasti lebih baik daripadaRange
.Menggunakan
Table
sebagai gantinyaSekarang tabel harus menebus 3 byte, atau setidaknya 2 ketika notasi infiks adalah pilihan:
Saat tidak menggunakan notasi infiks,
Table
mungkin Anda dapat menghilangkan tanda kurung jika fungsi Anda terdiri dari beberapa pernyataan:Ini masih lebih lama, tetapi memberikan penghematan ekstra dengan dalam kasus yang disebutkan di bawah ini.
Tabungan nyata berasal dari fakta yang
Table
memberi nama variabel berjalan tidak boleh diabaikan. Seringkali, Anda akan memiliki fungsi yang tidak disebutkan namanya yang bersarang di mana Anda ingin menggunakan variabel luar di dalam salah satu fungsi bagian dalam. Ketika itu terjadi,Table
lebih pendek dariRange
:Anda tidak hanya menyimpan karakter untuk ditugaskan
i
, Anda mungkin juga dapat mengurangi fungsi menjadi satu pernyataan dalam proses, yang memungkinkan Anda untuk menggunakan notasi infiks di atasnya. Sebagai referensi,Array
juga lebih lama dalam hal ini, tetapi masih lebih pendek dariRange
:Kapan Anda akan benar-benar menggunakannya
Range
?Kapan pun Anda tidak membutuhkan pemanggilan fungsi untuk memproses nilai-nilai, misalnya saat pemetaan dapat dilakukan melalui operasi yang di-vektor. Contohnya:
Tentu saja, ini juga lebih pendek jika Anda tidak ingin memetakan fungsi apa pun, misalnya
sumber
f/@Range[x]
secara teratur ...Menemukan angka terkecil yang memenuhi syarat
Beberapa konstruk like
i=1;While[cond[i],i++]
tidak apa-apa, tetapi ada alternatif yang lebih pendek dua byte:Kode di atas berulang kali menggantikan nomor
i
dengani+1
sementara itu memenuhi kondisicond[i]
. Dalam hal ini,i
mulai dari1
.Perhatikan bahwa jumlah iterasi maksimum default adalah 2 ^ 16 (= 65536). Jika Anda membutuhkan lebih banyak iterasi daripada itu,
While
akan lebih baik. (MaxIterations->∞
terlalu panjang)sumber
Evaluasi penyalahgunaan hubung singkat
Anda terkadang dapat mengganti
If
dengan operator yang logis.Misalnya, katakanlah Anda ingin membuat fungsi yang memeriksa apakah suatu bilangan prima, dan cetak
2*(number) - 1
adalah jika benar:Lebih pendek jika Anda menggunakan
&&
sebagai gantinya:Bahkan ketika Anda memiliki banyak ekspresi, Anda masih menyimpan byte:
Anda dapat menggunakan
||
kasus-kasus ketika Anda menginginkan kondisinyaFalse
:Trik ini berfungsi karena operator logis dapat mengalami hubungan pendek ; argumen kedua dan sesudahnya bahkan tidak perlu menjadi ekspresi boolean yang valid.
Tentu saja, ini tidak berfungsi jika Anda membutuhkan nilai balik
If
atau ketika Anda membutuhkan argumen yang benar dan salahIf
.sumber
Berikut adalah daftar dengan banyak formulir input operator yang dapat mempersingkat banyak hal. Beberapa di antaranya telah disebutkan di posting lain, tetapi daftarnya panjang dan saya selalu terkejut menemukan beberapa hal baru di sana:
sumber
Menggunakan
Optional (:)
Optional (:)
dapat digunakan untuk memperluas daftar dalam penggantian, tanpa harus menetapkan aturan terpisah untuk ekspansi.Jawaban ini oleh saya dan jawaban ini oleh @ngenisis adalah contoh.
Pemakaian
Penggantian di atas pertama menggunakan pola
{p___, a_, b_, q___}
dan menemukan kecocokan sedemikian sehinggab
memenuhi kondisi tertentu.Ketika tidak ada kecocokan seperti itu ditemukan, itu menghilangkan
a_
dan malah mencari{p___, b_, q___}
.a
tidak termasuk dalam pencarian dan dianggap memiliki nilai0
.Perhatikan bahwa pencarian pola kedua hanya akan berfungsi untuk
b
itu terjadi pada awal daftar; jikab
nilai yang memuaskan suatu kondisi berada di tengah, maka{p___, a_, b_, q___}
(yang memiliki prioritas lebih tinggi) akan cocok dengan itu sebagai gantinya.Penggantiannya sama dengan mengawali a
0
ketika kondisi yangb
memuaskan terjadi di awal daftar. (yaitu tidak perlu mendefinisikan aturan yang terpisah,{b_, q___} /; cond[b] :> ...
)sumber
Tahu kapan (dan kapan tidak) menggunakan argumen fungsi murni bernama
Untuk golf kode,
Function
argumen murni paling sering dirujuk menggunakanSlot
s; misalnya#
untuk argumen pertama,#2
untuk argumen kedua, dll. (lihat jawaban ini untuk lebih jelasnya).Dalam banyak kasus, Anda ingin bersarang
Function
. Sebagai contoh,1##&@@#&
adalahFunction
yang mengambil daftar sebagai argumen pertama dan mengeluarkan produk dari elemen-elemennya. Inilah fungsi diTreeForm
:Argumen yang diteruskan ke tingkat atas
Function
hanya dapat mengisi hadirSlot
danSlotSequence
s di tingkat atas, yang dalam hal ini berarti bahwaSlotSequence
di bagian dalamFunction
tidak akan ada cara mengakses argumen ke tingkat atasFunction
.Dalam beberapa kasus, meskipun, Anda mungkin ingin
Function
bersarang di dalam yang lainFunction
untuk dapat referensi argumen ke luarFunction
. Misalnya, Anda mungkin menginginkan sesuatu sepertiArray[fun,...]&
, di mana fungsinyafun
tergantung pada argumen ke tingkat atasFunction
. Untuk konkret, katakanlah yangfun
seharusnya memberikan sisa kuadrat dari input modulo input ke level atasFunction
. Salah satu cara untuk mencapai ini adalah dengan menetapkan argumen tingkat atas ke variabel:Di mana pun
x
muncul di dalamFunction
Mod[#^2,x]&
, itu akan merujuk pada argumen pertama ke luarFunction
, sedangkan#
akan merujuk pada argumen pertama ke dalamFunction
. Pendekatan yang lebih baik adalah dengan menggunakan fakta yangFunction
memiliki bentuk dua argumen di mana argumen pertama adalah simbol atau daftar simbol yang akan mewakili argumen bernama keFunction
(sebagai lawan dariSlot
s tanpa nama ). Ini akhirnya menghemat kita tiga byte dalam kasus ini:
adalah karakter penggunaan pribadi tiga byte yangU+F4A1
mewakili operator infus biner\[Function]
. Anda juga dapat menggunakan bentuk biner dari yangFunction
lainFunction
:Ini sama dengan di atas. Alasannya adalah, jika Anda menggunakan argumen bernama, maka
Slot
s danSlotSequences
dianggap milik berikutnya diFunction
atas yang tidak menggunakan argumen bernama.Sekarang hanya karena kita dapat bersarang
Function
dengan cara ini, tidak berarti kita harus selalu melakukannya. Misalnya, jika kami ingin memilih elemen-elemen daftar yang kurang dari input, kami mungkin tergoda untuk melakukan sesuatu seperti berikut:Ini sebenarnya akan lebih pendek untuk digunakan
Cases
dan menghindari kebutuhan untuk bersarangFunction
sepenuhnya:sumber
Anda dapat menyimpan byte dengan bekerja di sekitar
Prepend
atauPrependTo
:atau
Sayangnya, ini tidak membantu untuk yang lebih umum
Append
, yang tampaknya merupakan padanan terpendekArray.push()
dalam bahasa lain.sumber
Mathematica 10.2:
BlockMap
adalahPartition
+Map
Tip ini juga bisa berjudul, "Baca catatan rilis, semuanya". (Untuk referensi, berikut adalah catatan rilis untuk 10.2 dan di sini rilis 10.3 hari ini .)
Bagaimanapun, bahkan rilis kecil mengandung banyak fitur baru, dan salah satu yang lebih berguna (untuk bermain golf) dari 10.2 adalah
BlockMap
fungsi baru . Ini pada dasarnya menggabungkanPartition
danMap
, yang bagus untuk pegolf, karenaPartition
digunakan cukup sering, dan itu nama fungsi yang sangat panjang. Fungsi baru tidak akan memendekPartition
dengan sendirinya, tetapi setiap kali Anda ingin memetakan fungsi ke partisi (yang mungkin terjadi lebih sering daripada tidak), Anda sekarang dapat menyimpan satu atau dua byte:Penghematan semakin besar ketika posisi baru dari fungsi yang tidak disebutkan namanya memungkinkan Anda untuk menyelamatkan diri beberapa tanda kurung:
Sayangnya, saya tidak tahu mengapa mereka tidak menambahkannya
BlockApply
sementara mereka melakukannya ...Perhatikan juga bahwa
BlockMap
tidak mendukung parameter ke-4 yang dapat Anda gunakanPartition
untuk mendapatkan daftar siklik:sumber
Menyimpan fungsi dan ekspresi dalam suatu variabel
Jika jawaban Anda akhirnya menggunakan fungsi atau ekspresi yang sama beberapa kali, Anda mungkin ingin mempertimbangkan untuk menyimpannya dalam variabel.
Jika ekspresi Anda panjang
l
dan Anda menggunakannyan
kali, biasanya akan menggunakanl * n
byte.Namun, jika Anda menyimpannya dalam variabel panjang-1, itu hanya akan membutuhkan
3 + l + n
byte (atau2 + l + n
byte, jika Anda menetapkan variabel di mana Anda tidak perluCompoundExpression (;)
atau tanda kurung).Sebagai contoh, mari kita pertimbangkan masalah sederhana, menemukan bilangan prima kembar kurang dari N.
Seseorang dapat menulis solusi 54 byte ini:
Dalam contoh ini, fungsi
PrimeQ
ini digunakan tiga kali.Dengan menetapkan
PrimeQ
nama variabel, jumlah byte dapat dikurangi. Keduanya adalah 48 byte (54 - 6 byte):sumber
Untuk mencapai daftar nilai kunci yang naik, gunakan
Sort
sebagai gantiSortBy
Untuk daftar seperti
list = {{1, "world"}, {0, "universe"}, {2, "country"}}
, tiga pernyataan berikut ini hampir setara.Kombinasikan
Select
danSortBy
Kadang-kadang kita perlu mengambil entri dari set yang lebih besar dan mengurutkannya untuk menemukan minimum / maksimum. Dalam beberapa keadaan , dua operasi dapat digabungkan menjadi satu.
Misalnya, untuk minimum, dua pernyataan berikut ini hampir setara.
dan
1/0
adalahComplexInfinity
, yang "lebih besar" dari semua bilangan real.Untuk daftar nilai kunci, misalnya:
sumber
Meratakan
Array
dengan##&
Saat menggunakan Array multidimensi untuk menghitung daftar hasil yang perlu diratakan, gunakan
##&
sebagai argumen keempat. Ini menggantikan kepala Array dengan##&
(setara denganSequence
), bukanList
, sehingga hasil akhir akan menjadi (datar)Sequence
dari hasil.Dalam dua dimensi, bandingkan
Tentu saja,
Join@@Array[f,dims]
masih 2 (atau 3, jika notasi infiks dapat digunakan) byte lebih pendek dari{Array[f,dims,1,##&]}
.Dalam tiga atau lebih dimensi,
{Array[f,dims,origin,##&]}
selalu lebih pendek daripada alternatifnya, meskipun asalnya adalah 1.sumber
Nilai default
Nilai default menangani argumen pola yang hilang dengan cara yang efisien. Misalnya, jika kita ingin mencocokkan pola
Exp[c_*x]
dalam aturan untuk nilai apa punc
, naifmenggunakan lebih banyak byte daripada jika kita menggunakan nilai default untuk
c
setiap kali hilang:Penggunaan default ditunjukkan dengan titik setelah pola:
c_.
.Nilai default dikaitkan dengan operasi: dalam contoh di atas, operasi
Times
dalamc_.*x
, dan nilai yang hilang untukc_
dengan demikian diambil dari nilai default yang terkait denganTimes
, yaitu 1. UntukPlus
, nilai default adalah 0:Untuk
Power
eksponen, standarnya adalah 1:sumber