Lời khuyên cho việc chơi golf ở Mathematica


41

Bạn có lời khuyên chung nào cho việc chơi golf trong Mathematica? Tôi đang tìm kiếm những ý tưởng có thể được áp dụng cho các vấn đề về golf nói chung ít nhất là cụ thể đối với Mathematica (ví dụ: "xóa bình luận" không phải là một câu trả lời).

Câu trả lời:


30

Các mẹo dưới đây thay đổi từ kinh tế nhất đến thường được sử dụng nhất:

  1. Sử dụng các lệnh cấp cao của Mathematica nếu có thể, thậm chí là các lệnh cồng kềnh:

  2. Sử dụng Graphics and Textcho nghệ thuật Ascii: ví dụ lập trình Star! xây dựng một đồng hồ analog

  3. Biểu tượng chuyên dụng:

    • logic và thiết lập các ký hiệu hoạt động thay vì tên dạng dài của chúng:, ⋃, ∧,

    • MapApply: /@, //@. @@,@@@

  4. Tiền tố và ký hiệu infix:

    • Print@"hello" thay cho Print["hello"]

    • a~f~b thay cho f[a,b]

  5. Khi một chức năng chỉ được sử dụng một lần, một chức năng thuần túy có thể tiết kiệm một hoặc hai ký tự.

  6. Tham gia chuỗi trong một danh sách. ""<>{"a","b","c"}thay vìStringJoin@{"a","b","c"}

  7. Khai thác các chức năng có thể liệt kê. Danh sách càng dài càng tốt.

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


2
luôn luôn ngắn hơn để viết (Norm[#-#2]&)thay vì EuclideanDistance.
dùng202729

32

Một số hàm dựng sẵn có tên dài có thể được thay thế bằng các biểu thức ngắn hơn.

Ví dụ:

  • Total => Tr
  • Transpose=> Threadhoặc\[Transpose]
  • True => 1<2
  • False => 1>2
  • Times => 1##&
  • Alternatives => $|##&
  • IntegerQ => ⌊#⌋==#&
  • a[[1]] => #&@@a
  • a[[All,1]] => #&@@@a
  • ConstantArray[a,n]=> Array[a&,n]hoặcTable[a,{n}]
  • Union@a=> {}⋃ahoặca⋃a
  • ToExpression@n=> FromDigits@nnếu nlà một số
  • Divisible[n,m] => m∣n
  • FromDigits[n,2]=> Fold[#+##&,n]nếu nlà danh sách 0s và 1s
  • Complex@z=> {1,I}.zđâu zlà danh sách biểu mẫu{x,y}

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
Tôi nghĩ rằng Foldmẹo của bạn FromDigitscũng hoạt động cho bất kỳ cơ sở nào khác ngoại trừ 10. Ví dụ: FromDigits[n,5]> Fold[4#+##&,n](với phần thưởng là tiết kiệm thêm một byte cho các cơ sở 1001000).
Martin Ender

1
@ mbomb007 3 byte trong UTF-8. Trong thực tế nhân vật này là U+F3C7.
alephalpha

1
Cuối cùng tôi đã cài đặt 10.3. Nếu chúng tôi đang xem xét các chương trình đầy đủ, tôi không nghĩ Echolà một tùy chọn, vì nó in >>(và một khoảng trắng) thành STDOUT trước khi in chuỗi thực tế.
Martin Ender

2
Đối với Complex[x,y] => {1,I}.{x,y}, tôi nghĩ x+y*Ilà ngắn hơn nhiều với cùng một hiệu ứng?
Shieru Asakoto

22

Danh sách có giá trị lặp lại

Đây là một vector khá phổ biến để làm việc với:

{0,0}

Hóa ra điều này có thể được rút ngắn bằng một byte:

0{,}

Thậm chí nhiều byte được lưu nếu vectơ dài hơn hai số không. Điều này cũng có thể được sử dụng để khởi tạo ma trận bằng 0, ví dụ sau đây đưa ra ma trận 2x2 của các số 0:

0{{,},{,}}

Điều này cũng có thể được sử dụng cho các giá trị khác không nếu chúng đủ lớn hoặc đủ nhiều hoặc âm. So sánh các cặp sau:

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

Nhưng hãy nhớ rằng bắt đầu từ 6 giá trị, bạn nên làm tốt hơn 1~Table~6trong trường hợp này (có khả năng sớm hơn, tùy thuộc vào yêu cầu ưu tiên).

Lý do công việc này là ,giới thiệu hai đối số vào danh sách, nhưng các đối số bị bỏ qua (bất cứ nơi nào trong Mathicala) đều ẩn Null. Bên cạnh đó, nhân là Listable, và 0*x0đối với hầu như bất kỳ x(trừ những thứ như InfinityIndeterminate), vì vậy đây là những gì đang xảy ra:

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

Đối với danh sách 1s, bạn có thể sử dụng một mẹo tương tự bằng cách sử dụng quy tắc lũy thừa. Có hai cách khác nhau để lưu byte nếu bạn có ít nhất ba 1giây trong danh sách:

{1,1,1}
1^{,,}
{,,}^0

7
+1; điều này chỉ cho thấy rằng trong khi Mathematica có thể tích hợp sẵn mọi thứ, thì việc chơi golf trong đó có thể là một thách thức thực sự.
LegionMammal978

Nếu bạn muốn một mảng cuối cùng chứa đầy 1s thì 1^{,,,}nhỏ hơn một byte 0{,,,}+1.
Misha Lavrov

@MishaLavrov ơi, bắt tốt lắm. Điều đó làm cho nó ngắn hơn ở ba giá trị và bạn cũng có thể sử dụng {,,}^0. Tôi sẽ chỉnh sửa bài viết.
Martin Ender

19

Biết các đối số hàm thuần túy của bạn

Khi chơi mã, bạn sẽ thường sử dụng một cách tiếp cận chức năng, trong đó bạn sử dụng các hàm ẩn danh (thuần túy) với &cú pháp tốc ký. Có rất nhiều cách khác nhau để truy cập các đối số của hàm như vậy và bạn thường có thể loại bỏ một vài byte bằng cách nắm bắt tốt các khả năng.

Truy cập các đối số duy nhất

Bạn có thể biết điều này nếu bạn đã sử dụng các hàm thuần túy trước đây. Đối số thứ n được gọi là #n#đóng vai trò là bí danh cho #1. Vì vậy, nếu, giả sử, bạn muốn viết một hàm lấy tham số của hàm khác và đối số của nó (để truyền đối số cho hàm đó), hãy sử dụng

#@#2&

Điều này không hoạt động với các số âm (chẳng hạn như bạn có thể sử dụng khi truy cập danh sách).

Truy cập các đối số được đặt tên (mới trong V10)

Một trong những tính năng ngôn ngữ mới chính trong Mathematica 10 là Associations, về cơ bản là các bản đồ giá trị khóa với các loại khóa tùy ý, được viết như

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

Nếu một liên kết như vậy được truyền vào dưới dạng đối số đầu tiên cho hàm thuần túy, bạn có thể truy cập một số nếu đối số của nó là tham số được đặt tên:

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

Lưu ý rằng #vẫn đề cập đến toàn bộ hiệp hội như mong đợi. Để các tham số được đặt tên hoạt động, các khóa phải là các chuỗi (chẳng hạn, nó sẽ không hoạt động nếu bạn sử dụng các biến không xác định) và các chuỗi đó phải bắt đầu bằng một chữ cái và chỉ chứa các chữ cái và chữ số.

Đối số "tự" #0

Một tính năng ít được biết đến là nó #0cũng tồn tại và cung cấp cho bạn chính đối tượng hàm. Điều này có thể thực sự hữu ích trong các quines và quines tổng quát. Trong thực tế, quine Mathicala ngắn nhất (tôi biết) là

ToString[#0][] & []

Điều hơi khó chịu là nó sẽ không cung cấp cho bạn các ký tự chính xác mà bạn đã nhập. Ví dụ, nếu sử dụng @cho ứng dụng chức năng, nó vẫn sẽ hiển thị [...]và không gian sẽ được chèn vào một số nơi. Điều này thường sẽ làm cho quine dài hơn một chút so với mong muốn của bạn, nhưng nó sẽ luôn hoạt động, bằng cách đánh golf trước, và sau đó chỉ sao chép đầu ra của nó - mà bây giờ sẽ là một câu hỏi thực sự.

Ngoài quines, điều này cũng có nghĩa là bạn có thể viết mã đệ quy mà không phải đặt tên cho hàm của mình. So sánh ba cách triển khai Fibonacci (ngây thơ nhưng bị đánh gôn) này:

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]]&

Trình tự lập luận

Bây giờ đây là nơi ma thuật thực sự bắt đầu. Trình tự không được sử dụng thường xuyên trong việc chơi golf, bởi vì Sequencenó chỉ là một cái tên quá dài để có giá trị trong hầu hết thời gian. Nhưng trong các chức năng thuần túy là nơi chúng tỏa sáng. Nếu bạn không quen thuộc với các chuỗi, về cơ bản chúng giống như các biểu tượng trong một số ngôn ngữ khác, nếu bạn sử dụng một chuỗi trong Listdanh sách đối số của hàm, các phần tử của nó sẽ tự động được mở rộng thành các vị trí riêng biệt. Vì thế

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

Bây giờ, trong các hàm thuần túy ##hoặc ##1là một chuỗi tất cả các đối số. Tương tự, ##2là một chuỗi gồm tất cả các đối số bắt đầu từ giây, ##3tất cả các đối số bắt đầu từ thứ ba, v.v. Vì vậy, để bắt đầu, chúng ta chỉ có thể thực hiện lại Sequencenhư là ##&, tiết kiệm 5 byte. Như một cách sử dụng ví dụ, điều này cung cấp cho chúng ta một giải pháp thay thế cho Join@@list(xem mẹo này ), không lưu bất kỳ byte nào, nhưng dù sao cũng nên biết về:

 ##&@@@list

Điều này có hiệu quả làm phẳng cấp độ đầu tiên của một danh sách lồng nhau. Chúng ta có thể làm gì khác với điều này? Đây là một thay thế ngắn hơn 2 byte để RotateLeft:

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

Đối với những điều này một mình nó đáng để giữ tính năng này trong tâm trí. Tuy nhiên, chúng ta có thể làm tốt hơn! Trình tự thực sự thú vị khi xem xét rằng các nhà khai thác thực sự được thực hiện như các chức năng dưới mui xe. Ví dụ a+bthực sự đánh giá Plus[a,b]. Vì vậy, nếu chúng ta đưa ra một chuỗi ...

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

Thủ thuật này đã được sử dụng trong mẹo này để tiết kiệm một byte Times, bởi vì juxtap vị trí về mặt kỹ thuật cũng chỉ là một toán tử:

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

Bạn cũng có thể sử dụng nó để lưu một byte Unequalnếu bạn có một giá trị ký tự hoặc biến mà bạn biết không có trong các đối số của mình ( Ncó thể sẽ hoạt động trong 99% trường hợp):

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

Điều này thậm chí còn thú vị hơn với các toán tử đơn nguyên -/- hai cái sau thực sự được thực hiện theo phương pháp nhân và lũy thừa. Dưới đây là danh sách những điều bạn có thể làm, trong đó cột cuối cùng giả định rằng hàm đã được truyền các đối số 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

Toán tử phổ biến khác là !=, ==, &&, ||. Những người ít phổ biến cần lưu ý là |, @*, /*. Để kết luận, đây là một mẹo nhỏ tiền thưởng:

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

Tiếp tục thử nghiệm với những điều này và cho tôi biết nếu bạn tìm thấy bất kỳ ứng dụng hữu ích hoặc đặc biệt thú vị nào khác!


15

Sqrt@2hoặc 2^.5=>√2

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

#+#2&=>+##&

Flatten@a=> Join@@a(đôi khi)

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


1
Lưu ý rằng khi đo bằng byte, sử dụng lấy 3 byte mỗi byte (giả sử UTF8)
user202729

12

Toán tử là Hàm

Lấy cảm hứng từ khám phá gần đây của Dennis cho Julia, tôi nghĩ rằng tôi sẽ xem xét điều này cho Mathematica. Tôi đã biết rằng Mathicala định nghĩa một số lượng lớn các toán tử không sử dụng, nhưng không bao giờ chú ý đến nó.

Để tham khảo, danh sách tất cả các toán tử có thể được tìm thấy ở đây dưới dạng bảng ưu tiên. Hình tam giác trong cột cuối cùng cho biết toán tử đó có nghĩa tích hợp hay không. Mặc dù không phải tất cả những thứ không thể được định nghĩa dễ dàng, nhưng hầu hết chúng có thể.

Thuận tiện, có hai toán tử không được sử dụng với một mật mã nhỏ hơn 256, sao cho chúng có thể được sử dụng dưới dạng các byte đơn trong tệp nguồn được mã hóa ISO 8859-1:

  • ± (0xB1) có thể được sử dụng làm toán tử tiền tố đơn nguyên hoặc toán tử nhị phân nhị phân.
  • · (0xB7) có thể được sử dụng như một toán tử infixic hoặc n-ary, cho n> 2.

Mặc dù có thêm một nhược điểm: vì một số lý do kỳ lạ khi xác định các toán tử này, bạn cần một khoảng trắng ở phía trước chúng, hoặc nếu không, Mathicala cố gắng phân tích một phép nhân. Khi sử dụng chúng, bạn không cần bất kỳ khoảng trắng nào:

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

So sánh điều này với:

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

Vì vậy, điều này tiết kiệm một byte khi xác định hàm và hai byte khi sử dụng nó. Lưu ý rằng định nghĩa ·sẽ không lưu byte cho bốn toán hạng và sẽ bắt đầu tính phí byte cho nhiều toán hạng hơn, nhưng việc sử dụng vẫn có thể lưu byte, tùy thuộc vào các toán tử được sử dụng trong các đối số. Cũng tốt để lưu ý rằng bạn có thể định nghĩa một hàm giá rẻ mà sau đó được gọi là hiệu quả hơn nhiều:

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

Nhưng lưu ý rằng không thể dễ dàng gọi các hàm biến đổi này bằng một đối số duy nhất. (Bạn có thể làm CenterDot[x]hoặc ##&[]·xnhưng nếu bạn thực sự cần điều đó thì rất có thể bạn sẽ tốt hơn với một giải pháp khác.)

Tất nhiên, điều này không tiết kiệm bất cứ điều gì cho các giải pháp khi hàm không được đặt tên đủ, nhưng đôi khi bạn cần xác định các hàm trợ giúp để sử dụng sau này và đôi khi nó ngắn hơn để xác định các hàm được đặt tên, ví dụ như để thiết lập các định nghĩa khác nhau cho các tham số khác nhau. Trong những trường hợp đó, sử dụng toán tử thay vào đó có thể tiết kiệm được một lượng byte kha khá.

Lưu ý rằng việc sử dụng các tệp được mã hóa ISO 8859-1 này yêu cầu $CharacterEncodingphải được đặt thành giá trị tương thích, như mặc định của Windows WindowsANSI. Trên một số hệ thống, mặc định UTF-8này sẽ không thể đọc các điểm mã này từ các byte đơn.


Điều này thực sự tuyệt vời, tôi không biết Mathematica có một danh sách các toán tử, và thậm chí bao gồm cả quyền ưu tiên của chúng. Hai toán tử mà bạn tìm thấy tôi chắc chắn sẽ có ích.
dặm

8

Chọn giá trị dựa trên số nguyên

Cách tiếp cận ngây thơ phải lựa chọn giữa yz, tùy thuộc vào việc x0hay 1

If[x<1,y,z]

Tuy nhiên, có một cách ngắn hơn:

y[z][[x]]

Điều này hoạt động vì [[0]]đưa ra Headbiểu thức, trong trường hợp này y, trong khi [[1]]chỉ đưa ra phần tử đầu tiên - trong trường hợp này là đối số đầu tiên , z.

Bạn thậm chí có thể sử dụng điều này để chọn giữa nhiều hơn hai giá trị:

u[v,w][[x]]

Lưu ý rằng điều này sẽ không hoạt động nếu ulà một chức năng thực sự đánh giá một cái gì đó. Điều quan trọng là Mathicala giữ nguyên u[v,w]như vậy. Tuy nhiên, điều này hoạt động trong hầu hết các trường hợp, bao gồm nếu ulà một số, một chuỗi hoặc một danh sách.

Tín dụng cho thủ thuật này đi đến alephalpha - tôi đã phát hiện ra điều này trong một trong những câu trả lời của anh ấy.

Nếu xlà dựa trên 1 thay vì dựa trên không, chỉ cần sử dụng

{y,z}[[x]]

hoặc là

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

Trong một số trường hợp hiếm hoi, bạn thậm chí có thể sử dụng thực tế là phép nhân không được đánh giá cho một số giá trị:

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

Lưu ý rằng Mathicala thực sự sẽ sắp xếp lại các đối số, của phép nhân nếu nó vẫn chưa được đánh giá, do đó, ở trên giống hệt với

("def""abc")[[x]]

8

Các lựa chọn thay thế cho Length

Điều này đã được viết lại hoàn toàn với một số gợi ý từ LegionMammal978 và Misha Lavrov. Rất cám ơn cả hai.

Trong nhiều trường hợp, Lengthcó thể rút ngắn một chút bằng cách sử dụng Tr. Ý tưởng cơ bản là biến đầu vào thành một danh sách 1s, sao cho Trtổng hợp chúng sau đó sẽ bằng độ dài của danh sách.

Cách phổ biến nhất để làm điều này là sử dụng 1^x(cho một danh sách x). Này hoạt động vì PowerListable1^nđối với hầu hết các giá trị nguyên tử nđược chỉ 1(bao gồm tất cả các số, chuỗi và biểu tượng). Vì vậy, chúng ta đã có thể lưu một byte với điều này:

Length@x
Tr[1^x]

Tất nhiên, điều này giả định rằng đó xlà một biểu thức có độ ưu tiên cao hơn ^.

Nếu xchỉ chứa 0s và 1s, chúng ta có thể lưu một byte khác bằng cách sử dụng Factorial(giả sử xcó độ ưu tiên cao hơn !):

Length@x
Tr[x!]

Trong một số trường hợp hiếm hoi, xcó thể có độ ưu tiên thấp hơn ^nhưng vẫn có độ ưu tiên cao hơn phép nhân. Trong trường hợp đó, nó cũng sẽ có mức độ ưu tiên thấp hơn @, vì vậy chúng tôi thực sự cần phải so sánh với Length[x]. Một ví dụ về một toán tử như vậy là .. Trong những trường hợp đó, bạn vẫn có thể lưu một byte với dạng này:

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

Cuối cùng, một số nhận xét về loại danh sách này hoạt động trên:

Như đã đề cập ở trên cùng, điều này hoạt động trên danh sách phẳng chỉ chứa số, chuỗi và ký hiệu. Tuy nhiên, nó cũng sẽ hoạt động trên một số danh sách sâu hơn, mặc dù nó thực sự tính toán một cái gì đó hơi khác. Đối với mảng hình chữ nhật n -D, việc sử dụng Trcung cấp cho bạn kích thước ngắn nhất (trái ngược với kích thước đầu tiên). Nếu bạn biết rằng kích thước ngoài cùng là ngắn nhất hoặc bạn biết rằng tất cả chúng đều giống nhau, so với kích thước Trvẫn tương đương Length.


3
Chỉ cần tìm một giải pháp thậm chí ngắn hơn : Length@x == Tr[1^x]. Nên làm việc với hầu hết các danh sách.
LegionMammal978

@ LegionMammal978 thật tuyệt vời, cảm ơn :). Tôi sẽ sớm chỉnh sửa nó.
Martin Ender

1
Hai lần bây giờ, tôi thấy mình sử dụng Tr[x!]thay vì Tr[1^x]để lưu một byte trong trường hợp đặc biệt xchỉ chứa số không và số không.
Misha Lavrov

@MishaLavrov Thật là gọn gàng! :)
Martin Ender

7
  1. Khám phá các giải pháp đệ quy - Mathematica là đa mô hình, nhưng cách tiếp cận chức năng thường là kinh tế nhất. NestWhilecó thể là một giải pháp rất nhỏ gọn để tìm kiếm các vấn đề NestWhileListFoldListrất mạnh mẽ khi bạn cần trả về hoặc xử lý kết quả của các lần lặp trung gian. Map (/@), Apply (@@, @@@), MapThread, Và thực sự mọi thứ trên Wolfram của lập trình chức năng trang tài liệu là công cụ mạnh.

  2. Biểu mẫu rút gọn để tăng / giảm - Ví dụ: thay vì While[i<1,*code*;i++]bạn có thể làm
    While[i++<1,*code*]

  3. Đừng quên bạn có thể tăng / giảm trước - Ví dụ, --ithay vì i--. Điều này đôi khi có thể giúp bạn tiết kiệm một vài byte trong mã xung quanh bằng cách loại bỏ một hoạt động chuẩn bị.

  4. Hệ quả với Số 5 của David Carraher: Khi cùng một chức năng được sử dụng nhiều lần, việc gán một biểu tượng cho nó có thể tiết kiệm byte. Ví dụ: nếu bạn đang sử dụng ToExpression4 lần trong một giải pháp, t=ToExpressioncho phép bạn sử dụng t@*expression*sau đó. Tuy nhiên, trước khi bạn thực hiện việc này, hãy xem xét liệu ứng dụng lặp lại của cùng chức năng có cho thấy cơ hội cho cách tiếp cận đệ quy kinh tế hơn không.


MapThreadthường có thể được thay thế bởi \[Transpose]. TIO .
dùng202729

7

Đừng sử dụng {}nếu bạn đang sử dụng @@@.

Trong một số trường hợp, bạn có thể gặp một biểu thức như:

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

Có thể giảm byte bằng cách viết:

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

Alternativescó độ ưu tiên rất thấp, do đó, nói chung là ổn khi viết biểu thức (một ngoại lệ đáng chú ý là các hàm thuần túy; bạn chỉ có thể sử dụng nó trong phần tử ngoài cùng bên trái Alternatives).

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

Lưu ý rằng f@@a|b|c(thay vì f@@{a,b,c}) không hoạt động vì Applycó độ ưu tiên cao hơn Alternative.

Trong trường hợp này, bạn chỉ cần sử dụng f@@{a,b,c}.


6

Toán học chỉ 10

Hình thức khai thác

Mathematica 10 hỗ trợ cái gọi là "biểu mẫu toán tử", về cơ bản có nghĩa là một số chức năng có thể được sử dụng. Kết hợp một chức năng là tạo ra một chức năng mới bằng cách sửa một trong các toán tử của nó. Giả sử, bạn đang sử dụng SortBy[list, somereallylongfunction&]rất nhiều lists khác nhau . Trước đây, bạn có lẽ sẽ được gán SortBycho svà chức năng tinh khiết đến fvậy

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

Bây giờ bạn có thể cà ri SortBy, có nghĩa là bây giờ bạn có thể làm

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

Các công trình tương tự cho rất nhiều các chức năng khác, trong đó có một danh sách hoặc chức năng lập luận, bao gồm (nhưng không giới hạn) Select, Map, Nearestvv

ybeltukov trên Mathematica.SE đã có thể tạo ra một danh sách đầy đủ về những điều này :

{"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"}

Thành phần và RightCysis

Có các tốc ký mới cho Composition( @*) và RightComposition( /*). Một ví dụ rõ ràng được đặt ra trong đó những cái này có thể lưu các ký tự được nhìn thấy trong ba dòng tương đương sau

Last@Range@# & /@ Range[5]
Last@*Range /@ Range[5]
Range /* Last /@ Range[5]

5

Không viết các hàm 0 đối số

Không cần mã như thế này:

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

Bạn chỉ có thể sử dụng một biến với :=để đánh giá lại phía bên tay phải:

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

Điều này cũng có nghĩa là bạn có thể đặt bí danh cho bất kỳ hành động nào mà bạn thực hiện thường xuyên (ngay cả khi đó chỉ là một cái gì đó giống như n++) với một ký tự với giá 5 byte. Vì vậy, trong trường hợp n++nó trả lại sau lần sử dụng thứ tư:

n++;n++;n++;n++
f:=n++;f;f;f;f

5

Sử dụng %để có được một biến miễn phí

Mẹo này chỉ có thể áp dụng nếu môi trường REPL của Mathicala có thể được giả định. %không được xác định khi mã được chạy dưới dạng tập lệnh.

Khi bạn có thể sử dụng các tính năng REPL, đừng làm điều này:

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

Thay vào đó, hãy nhớ rằng Mathicala lưu trữ biểu thức được đánh giá cuối cùng (kết thúc dòng mới) trong %:

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

Dòng mới được thêm vào có giá một byte, nhưng bạn đang tiết kiệm hai bằng cách loại bỏ a=, do đó, tổng thể này sẽ tiết kiệm được một byte.

Trong một số trường hợp (ví dụ: khi bạn muốn in giá trị bằng amọi cách), bạn thậm chí có thể bỏ qua ;, lưu hai byte:

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

Một hoặc hai byte có vẻ khá nhỏ, nhưng đây là một trường hợp quan trọng, vì nó làm cho việc trích xuất các biểu thức lặp lại (đây là một kỹ thuật rất phổ biến) hữu ích hơn nhiều khi chơi golf:

Kỹ thuật bình thường để trích xuất các biểu thức lặp đi lặp lại tốn bốn byte chi phí, cần được lưu lại bằng cách sử dụng thêm biểu thức. Dưới đây là một bảng ngắn về số lần sử dụng tối thiểu của một biểu thức (theo độ dài của biểu thức) để trích xuất thành một biến được đặt tên để lưu bất cứ thứ gì:

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

Bằng cách sử dụng biến không tên, có thể lưu một vài byte thường xuyên hơn:

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

Tôi không nghĩ %%hoặc %ncó thể được sử dụng để chơi gôn, bởi vì nếu bạn không sử dụng chúng ít nhất hai lần, bạn có thể đặt biểu thức ngay khi cần. Và nếu bạn sử dụng nó hai lần, ký tự bổ sung trong tên biến sẽ hủy bỏ khoản tiết kiệm từ việc bỏ qua một số x=.


Lưu ý rằng nó không hoạt động trong chế độ tập lệnh.
alephalpha

@alephalpha Chế độ tập lệnh là gì?
Martin Ender


@alephalpha Ồ đúng rồi, tôi tắt não ở đó trong một giây ... vì vậy điều đó có nghĩa là nó hoàn toàn không thể được sử dụng, trừ khi môi trường REPL có thể được giả định.
Martin Ender

5

Kiểm tra nếu một danh sách được sắp xếp

Đây thực chất là một hệ quả tất yếu của mẹo này nhưng đây là một nhiệm vụ đủ phổ biến mà tôi nghĩ rằng nó đảm bảo câu trả lời của chính nó.

Cách ngây thơ để kiểm tra nếu một danh sách theo thứ tự là sử dụng

OrderedQ@a

Chúng ta có thể làm tốt hơn một byte với

Sort@a==a

Tuy nhiên, điều này không hoạt động nếu chúng ta chưa có thứ chúng ta muốn kiểm tra một biến. (Chúng ta cần một cái gì Sort[a=...]==ađó dài đến mức không cần thiết.) Tuy nhiên, có một lựa chọn khác:

#<=##&@@a

Điều tốt nhất là điều này có thể được sử dụng để kiểm tra xem đầu vào có được sắp xếp ngược lại cho cùng một số byte hay không:

#>=##&@@a

Có thể lưu thêm một byte nếu a) chúng ta biết rằng các thành phần danh sách là khác biệt và b) chúng ta biết giới hạn dưới từ 0 đến 9 (bao gồm; hoặc giới hạn trên cho thứ tự sắp xếp ngược):

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

Để xem lý do tại sao điều này hoạt động, hãy xem "Chuỗi các đối số" trong mẹo được liên kết ở trên cùng.


Ngoài ra, (nghiêm ngặt) giới hạn dưới để sắp xếp ngược cũng hoạt động : ##>0&@@a. Tương tự cho giới hạn trên để sắp xếp.
dùng202729

@ user202729 Ôi điểm tốt, cứ thoải mái chỉnh sửa (nếu không tôi sẽ thử làm vào cuối tuần nếu tôi nhớ).
Martin Ender

5

Lặp lại một chuỗi

Thay vì StringRepeat[str,n]sử dụng (0Range[n]+str)<>"". Hoặc nếu strkhông phụ thuộc vào bất kỳ đối số vị trí nào, thậm chí tốt hơn là Array[str&,n]<>""theo mẹo này .


1
Hệ quả: thay vì StringRepeat[s,n+1]sử dụng Array[s&,n]<>s(ngay cả khi bạn đã có sẵn n+1một biến).
Martin Ender

Tốt hơn,Table[str,n]<>""
attinat

5

Nếu bạn cần một danh sách các số được sắp xếp ngược lại, không sử dụng

Reverse@Sort@x

nhưng

-Sort@-x

để lưu sáu byte. Sắp xếp theo giá trị âm cũng hữu ích cho các SortBytình huống:

Reverse@SortBy[x,Last]
SortBy[x,-Last@#&]

2
Thế còn -Sort@-x?
JungHwan Min

1
@JungHwanMin Oh, uhhh, yeah, tốt hơn nhiều. :)
Martin Ender

4

Bạn có thể dán một biểu thức trong Breakđó có thể lưu một hoặc hai ký tự. Ví dụ ( các chi tiết khác không được đánh golf cho rõ ràng ):

result = False;
Break[]

có thể biến thành

Break[result = False]

để lưu một nhân vật. Nếu biểu thức trong câu hỏi không có độ ưu tiên thấp hơn ứng dụng hàm, bạn thậm chí có thể lưu một ký tự khác:

Print@x;
Break[]

có thể biến thành

Break@Print@x

Mặc dù không có giấy tờ, nhưng đối số Breakdường như được trả về bởi vòng lặp xung quanh, điều này có khả năng dẫn đến tiết kiệm hơn nữa.


4

Để xóa tất cả khoảng trắng khỏi chuỗi s, sử dụng

StringSplit@s<>""

Đó là, sử dụng StringSplitmặc định (chia thành các thành phần không phải khoảng trắng) và chỉ cần nối chúng lại với nhau. Điều tương tự có lẽ vẫn là ngắn nhất nếu bạn muốn loại bỏ bất kỳ ký tự hoặc chuỗi con nào khác:

s~StringSplit~"x"<>""

4

Các lựa chọn thay thế cho Range

Một nhiệm vụ rất phổ biến là áp dụng một số loại hàm cho tất cả các số từ 1 đến a n(thường được đưa ra làm đầu vào). Về cơ bản có 3 cách để làm điều này (sử dụng hàm nhận dạng không tên làm ví dụ):

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

Tôi có xu hướng đi cho người đầu tiên (vì bất kỳ lý do gì), nhưng điều này hiếm khi là sự lựa chọn tốt nhất.

Sử dụng Arraythay thế

Ví dụ trên cho thấy việc sử dụng Arraycó cùng số byte. Tuy nhiên, nó có lợi thế là nó là một biểu thức duy nhất. Cụ thể, nếu bạn muốn xử lý thêm kết quả bằng một hàm, fbạn có thể sử dụng ký hiệu tiền tố, giúp lưu một byte qua Range:

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

Hơn nữa, bạn có thể bỏ qua dấu ngoặc đơn xung quanh hàm không tên mà bạn có thể cần với Range, ví dụ:

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

Nếu bạn không muốn sử dụng nó thêm (hoặc với một toán tử có mức độ ưu tiên thấp hơn), thay vào đó bạn có thể Arraytự viết bằng ký hiệu infix và cũng lưu một byte:

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

Do đó, Arraygần như chắc chắn là tốt hơn Range.

Sử dụng Tablethay thế

Bây giờ bảng phải chiếm 3 byte hoặc ít nhất là 2 khi ký hiệu infix là một tùy chọn:

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

Khi không sử dụng ký hiệu infix, Tablecó thể cho phép bạn bỏ qua dấu ngoặc đơn nếu hàm của bạn bao gồm một số câu lệnh:

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

Điều này vẫn còn lâu hơn, nhưng cung cấp thêm tiền tiết kiệm trong trường hợp được đề cập dưới đây.

Các khoản tiết kiệm thực sự xuất phát từ thực tế là Tablekhông nên loại bỏ tên biến đang chạy. Thông thường, bạn sẽ có các hàm không được lồng trong đó bạn muốn sử dụng biến ngoài trong một trong các hàm bên trong. Khi điều đó xảy ra, Tablengắn hơn Range:

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

Bạn không chỉ lưu các ký tự để gán i, bạn còn có thể giảm hàm thành một câu lệnh trong quy trình, cho phép bạn sử dụng ký hiệu infix trên đầu nó. Để tham khảo, Arraycũng dài hơn trong trường hợp này, nhưng vẫn ngắn hơn Range:

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

Khi nào bạn thực sự sử dụng Range?

Bất cứ khi nào bạn không cần một hàm gọi để xử lý các giá trị, ví dụ khi ánh xạ có thể được thực hiện thông qua thao tác véc tơ. Ví dụ:

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

Tất nhiên, nó cũng ngắn hơn nếu bạn không muốn ánh xạ bất kỳ chức năng nào, vd

Mean@Array[#&,n]
Mean@Range@n

Cuối cùng, một người khác sử dụng f/@Range[x]thường xuyên ...
LegionMammal978

4

Tìm số nhỏ nhất thỏa mãn điều kiện

Một số cấu trúc như thế i=1;While[cond[i],i++]là tốt, nhưng có một cách thay thế ngắn hơn hai byte:

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

Đoạn mã trên nhiều lần thay thế một số ivới i+1khi nó đáp ứng điều kiện cond[i]. Trong trường hợp này, ibắt đầu tại 1.

Lưu ý rằng số lần lặp tối đa mặc định là 2 ^ 16 (= 65536). Nếu bạn cần nhiều lần lặp hơn thế, Whilesẽ tốt hơn. ( MaxIterations->∞quá dài)


4

Lạm dụng đánh giá ngắn mạch

Đôi khi bạn có thể thay thế Ifbằng một toán tử logic.

Chẳng hạn, giả sử bạn muốn tạo một hàm kiểm tra xem một số có phải là số nguyên tố hay không và in 2*(number) - 1có đúng không:

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

Nó ngắn hơn nếu bạn sử dụng &&thay thế:

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

Ngay cả khi bạn có nhiều biểu thức, bạn vẫn lưu byte (s):

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

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

Bạn có thể sử dụng ||cho các trường hợp khi bạn muốn điều kiện là False:

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

Những thủ thuật này hoạt động vì các toán tử logic có thể bị ngắn mạch ; đối số thứ hai và sau đó thậm chí không cần phải là biểu thức boolean hợp lệ.

Tất nhiên, điều này không hoạt động nếu bạn cần giá trị trả về Ifhoặc khi bạn cần cả hai đối số trung thực và giả dối If.



3

Sử dụng Optional (:)

Optional (:) có thể được sử dụng để mở rộng danh sách trong các thay thế, mà không phải xác định quy tắc riêng cho việc mở rộng.

Câu trả lời này của tôicâu trả lời này của @ngenisis là ví dụ.

Sử dụng

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

Sự thay thế ở trên trước tiên sử dụng mẫu {p___, a_, b_, q___}và tìm một kết quả khớp với bmột điều kiện nhất định.

Khi không tìm thấy kết quả khớp như vậy, nó sẽ bỏ qua a_và thay vào đó tìm kiếm {p___, b_, q___}. akhông được bao gồm trong tìm kiếm và được coi là có giá trị 0.

Lưu ý rằng tìm kiếm mẫu thứ hai sẽ chỉ hoạt động cho bđiều đó xảy ra ở đầu danh sách; nếu một bgiá trị thỏa mãn một điều kiện ở giữa, thì {p___, a_, b_, q___}(có độ ưu tiên cao hơn) sẽ khớp với nó.

Sự thay thế tương đương với việc chuẩn bị trước 0khi bmột điều kiện thỏa mãn xảy ra ở đầu danh sách. (tức là không cần xác định quy tắc riêng, {b_, q___} /; cond[b] :> ...)


3

Biết khi nào (và khi nào không) sử dụng các đối số hàm thuần có tên

Đối với mã golf, các Functionđối số thuần túy được tham chiếu phổ biến nhất bằng Slots; ví dụ #cho đối số thứ nhất, #2cho đối số thứ hai, v.v. (xem câu trả lời này để biết thêm chi tiết).

Trong nhiều trường hợp, bạn sẽ muốn làm tổ Functions. Ví dụ, 1##&@@#&là một Functiondanh sách lấy danh sách làm đối số đầu tiên của nó và đưa ra sản phẩm của các phần tử của nó. Đây là chức năng trong TreeForm:

nhập mô tả hình ảnh ở đây

Các đối số được chuyển đến cấp cao Functionnhất chỉ có thể điền vào Slots và SlotSequences ở cấp cao nhất, trong trường hợp này có nghĩa là SlotSequencebên trong Functionsẽ không có bất kỳ cách nào để truy cập các đối số lên cấp cao nhất Function.

Tuy nhiên, trong một số trường hợp, bạn có thể muốn một Functionlồng trong một cái khác Functionđể có thể tham chiếu các đối số ra bên ngoài Function. Ví dụ, bạn có thể muốn một cái gì đó như Array[fun,...]&, trong đó hàm funphụ thuộc vào một đối số đến cấp cao nhất Function. Để cụ thể, hãy nói rằng funnên cho phần còn lại của bình phương modulo đầu vào của nó ở mức cao nhất Function. Một cách để thực hiện điều này là gán đối số cấp cao nhất cho một biến:

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

Bất cứ nơi nào xxuất hiện ở bên trong Function Mod[#^2,x]&, nó sẽ đề cập đến đối số đầu tiên ở bên ngoài Function, trong khi đó #sẽ đề cập đến đối số đầu tiên cho bên trong Function. Cách tiếp cận tốt hơn là sử dụng thực tế Functioncó hai dạng đối số trong đó đối số đầu tiên là ký hiệu hoặc danh sách các ký hiệu sẽ biểu thị các đối số được đặt tên cho Function(trái ngược với Slots không được đặt tên ). Điều này kết thúc việc tiết kiệm cho chúng tôi ba byte trong trường hợp này:

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

là ký tự sử dụng riêng ba byte U+F4A1đại diện cho toán tử infix nhị phân \[Function]. Bạn cũng có thể sử dụng hình thức nhị phân của Functionbên trong khác Function:

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

Điều này tương đương với ở trên. Lý do là, nếu bạn đang sử dụng các đối số được đặt tên, thì Slots và SlotSequencesđược coi là thuộc về bên Functiontrên mà không sử dụng các đối số được đặt tên.

Bây giờ chỉ vì chúng ta có thể làm tổ Functiontheo cách này, không có nghĩa là chúng ta luôn luôn nên như vậy. Ví dụ: nếu chúng tôi muốn chọn ra các yếu tố của danh sách nhỏ hơn đầu vào, chúng tôi có thể bị cám dỗ làm điều gì đó như sau:

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

Nó thực sự sẽ ngắn hơn để sử dụng Casesvà tránh sự cần thiết phải lồng Functionhoàn toàn:

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

2

Bạn có thể lưu một byte bằng cách làm việc xung quanh Prependhoặc PrependTo:

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

hoặc là

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

Thật không may, điều này không giúp ích cho phổ biến hơn Append, dường như là tương đương ngắn nhất với một Array.push()ngôn ngữ khác.


2

Toán học 10.2: BlockMapPartition+Map

Mẹo này cũng có thể có tiêu đề, "Đọc ghi chú phát hành, tất cả chúng". (Để tham khảo, đây là ghi chú phát hành cho 10.2ở đây là bản phát hành 10.3 hôm nay .)

Dù sao, ngay cả các bản phát hành nhỏ cũng chứa vô số tính năng mới và một trong những tính năng hữu ích hơn (để chơi gôn) từ 10.2 là BlockMapchức năng mới . Về cơ bản , nó kết hợp PartitionMap, rất phù hợp với người chơi golf, vì Partitionđược sử dụng khá thường xuyên và đó là một tên chức năng thực sự khó chịu. Hàm mới sẽ không tự rút ngắn Partition, nhưng bất cứ khi nào bạn muốn ánh xạ một hàm lên các phân vùng (điều này có thể xảy ra thường xuyên hơn không), giờ đây bạn có thể lưu một hoặc hai byte:

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

Khoản tiết kiệm thậm chí còn lớn hơn khi vị trí mới của hàm không tên cho phép bạn tự lưu một số dấu ngoặc đơn:

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

Thật không may, tôi không biết tại sao họ cũng không thêm vào BlockApplykhi họ ở đó ...

Cũng lưu ý rằng BlockMapkhông hỗ trợ tham số thứ 4 mà bạn có thể sử dụng Partitionđể có danh sách tuần hoàn:

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

2

Lưu trữ các hàm và biểu thức trong một biến

Nếu câu trả lời của bạn kết thúc bằng cách sử dụng cùng một hàm hoặc biểu thức nhiều lần, bạn có thể muốn xem xét việc lưu trữ chúng trong các biến.

Nếu biểu thức của bạn là độ dài lvà bạn sử dụng nó nlần, nó thường sẽ sử dụng hết l * nbyte.

Tuy nhiên, nếu bạn lưu trữ nó trong biến có độ dài 1, nó sẽ chỉ mất 3 + l + nbyte (hoặc 2 + l + nbyte, nếu bạn chỉ định biến mà bạn sẽ không cần CompoundExpression (;)hoặc dấu ngoặc đơn).


Ví dụ: chúng ta hãy xem xét một vấn đề đơn giản, tìm các số nguyên tố sinh đôi ít hơn N.

Người ta có thể viết giải pháp 54 byte này:

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

Trong ví dụ này, hàm PrimeQđược sử dụng ba lần.

Bằng cách gán PrimeQtên biến, số byte có thể giảm. Cả hai điều sau đây là 48 byte (54 - 6 byte):

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

2

Để đạt được danh sách khóa-giá trị tăng dần, hãy sử dụng Sortthay vìSortBy

Đối với các danh sách như list = {{1, "world"}, {0, "universe"}, {2, "country"}}, ba tuyên bố sau gần như tương đương.

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

Kết hợp SelectSortBy

Đôi khi chúng ta cần chọn các mục trong một tập lớn hơn và sắp xếp chúng để tìm mức tối thiểu / tối đa. Trong một số trường hợp , hai hoạt động có thể được kết hợp thành một.

Ví dụ, ở mức tối thiểu, hai câu lệnh sau gần như tương đương nhau.

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

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

1/0ComplexInfinity, "lớn hơn" so với tất cả các số thực.

Đối với danh sách khóa-giá trị, ví dụ:

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

1

Làm phẳng một Arrayvới##&

Khi sử dụng Mảng nhiều chiều để tính toán danh sách các kết quả cần được làm phẳng, hãy sử dụng ##&làm đối số thứ tư. Điều này thay thế các đầu của Mảng bằng ##&(tương đương Sequence) thay vì List, vì vậy kết quả cuối cùng sẽ là (bằng phẳng) Sequencekết quả.

Trong hai chiều, so sánh

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

Tất nhiên, Join@@Array[f,dims] vẫn là 2 (hoặc 3, nếu ký hiệu infix có thể được sử dụng) byte ngắn hơn {Array[f,dims,1,##&]}.

Trong ba chiều trở lên, {Array[f,dims,origin,##&]}luôn luôn ngắn hơn so với thay thế, ngay cả khi gốc là 1.

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

1

Giá trị mặc định

Các giá trị mặc định xử lý các đối số mẫu bị thiếu một cách hiệu quả. Ví dụ: nếu chúng ta muốn khớp mẫu Exp[c_*x]theo quy tắc cho bất kỳ giá trị nào c, thì ngây thơ

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

sử dụng nhiều byte hơn nếu chúng ta sử dụng giá trị mặc định cho cbất cứ khi nào nó bị thiếu:

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

Việc sử dụng mặc định được biểu thị bằng dấu chấm sau mẫu : c_..

Các giá trị mặc định được liên kết với các hoạt động: trong ví dụ trên, thao tác nằm Timestrong c_.*xc_do đó , một giá trị bị thiếu được lấy từ giá trị mặc định được liên kết với Times, đó là 1. Đối với Plus, giá trị mặc định là 0:

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

Đối với Powersố mũ, mặc định là 1:

x + x^2 /. x^n_. -> p[n]
(*    p[1] + p[2]    *)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.