Tips untuk bermain golf di Mathematica

41

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).

alephalpha
sumber

Jawaban:

30

Kiat di bawah ini bervariasi dari yang paling ekonomis hingga yang paling sering digunakan:

  1. Gunakan perintah tingkat tinggi Mathematica jika memungkinkan, bahkan yang besar:

  2. Gunakan Graphics and Textuntuk seni Ascii: mis. Pemrograman bintang! dan Bangun jam analog

  3. Simbol khusus:

    • logika dan tetapkan simbol operasi alih-alih nama panjangnya: ⋂, ⋃, ∧, ∨

    • Mapdan Apply: /@, //@. @@,@@@

  4. Awalan dan infiks notasi:

    • Print@"hello" di tempat Print["hello"]

    • a~f~b di tempat f[a,b]

  5. Ketika suatu fungsi hanya digunakan sekali, fungsi murni dapat menghemat satu atau dua karakter.

  6. Menggabungkan string dalam daftar. ""<>{"a","b","c"}dari padaStringJoin@{"a","b","c"}

  7. 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}}

DavidC
sumber
2
Itu selalu lebih pendek (Norm[#-#2]&)daripada menulis EuclideanDistance.
user202729
32

Beberapa fungsi bawaan dengan nama panjang dapat diganti dengan ekspresi yang lebih pendek.

Sebagai contoh:

  • Total => Tr
  • Transpose=> Threadatau\[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=> {}⋃aataua⋃a
  • ToExpression@n=> FromDigits@njika nadalah angka
  • Divisible[n,m] => m∣n
  • FromDigits[n,2]=> Fold[#+##&,n]jika ndaftar 0s dan 1s
  • Complex@z=> di {1,I}.zmana zdaftar formulir{x,y}
alephalpha
sumber
5
@belisarius 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}}]
alephalpha
2
Saya pikir Foldtrik Anda untuk FromDigitsjuga berfungsi untuk pangkalan lain kecuali 10. Misalnya FromDigits[n,5]-> Fold[4#+##&,n](dengan bonus menyimpan byte tambahan untuk basis 100dan 1000).
Martin Ender
1
@ mbomb007 3 byte dalam UTF-8. Sebenarnya karakter ini U+F3C7.
alephalpha
1
Saya akhirnya menginstal 10.3. Jika kita mempertimbangkan program lengkap, saya tidak berpikir Echoitu pilihan, karena ia mencetak >>(dan spasi) untuk STDOUT sebelum mencetak string yang sebenarnya.
Martin Ender
2
Sebab Complex[x,y] => {1,I}.{x,y}, saya pikir x+y*Ijauh lebih pendek dengan efek yang sama?
Shieru Asakoto
22

Daftar dengan nilai berulang

Ini adalah vektor yang cukup umum untuk digunakan:

{0,0}

Ternyata ini dapat disingkat dengan byte:

0{,}

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:

0{{,},{,}}

Ini juga dapat digunakan untuk nilai-nilai non-nol jika cukup besar atau cukup banyak atau negatif. Bandingkan pasangan berikut:

{100,100}
0{,}+100
{-1,-1}
0{,}-1
{3,3,3,3}
0{,,,}+3

Tetapi ingat bahwa mulai dari 6 nilai, Anda lebih baik 1~Table~6dalam 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) adalah Nulls implisit . Selanjutnya, perkalian Listable, dan 0*xmerupakan 0untuk hampir semua x(kecuali untuk hal-hal seperti Infinitydan Indeterminate), jadi di sini adalah apa yang terjadi:

  0{,}
= 0*{,}
= 0*{Null,Null}
= {0*Null,0*Null}
= {0,0}

Untuk daftar 1s, Anda dapat menggunakan trik serupa dengan memanfaatkan aturan eksponensial. Ada dua cara berbeda untuk menghemat byte jika Anda memiliki setidaknya tiga 1s dalam daftar:

{1,1,1}
1^{,,}
{,,}^0
Martin Ender
sumber
7
+1; ini hanya untuk menunjukkan bahwa sementara Mathematica mungkin memiliki built-in untuk semuanya, bermain golf di dalamnya bisa menjadi tantangan nyata.
LegionMammal978
Jika Anda menginginkan array yang akhirnya diisi dengan 1s, maka 1^{,,,}satu byte lebih kecil dari 0{,,,}+1.
Misha Lavrov
@MishaLavrov Oh, tangkapan yang bagus. Itu membuatnya lebih pendek pada tiga nilai dan Anda juga bisa menggunakannya {,,}^0. Saya akan mengedit posting.
Martin Ender
19

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), gunakan

#@#2&

Ini 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 Associations, yang pada dasarnya adalah peta nilai-kunci dengan jenis kunci acak, ditulis seperti

<| x -> 1, "abc" -> 2, 5 -> 3 |>

Jika asosiasi seperti itu diteruskan sebagai argumen pertama ke fungsi murni, Anda dapat mengakses beberapa jika argumennya sebagai parameter bernama:

{#, #2, #3, #abc, #xyz} & [<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th"]
(* {<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th", "1st", "2nd"} *)

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 #0juga ada, dan memberi Anda objek fungsi itu sendiri. Ini bisa sangat berguna dalam quines dan quines umum. Bahkan, Quine Mathematica terpendek (saya tahu) adalah

ToString[#0][] & []

Yang 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:

f@0=0;f@1=1;f@n_:=f[n-1]+f[n-2]
f@n_:=If[n<2,n,f[n-1]+f[n-2]]
If[#<2,#,#0[#-1]+#0[#-2]]&

Urutan argumen

Sekarang di sinilah keajaiban yang sebenarnya dimulai. Urutan tidak sering digunakan dalam bermain golf, karena nama Sequenceitu 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 dalam Listatau daftar argumen fungsi, elemen-elemennya akan secara otomatis diperluas ke slot yang terpisah. Begitu

{1, Sequence[2, 3, 4], 5} == {1, 2, 3, 4, 5}
f["a", Sequence[0, {}], "b"] == f["a", 0, {}, "b"]

Sekarang, dalam fungsi murni ##atau ##1merupakan urutan dari semua argumen. Demikian juga, ##2merupakan urutan semua argumen mulai dari kedua, ##3semua argumen mulai dari dll Jadi ketiga untuk memulai, kita hanya bisa reimplement Sequencesebagai ##&, tabungan 5 byte. Sebagai contoh penggunaan, ini memberi kami alternatif untuk Join@@list(lihat tip ini ), yang tidak menyimpan byte apa pun, tetapi bagaimanapun juga baik untuk diketahui:

 ##&@@@list

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:

 RotateLeft@list
 {##2,#}&@list

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+bsebenarnya mengevaluasi Plus[a,b]. Jadi jika kita memberi urutan ...

1+##&[1,2,3]
=> Plus[1,##] 
=> Plus[1,1,2,3]
=> 7

Trik ini telah digunakan dalam tip ini untuk menghemat byte Times, karena penjajaran secara teknis juga hanya operator:

1##&[1,2,3]
=> Times[1,##]
=> Times[1,1,2,3]
=> 6

Anda juga dapat menggunakannya untuk menyimpan byte Unequaljika Anda memiliki nilai karakter tunggal atau variabel yang Anda tahu tidak ada dalam argumen Anda ( Nmungkin akan bekerja di 99% kasus):

Unequal[a,b,c]
N!=##&[a,b,c]

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 argumen a, b, c:

Operator    Function                Expanded                    Equivalent to

+##         Plus[##]                Plus[a,b,c]                 a+b+c
1##         Times[1,##]             Times[1,a,b,c]              a*b*c
-##         Times[-1,##]            Times[-1,a,b,c]             -a*b*c
x+##        Plus[x,##]              Plus[x,a,b,c]               x+a+b+c
x-##        Plus[x,Times[-1,##]]    Plus[x,Times[-1,a,b,c]]     x-a*b*c
x##         Times[x,##]             Times[x,a,b,c]              x*a*b*c
x/##        Times[x,Power[##,-1]]   Times[x,Power[a,b,c,-1]]    x*a^b^c^-1
##/x        Times[##,Power[x,-1]]   Times[a,b,c,Power[x,-1]]    a*b*c/x
x^##        Power[x,##]             Power[x,a,b,c]              x^a^b^c
##^x        Power[##,x]             Power[a,b,c,#]              a^b^c^x
x.##        Dot[x,##]               Dot[x,a,b,c]                x.a.b.c

Operator umum lainnya adalah !=, ==, &&, ||. Yang kurang umum untuk diingat adalah |, @*, /*. Untuk menyimpulkan, berikut adalah trik bonus kecil:

####        Times[##,##]            Times[a,b,c,a,b,c]          (a*b*c)^2

Terus bereksperimen dengan ini, dan beri tahu saya jika Anda menemukan aplikasi lain yang bermanfaat atau sangat menarik!

Martin Ender
sumber
15

Sqrt@2atau 2^.5=>√2

a[[1]]=>a〚1〛

#+#2&=>+##&

Flatten@a=> Join@@a(terkadang)

Function[x,x^2]=> xx^2atau#^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

chyanog
sumber
1
Perhatikan bahwa ketika mengukur dengan byte, menggunakan dan mengambil masing-masing 3 byte (asumsikan UTF8)
user202729
12

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:

±x_:=2x
x_ ±y_:=x+y
x_ ·y_ ·z_:=x*y+z
Print[±5]  (* 10 *)
Print[3±4] (*  7 *)
Print[3·4·5] (* 17 *)

Bandingkan ini dengan:

f@x_:=2x
x_~g~y_:=x+y
h[x_,y_,z_]:=x*y+z
Print[f@5]   (* 10 *)
Print[3~g~4] (*  7 *)
Print[h[x,y,z]] (* 17 *)

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:

x_ ·y__:={y}
Print[1·2·3·4·5] (* {2, 3, 4, 5} *)

Tetapi perhatikan bahwa tidak mudah untuk memanggil fungsi variadic ini dengan satu argumen. (Anda bisa melakukannya CenterDot[x]atau ##&[]·xtetapi 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 $CharacterEncodingharus diatur ke nilai yang kompatibel, seperti standar Windows WindowsANSI. Pada beberapa sistem, default ini UTF-8tidak dapat membaca poin kode ini dari satu byte.

Martin Ender
sumber
Ini benar-benar hebat, saya tidak tahu Mathematica punya daftar operator, dan bahkan memasukkan prioritas mereka. Dua operator yang Anda temukan saya yakin akan berguna.
mil
8

Memilih nilai berdasarkan integer

Pendekatan naif untuk memilih antara ydan z, tergantung pada apakah xadalah 0atau 1merupakan

If[x<1,y,z]

Namun, ada cara yang lebih singkat:

y[z][[x]]

Ini berfungsi karena [[0]]memberikan Headekspresi, dalam hal ini y, sedangkan [[1]]hanya memberikan elemen pertama - dalam hal ini argumen pertama z,.

Anda bahkan dapat menggunakan ini untuk memilih antara lebih dari dua nilai:

u[v,w][[x]]

Perhatikan bahwa ini tidak akan berfungsi jika ufungsi yang sebenarnya mengevaluasi sesuatu. Penting agar Mathematica tetap u[v,w]seperti itu. Namun, ini berfungsi dalam kebanyakan kasus, termasuk jika uadalah angka, string atau daftar.

Penghargaan untuk trik ini diberikan ke alephalpha - Saya menemukan ini dalam salah satu jawabannya.

Jika xberbasis 1 dan bukan berbasis nol, gunakan saja

{y,z}[[x]]

atau

{u,v,w}[[x]]

Dalam beberapa kasus yang jarang terjadi, Anda bahkan dapat menggunakan fakta bahwa perkalian tidak dievaluasi untuk beberapa nilai:

{"abc","def"}[[x]]
("abc""def")[[x]]

Catat bahwa Mathematica sebenarnya akan menyusun ulang argumen, dari perkalian jika tetap tidak dievaluasi, sehingga hal di atas identik dengan

("def""abc")[[x]]
Martin Ender
sumber
8

Alternatif untuk Length

Ini sepenuhnya ditulis ulang dengan beberapa saran dari LegionMammal978 dan Misha Lavrov. Terima kasih banyak untuk mereka berdua.

Dalam banyak kasus, Lengthdapat dipersingkat sedikit dengan memanfaatkan Tr. Ide dasarnya adalah mengubah input menjadi daftar 1s, sehingga Trmeringkasnya yang kemudian akan sama dengan panjang daftar.

Cara paling umum untuk melakukan ini adalah menggunakan 1^x(untuk daftar x). Ini bekerja karena Powermerupakan Listabledan 1^nuntuk sebagian besar nilai-nilai atom nhanya 1(termasuk semua nomor, string dan simbol). Jadi kita sudah bisa menyimpan satu byte dengan ini:

Length@x
Tr[1^x]

Tentu saja, ini mengasumsikan bahwa xini adalah ekspresi dengan prioritas lebih tinggi daripada ^.

Jika xhanya berisi 0s dan 1s, kita dapat menyimpan byte lain menggunakan Factorial(dengan asumsi xmemiliki prioritas lebih tinggi daripada !):

Length@x
Tr[x!]

Dalam beberapa kasus yang jarang terjadi, xmungkin 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 membandingkan Length[x]. Contoh dari operator tersebut adalah .. Dalam kasus tersebut, Anda masih dapat menyimpan byte dengan formulir ini:

Length[x.y]
Tr[0x.y+1]

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 Trmemberi Anda dimensi terpendek (bukan yang pertama). Jika Anda tahu bahwa dimensi terluar adalah yang terpendek, atau Anda tahu mereka semua sama, daripada Tr-ekspresi masih setara Length.

Martin Ender
sumber
3
Hanya menemukan solusi bahkan lebih pendek: Length@x == Tr[1^x]. Harus bekerja dengan sebagian besar daftar.
LegionMammal978
@ LegionMammal978 itu luar biasa, terima kasih :). Saya akan segera mengeditnya.
Martin Ender
1
Dua kali sekarang, saya menemukan diri saya menggunakan Tr[x!]alih-alih Tr[1^x]menyimpan satu byte dalam kasus khusus di mana xhanya berisi nol dan satu.
Misha Lavrov
@MishaLavrov Benar-benar rapi! :)
Martin Ender
7
  1. Jelajahi solusi rekursif - Mathematica adalah multi-paradigma, tetapi pendekatan fungsional sering kali paling ekonomis. NestWhilebisa menjadi solusi yang sangat kompak untuk mencari masalah, NestWhileListdan FoldListsangat 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.

  2. Formulir singkat untuk kenaikan / penurunan - Misalnya, alih-alih While[i<1,*code*;i++]yang dapat Anda lakukan
    While[i++<1,*code*]

  3. Jangan lupa Anda bisa melakukan pra-kenaikan / penurunan - Misalnya, --ialih-alih i--. Ini kadang-kadang dapat menghemat beberapa byte dalam kode di sekitarnya dengan menghilangkan operasi persiapan.

  4. 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 ToExpression4 kali dalam suatu solusi, t=ToExpressionmemungkinkan Anda untuk menggunakannya t@*expression*setelahnya. Namun, sebelum Anda melakukan ini pertimbangkan apakah aplikasi berulang dari fungsi yang sama menunjukkan peluang untuk pendekatan rekursif yang lebih ekonomis.

Jonathan Van Matre
sumber
MapThreadsering dapat diganti dengan \[Transpose]. TIO .
user202729
7

Jangan gunakan {}jika Anda menggunakan @@@.

Dalam beberapa kasus, Anda mungkin menemukan ekspresi seperti:

f@@@{{a,b},{c,d}}

Dimungkinkan untuk mengurangi byte dengan menulis:

f@@@{a|b,c|d}

Alternativesmemiliki prioritas yang sangat rendah, jadi biasanya tidak apa-apa untuk menulis ekspresi (pengecualian penting adalah fungsi murni; Anda dapat menggunakannya hanya di elemen paling kiri Alternatives).

f@@@{f@a|b~g~1,#^2&@c|d@2}

Perhatikan bahwa f@@a|b|c(bukannya f@@{a,b,c}) tidak berfungsi karena Applymemiliki prioritas lebih tinggi daripada Alternative.

Dalam hal ini, Anda cukup menggunakan f@@{a,b,c}.

JungHwan Min
sumber
6

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&]banyak lists berbeda . Sebelumnya, Anda mungkin akan ditugaskan SortByuntuk sdan fungsi murni untuk fjadi

s=SortBy;
f=somereallylongfunction&;
list1~s~f;
list2~s~f;
list3~s~f;

Sekarang Anda bisa menjilat SortBy, yang artinya sekarang bisa Anda lakukan

s=SortBy[somereallylongfunction&];
s@list1;
s@list2;
s@list3;

Karya-karya yang sama untuk banyak fungsi lainnya, yang mengambil daftar atau fungsi argumen, termasuk (namun tidak terbatas pada) Select, Map, Nearest, dll

ybeltukov ke atas di Mathematica.SE mampu menghasilkan daftar lengkap ini :

{"AllTrue", "AnyTrue", "Append", "Apply", "AssociationMap", "Cases", 
 "Count", "CountDistinctBy", "CountsBy", "Delete", "DeleteCases", 
 "DeleteDuplicatesBy", "Extract", "FirstCase", "FirstPosition", 
 "FreeQ", "GroupBy", "Insert", "KeyDrop", "KeyExistsQ", "KeyMap", 
 "KeySelect", "KeySortBy", "KeyTake", "Map", "MapAt", "MapIndexed", 
 "MatchQ", "MaximalBy", "MemberQ", "Merge", "MinimalBy", "NoneTrue", 
 "Position", "Prepend", "Replace", "ReplacePart", "Scan", "Select", 
 "SelectFirst", "SortBy", "StringCases"}

Komposisi dan Komposisi Kanan

Ada singkatan baru untuk Composition( @*) dan RightComposition( /*). Contoh yang jelas dibuat di mana ini dapat menyimpan karakter terlihat dalam tiga baris setara berikut

Last@Range@# & /@ Range[5]
Last@*Range /@ Range[5]
Range /* Last /@ Range[5]
Martin Ender
sumber
5

Jangan menulis fungsi 0-argumen

Tidak perlu kode seperti ini:

f[]:=DoSomething[1,2]
(*...*)
f[]
(*...*)
f[]

Anda cukup menggunakan variabel dengan :=untuk memaksa evaluasi ulang dari sisi kanan:

f:=DoSomething[1,2]
(*...*)
f
(*...*)
f

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 kasus n++itu membayar kembali setelah penggunaan keempat:

n++;n++;n++;n++
f:=n++;f;f;f;f
Martin Ender
sumber
5

Gunakan %untuk mendapatkan variabel gratis

Tip 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:

a=someLongExpression;some[other*a,expression@a,using^a]

Sebagai gantinya, ingatlah bahwa Mathematica menyimpan ekspresi yang terakhir dievaluasi (diakhiri baris) di %:

someLongExpression;
some[other*%,expression@%,using^%]

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 atoh), Anda bahkan dapat mengabaikannya ;, menghemat dua byte:

someLongExpression
some[other*%,expression@%,using^%]

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:

Length   Min. Uses
2        6
3        4
4        3
5        3
6        2
...      2

Dengan menggunakan variabel yang tidak disebutkan namanya, akan lebih mungkin untuk menyimpan beberapa byte lebih sering:

When ; is required                        When ; can be omitted

Length   Min. Uses                        Length   Min. Uses
2        5                                2        4
3        3                                3        3
4        3                                4        2
5        2                                ...      2
...      2

Saya tidak berpikir %%atau tidak %nbisa 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 beberapa x=.

Martin Ender
sumber
Perhatikan bahwa ini tidak berfungsi dalam mode skrip.
alephalpha
@alephalpha Apa itu mode skrip?
Martin Ender
Sebuah naskah Mathematica .
alephalpha
@alephalpha Oh benar, saya mematikan otak saya di sana sebentar ... jadi itu berarti tidak bisa digunakan sama sekali, kecuali lingkungan REPL dapat diasumsikan.
Martin Ender
5

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

OrderedQ@a

Kita dapat melakukan satu byte dengan lebih baik

Sort@a==a

Namun, ini tidak berfungsi jika kita belum memiliki hal yang ingin kita periksa di variabel. (Kami membutuhkan sesuatu Sort[a=...]==ayang panjangnya tidak perlu.) Namun, ada opsi lain:

#<=##&@@a

Yang terbaik adalah ini dapat digunakan untuk memeriksa apakah input diurutkan terbalik untuk jumlah byte yang sama:

#>=##&@@a

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):

0<##&@@a
5>##&@@a

Untuk mengetahui mengapa ini berhasil, lihat "Urutan argumen" di ujung yang ditautkan di atas.

Martin Ender
sumber
Atau, (ketat) menurunkan terikat untuk reverse-diurutkan juga bekerja: ##>0&@@a. Mirip untuk batas atas untuk diurutkan.
user202729
@ user202729 Oh good point, jangan ragu untuk mengedit (kalau tidak saya akan mencoba melakukannya pada akhir pekan jika saya ingat).
Martin Ender
5

Mengulang sebuah string

Alih-alih StringRepeat[str,n]digunakan (0Range[n]+str)<>"". Atau jika strtidak bergantung pada argumen slot mana pun, bahkan lebih baik Array[str&,n]<>""sesuai tip ini .

feersum
sumber
1
Konsekuensi: alih-alih StringRepeat[s,n+1]digunakan Array[s&,n]<>s(bahkan saat Anda sudah memiliki n+1variabel juga).
Martin Ender
Lebih baik,Table[str,n]<>""
attinat
5

Jika Anda membutuhkan daftar angka yang diurutkan secara terbalik, jangan gunakan

Reverse@Sort@x

tapi

-Sort@-x

untuk menghemat enam byte. Menyortir berdasarkan nilai negatif juga berguna untuk SortByskenario:

Reverse@SortBy[x,Last]
SortBy[x,-Last@#&]
Martin Ender
sumber
2
Bagaimana dengan -Sort@-x?
JungHwan Min
1
@JungHwanMin Oh, uhhh, ya, itu jauh lebih baik. :)
Martin Ender
4

Anda dapat menempel ekspresi di Breakmana dapat menyimpan satu atau dua karakter. Contoh ( detail lain yang tidak di-golf untuk kejelasan ):

result = False;
Break[]

bisa diubah menjadi

Break[result = False]

untuk menyimpan satu karakter. Jika ekspresi yang dipermasalahkan tidak memiliki prioritas lebih rendah dari aplikasi fungsi, Anda bahkan dapat menyimpan karakter lain:

Print@x;
Break[]

bisa diubah menjadi

Break@Print@x

Meskipun tidak berdokumen, argumen untuk Breaktampaknya dikembalikan oleh lingkaran di sekitarnya, yang berpotensi dapat menyebabkan penghematan lebih banyak lagi.

Martin Ender
sumber
4

Untuk menghapus semua spasi putih dari string s, gunakan

StringSplit@s<>""

Artinya, gunakan StringSplitdefault (dipecah menjadi komponen non-spasi putih) dan cukup bergabung kembali. Hal yang sama mungkin masih terpendek jika Anda ingin menghilangkan karakter atau substring lain:

s~StringSplit~"x"<>""
Martin Ender
sumber
4

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):

#&/@Range@n
Array[#&,n]
Table[i,{i,n}]

Saya cenderung memilih yang pertama (untuk alasan apa pun), tetapi ini jarang merupakan pilihan terbaik.

Menggunakan Array sebagai gantinya

Contoh di atas menunjukkan bahwa menggunakan Arraymemiliki jumlah byte yang sama. Namun, itu memiliki keuntungan bahwa itu adalah ekspresi tunggal. Secara khusus, jika Anda ingin memproses lebih lanjut hasil dengan fungsi fAnda dapat menggunakan notasi awalan, yang menyimpan byte lebih dari Range:

f[#&/@Range@n]
f@Array[#&,n]

Selain itu, Anda mungkin dapat menghilangkan tanda kurung di sekitar fungsi yang tidak disebutkan namanya yang mungkin Anda perlukan Range, misalnya

15/(#&)/@Range@n
15/Array[#&,n]

Jika Anda tidak ingin menggunakannya lebih lanjut (atau dengan operator yang memiliki prioritas lebih rendah), Anda dapat menulis Arraysendiri dalam notasi infiks dan juga menyimpan byte:

#&/@Range@n
#&~Array~n

Karenanya, Arrayhampir pasti lebih baik daripadaRange .

Menggunakan Table sebagai gantinya

Sekarang tabel harus menebus 3 byte, atau setidaknya 2 ketika notasi infiks adalah pilihan:

#&/@Range@n
i~Table~{i,n}

Saat tidak menggunakan notasi infiks, Tablemungkin Anda dapat menghilangkan tanda kurung jika fungsi Anda terdiri dari beberapa pernyataan:

(#;#)&/@Range@n
Table[i;i,{i,n}]

Ini masih lebih lama, tetapi memberikan penghematan ekstra dengan dalam kasus yang disebutkan di bawah ini.

Tabungan nyata berasal dari fakta yang Tablememberi 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, Tablelebih pendek dari Range:

(i=#;i&[])&/@Range@n
Table[i&[],{i,n}]
i&[]~Table~{i,n}

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, Arrayjuga lebih lama dalam hal ini, tetapi masih lebih pendek dari Range:

(i=#;i&[])&~Array~n

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:

5#&~Array~n
5Range@n
#^2&~Array~n
Range@n^2

Tentu saja, ini juga lebih pendek jika Anda tidak ingin memetakan fungsi apa pun, misalnya

Mean@Array[#&,n]
Mean@Range@n
Martin Ender
sumber
Akhirnya orang lain yang menggunakan f/@Range[x]secara teratur ...
LegionMammal978
4

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:

1//.i_/;cond[i]:>i+1

Kode di atas berulang kali menggantikan nomor idengan i+1sementara itu memenuhi kondisi cond[i]. Dalam hal ini, imulai dari 1.

Perhatikan bahwa jumlah iterasi maksimum default adalah 2 ^ 16 (= 65536). Jika Anda membutuhkan lebih banyak iterasi daripada itu, Whileakan lebih baik. ( MaxIterations->∞terlalu panjang)

JungHwan Min
sumber
4

Evaluasi penyalahgunaan hubung singkat

Anda terkadang dapat mengganti Ifdengan operator yang logis.

Misalnya, katakanlah Anda ingin membuat fungsi yang memeriksa apakah suatu bilangan prima, dan cetak 2*(number) - 1adalah jika benar:

If[PrimeQ@#,Print[2#-1]]&

Lebih pendek jika Anda menggunakan &&sebagai gantinya:

PrimeQ@#&&Print[2#-1]&

Bahkan ketika Anda memiliki banyak ekspresi, Anda masih menyimpan byte:

If[PrimeQ@#,a++;Print[2#-1]]&

PrimeQ@#&&a++&&Print[2#-1]&
(* or *)
PrimeQ@#&&(a++;Print[2#-1])&

Anda dapat menggunakan ||kasus-kasus ketika Anda menginginkan kondisinya False:

If[!PrimeQ@#,Print[2#-1]]&
(* or *)
If[PrimeQ@#,,Print[2#-1]]&
(* can become *)
PrimeQ@#||Print[2#-1]&

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 Ifatau ketika Anda membutuhkan argumen yang benar dan salah If.

JungHwan Min
sumber
3

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:

Martin Ender
sumber
Namun, ini hanya berfungsi ketika operator menggunakan lebih sedikit byte UTF-8.
LegionMammal978
3

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

... /. {p___, a_: 0, b_, q___} /; cond[b] :> ...

Penggantian di atas pertama menggunakan pola {p___, a_, b_, q___}dan menemukan kecocokan sedemikian sehingga bmemenuhi kondisi tertentu.

Ketika tidak ada kecocokan seperti itu ditemukan, itu menghilangkan a_dan malah mencari {p___, b_, q___}. atidak termasuk dalam pencarian dan dianggap memiliki nilai 0.

Perhatikan bahwa pencarian pola kedua hanya akan berfungsi untuk bitu terjadi pada awal daftar; jika bnilai 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 0ketika kondisi yang bmemuaskan terjadi di awal daftar. (yaitu tidak perlu mendefinisikan aturan yang terpisah, {b_, q___} /; cond[b] :> ...)

JungHwan Min
sumber
3

Tahu kapan (dan kapan tidak) menggunakan argumen fungsi murni bernama

Untuk golf kode, Functionargumen murni paling sering dirujuk menggunakan Slots; misalnya #untuk argumen pertama, #2untuk argumen kedua, dll. (lihat jawaban ini untuk lebih jelasnya).

Dalam banyak kasus, Anda ingin bersarang Function. Sebagai contoh, 1##&@@#&adalah Functionyang mengambil daftar sebagai argumen pertama dan mengeluarkan produk dari elemen-elemennya. Inilah fungsi di TreeForm:

masukkan deskripsi gambar di sini

Argumen yang diteruskan ke tingkat atas Functionhanya dapat mengisi hadir Slotdan SlotSequences di tingkat atas, yang dalam hal ini berarti bahwa SlotSequencedi bagian dalam Functiontidak akan ada cara mengakses argumen ke tingkat atas Function.

Dalam beberapa kasus, meskipun, Anda mungkin ingin Functionbersarang di dalam yang lain Functionuntuk dapat referensi argumen ke luar Function. Misalnya, Anda mungkin menginginkan sesuatu seperti Array[fun,...]&, di mana fungsinya funtergantung pada argumen ke tingkat atas Function. Untuk konkret, katakanlah yang funseharusnya memberikan sisa kuadrat dari input modulo input ke level atas Function. Salah satu cara untuk mencapai ini adalah dengan menetapkan argumen tingkat atas ke variabel:

(x=#;Array[Mod[#^2,x]&,...])&

Di mana pun xmuncul di dalam Function Mod[#^2,x]&, itu akan merujuk pada argumen pertama ke luar Function, sedangkan #akan merujuk pada argumen pertama ke dalam Function. Pendekatan yang lebih baik adalah dengan menggunakan fakta yang Functionmemiliki bentuk dua argumen di mana argumen pertama adalah simbol atau daftar simbol yang akan mewakili argumen bernama ke Function(sebagai lawan dari Slots tanpa nama ). Ini akhirnya menghemat kita tiga byte dalam kasus ini:

xArray[Mod[#^2,x]&,...]

adalah karakter penggunaan pribadi tiga byte yang U+F4A1mewakili operator infus biner \[Function]. Anda juga dapat menggunakan bentuk biner dari yang Functionlain Function:

Array[xMod[x^2,#],...]&

Ini sama dengan di atas. Alasannya adalah, jika Anda menggunakan argumen bernama, maka Slots dan SlotSequencesdianggap milik berikutnya di Functionatas yang tidak menggunakan argumen bernama.

Sekarang hanya karena kita dapat bersarang Functiondengan 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:

Select[...,xx<#]&

Ini sebenarnya akan lebih pendek untuk digunakan Casesdan menghindari kebutuhan untuk bersarang Functionsepenuhnya:

Cases[...,x_/;x<#]&
ngenisis
sumber
2

Anda dapat menyimpan byte dengan bekerja di sekitar Prependatau PrependTo:

l~Prepend~x
{x}~Join~l
{x,##}&@@l

atau

l~PrependTo~x
l={x}~Join~l
l={x,##}&@@l

Sayangnya, ini tidak membantu untuk yang lebih umum Append, yang tampaknya merupakan padanan terpendek Array.push()dalam bahasa lain.

Martin Ender
sumber
2

Mathematica 10.2: BlockMapadalah Partition+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 BlockMapfungsi baru . Ini pada dasarnya menggabungkan Partitiondan Map, yang bagus untuk pegolf, karena Partitiondigunakan cukup sering, dan itu nama fungsi yang sangat panjang. Fungsi baru tidak akan memendek Partitiondengan 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:

#&/@l~Partition~2
BlockMap[#&,l,2]
#&/@Partition[l,3,1]
BlockMap[#&,l,3,1]

Penghematan semakin besar ketika posisi baru dari fungsi yang tidak disebutkan namanya memungkinkan Anda untuk menyelamatkan diri beberapa tanda kurung:

#&@@(#&/@Partition[l,3,1])
#&@@BlockMap[#&,l,3,1]

Sayangnya, saya tidak tahu mengapa mereka tidak menambahkannya BlockApplysementara mereka melakukannya ...

Perhatikan juga bahwa BlockMaptidak mendukung parameter ke-4 yang dapat Anda gunakan Partitionuntuk mendapatkan daftar siklik:

Partition[Range@5, 2, 1, 1]
(* Gives {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 1}} *)
BlockMap[f, Range@5, 2, 1, 1]
(* Nope... *)
Martin Ender
sumber
2

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 ldan Anda menggunakannya nkali, biasanya akan menggunakan l * nbyte.

Namun, jika Anda menyimpannya dalam variabel panjang-1, itu hanya akan membutuhkan 3 + l + nbyte (atau 2 + l + nbyte, jika Anda menetapkan variabel di mana Anda tidak perlu CompoundExpression (;)atau tanda kurung).


Sebagai contoh, mari kita pertimbangkan masalah sederhana, menemukan bilangan prima kembar kurang dari N.

Seseorang dapat menulis solusi 54 byte ini:

Select[Range@#,PrimeQ@#&&(PrimeQ[#+2]||PrimeQ[#-2])&]&

Dalam contoh ini, fungsi PrimeQini digunakan tiga kali.

Dengan menetapkan PrimeQnama variabel, jumlah byte dapat dikurangi. Keduanya adalah 48 byte (54 - 6 byte):

Select[p=PrimeQ;Range@#,p@#&&(p[#+2]||p[#-2])&]&
Select[Range@#,(p=PrimeQ)@#&&(p[#+2]||p[#-2])&]&
JungHwan Min
sumber
2

Untuk mencapai daftar nilai kunci yang naik, gunakan Sortsebagai gantiSortBy

Untuk daftar seperti list = {{1, "world"}, {0, "universe"}, {2, "country"}}, tiga pernyataan berikut ini hampir setara.

SortBy[list,#[[1]]&]
list~SortBy~First
Sort@list

Kombinasikan SelectdanSortBy

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.

SortBy[Select[l,SomeFormula==SomeConstant&],SortValue&]
SortBy[l,SortValue+99!(SomeFormula-SomeConstant)^2&]

dan

SortBy[Select[l,SomeFormula!=SomeConstant&],SortValue&]
SortBy[l,SortValue+1/(SomeFormula-SomeConstant)&]

1/0adalah ComplexInfinity, yang "lebih besar" dari semua bilangan real.

Untuk daftar nilai kunci, misalnya:

{SortValue,#}&/@SortBy[Select[l,SomeFormula==SomeConstant],SortValue&]
Sort[{SortValue+99!(SomeFormula-SomeConstant)^2,#})&/@l]
Keyu Gan
sumber
1

Meratakan Arraydengan##&

Saat menggunakan Array multidimensi untuk menghitung daftar hasil yang perlu diratakan, gunakan ##&sebagai argumen keempat. Ini menggantikan kepala Array dengan ##&(setara dengan Sequence), bukan List, sehingga hasil akhir akan menjadi (datar) Sequencedari hasil.

Dalam dua dimensi, bandingkan

{Array[f,dims,origin,##&]}
Join@@Array[f,dims,origin]

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.

{Array[f,dims,1,##&]}
f~Array~dims~Flatten~2
attinat
sumber
1

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 pun c, naif

Exp[x] + Exp[2x] /. {Exp[c_*x] -> f[c], Exp[x] -> f[1]}
(*    f[1] + f[2]    *)

menggunakan lebih banyak byte daripada jika kita menggunakan nilai default untuk csetiap kali hilang:

Exp[x] + Exp[2 x] /. Exp[c_.*x] -> f[c]
(*    f[1] + f[2]    *)

Penggunaan default ditunjukkan dengan titik setelah pola: c_..

Nilai default dikaitkan dengan operasi: dalam contoh di atas, operasi Timesdalam c_.*x, dan nilai yang hilang untuk c_dengan demikian diambil dari nilai default yang terkait dengan Times, yaitu 1. Untuk Plus, nilai default adalah 0:

Exp[x] + Exp[x + 2] /. Exp[x + c_.] -> f[c]
(*    f[0] + f[2]    *)

Untuk Powereksponen, standarnya adalah 1:

x + x^2 /. x^n_. -> p[n]
(*    p[1] + p[2]    *)
Roma
sumber