เคล็ดลับสำหรับการเล่นกอล์ฟใน Mathematica


41

คุณมีเคล็ดลับทั่วไปสำหรับการเล่นกอล์ฟใน Mathematica หรือไม่? ฉันกำลังมองหาแนวคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะกับ Mathematica (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ)

คำตอบ:


30

เคล็ดลับด้านล่างแตกต่างกันไปจากที่ประหยัดที่สุดไปสู่การใช้บ่อยที่สุด:

  1. ใช้คำสั่งระดับสูงของ Mathematica ถ้าเป็นไปได้แม้คำสั่งใหญ่ ๆ :

  2. ใช้Graphics and Textสำหรับ Ascii art: เช่นการเขียนโปรแกรม Star! และสร้างนาฬิกาอะนาล็อก

  3. สัญลักษณ์เฉพาะ:

    • สัญลักษณ์ลอจิกและตั้งค่าการดำเนินงานแทนชื่อแบบยาว: ⋂, ⋃, ∧, ∨

    • MapและApply: /@, //@. @@,@@@

  4. สัญลักษณ์คำนำหน้าและมัด:

    • Print@"hello" แทน Print["hello"]

    • a~f~b แทน f[a,b]

  5. เมื่อฟังก์ชั่นใช้เพียงครั้งเดียวฟังก์ชั่นแท้อาจประหยัดอักขระหรือสอง

  6. การเข้าร่วมสตริงในรายการ ""<>{"a","b","c"}แทนStringJoin@{"a","b","c"}

  7. ใช้ประโยชน์จากฟังก์ชั่นที่ฟังได้ รายการยิ่งยาวยิ่งดี

    {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
มันมักจะสั้นจะเขียนแทน(Norm[#-#2]&) EuclideanDistance
user202729

32

ฟังก์ชันในตัวบางตัวที่มีชื่อยาวสามารถแทนที่ด้วยนิพจน์ที่สั้นลง

ตัวอย่างเช่น:

  • Total => Tr
  • Transpose=> Threadหรือ\[Transpose]
  • True => 1<2
  • False => 1>2
  • Times => 1##&
  • Alternatives => $|##&
  • IntegerQ => ⌊#⌋==#&
  • a[[1]] => #&@@a
  • a[[All,1]] => #&@@@a
  • ConstantArray[a,n]=> Array[a&,n]หรือTable[a,{n}]
  • Union@a=> {}⋃aหรือa⋃a
  • ToExpression@n=> FromDigits@nถ้าnเป็นตัวเลข
  • Divisible[n,m] => m∣n
  • FromDigits[n,2]=> Fold[#+##&,n]ถ้าnเป็นรายการของ0s และ1s
  • Complex@z=> {1,I}.zซึ่งzเป็นรายการของแบบฟอร์ม{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
ผมคิดว่าคุณFoldเคล็ดลับสำหรับการFromDigitsทำงานกับฐานอื่น ๆ 10ยกเว้น เช่นFromDigits[n,5]-> Fold[4#+##&,n](พร้อมโบนัสการบันทึกไบต์พิเศษสำหรับฐาน100และ1000)
Martin Ender

1
@ mbomb007 3 ไบต์ใน UTF-8 U+F3C7ในความเป็นจริงตัวละครตัวนี้คือ
alephalpha

1
ในที่สุดฉันก็ติดตั้ง 10.3 หากเรากำลังพิจารณาโปรแกรมเต็มรูปแบบฉันไม่คิดว่าEchoเป็นตัวเลือกเพราะจะพิมพ์>>(และที่ว่าง) ไปยัง STDOUT ก่อนที่จะพิมพ์สตริงจริง
Martin Ender

2
สำหรับComplex[x,y] => {1,I}.{x,y}ฉันคิดว่าx+y*Iสั้นกว่ามากที่มีผลเหมือนกันหรือไม่
Shieru Asakoto

22

รายการที่มีค่าซ้ำ

นี่เป็นเวกเตอร์ทั่วไปที่ใช้งานได้:

{0,0}

ปรากฎว่าสิ่งนี้สามารถทำให้สั้นลงโดยไบต์:

0{,}

ไบต์ยิ่งมากขึ้นจะถูกบันทึกหากเวกเตอร์ยาวกว่าสองศูนย์ สิ่งนี้ยังสามารถใช้ในการเริ่มต้นศูนย์ฝึกอบรมเช่นต่อไปนี้ให้เมทริกซ์ 2x2 ของศูนย์:

0{{,},{,}}

นอกจากนี้ยังสามารถใช้สำหรับค่าที่ไม่ใช่ศูนย์ได้หากมีขนาดใหญ่พอหรือมากพอหรือติดลบ เปรียบเทียบคู่ต่อไปนี้:

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

แต่จำไว้ว่าเริ่มต้นที่ 6 ค่าคุณจะดีกว่า1~Table~6ในกรณีนี้ (อาจเร็วกว่านี้ขึ้นอยู่กับข้อกำหนดก่อนหน้า)

เหตุผลที่งานนี้คือการที่,แนะนำสองข้อโต้แย้งในรายการ แต่ข้อโต้แย้งละเว้น (ที่ใดก็ได้ในมาติกา) เป็นนัยNulls นอกจากนี้การคูณListableและ0*xเป็น0เกือบ ๆx(ยกเว้นสำหรับสิ่งที่ต้องการInfinityและIndeterminate) ดังนั้นนี่คือสิ่งที่เกิดขึ้น:

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

สำหรับรายการของ1คุณสามารถใช้เคล็ดลับที่คล้ายกันโดยใช้กฎการยกกำลัง มีวิธีการบันทึกไบต์ที่ต่างกันสองวิธีหากคุณมีอย่างน้อยสาม1รายการในรายการ:

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

7
+1; นี่เป็นเพียงการแสดงให้เห็นว่าในขณะที่ Mathematica อาจมีอุปกรณ์ในตัวสำหรับทุกสิ่งการเล่นกอล์ฟในนั้นอาจเป็นความท้าทายที่แท้จริง
LegionMammal978

หากคุณต้องการอาร์เรย์ที่เต็มไปด้วยในที่สุด 1s แล้วเป็นหนึ่งไบต์มีขนาดเล็กกว่า1^{,,,} 0{,,,}+1
Misha Lavrov

@MishaLavrov โอ้จับได้ดี {,,}^0ที่ทำให้มันสั้นที่สามค่าและคุณยังสามารถใช้ ฉันจะแก้ไขโพสต์
Martin Ender

19

รู้ว่าข้อโต้แย้งฟังก์ชั่นบริสุทธิ์ของคุณ

เมื่อตีกอล์ฟรหัสคุณมักจะใช้วิธีการทำงานที่คุณใช้ฟังก์ชั่นที่ไม่ระบุชื่อ (บริสุทธิ์) กับ&ไวยากรณ์ชวเลข มีหลายวิธีในการเข้าถึงอาร์กิวเมนต์ของฟังก์ชั่นดังกล่าวและคุณมักจะสามารถปัดทิ้งสองไบต์ด้วยการเข้าใจถึงความเป็นไปได้

การเข้าถึงอาร์กิวเมนต์เดียว

คุณอาจจะรู้สิ่งนี้ถ้าคุณเคยใช้ฟังก์ชั่นบริสุทธิ์มาก่อน nอาร์กิวเมนต์ TH จะเรียกว่าเป็น#nและทำหน้าที่เป็นนามแฝงสำหรับ# #1ดังนั้นถ้าพูดว่าคุณต้องการที่จะเขียนฟังก์ชั่นที่ใช้เป็นพารามิเตอร์ฟังก์ชั่นอื่นและการโต้แย้ง (เพื่อส่งผ่านอาร์กิวเมนต์ไปยังฟังก์ชั่นนั้น) ให้ใช้

#@#2&

สิ่งนี้ใช้ไม่ได้กับจำนวนลบ (เช่นคุณอาจใช้เมื่อเข้าถึงรายการ)

การเข้าถึงอาร์กิวเมนต์ที่มีชื่อ (ใหม่ใน V10)

หนึ่งในฟีเจอร์ภาษาใหม่ที่สำคัญใน Mathematica 10 คือAssociations ซึ่งโดยทั่วไปแล้วเป็นแผนที่ค่าคีย์ที่มีประเภทของคีย์โดยพลการเขียนเช่น

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

หากการเชื่อมโยงดังกล่าวถูกส่งผ่านเป็นอาร์กิวเมนต์แรกไปยังฟังก์ชันบริสุทธิ์คุณสามารถเข้าถึงบางอย่างถ้าอาร์กิวเมนต์เป็นพารามิเตอร์ที่มีชื่อ:

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

โปรดทราบว่า#ยังคงหมายถึงการเชื่อมโยงทั้งหมดตามที่คาดไว้ เพื่อให้พารามิเตอร์ที่มีชื่อใช้งานได้คีย์จะต้องเป็นสตริง (จะไม่ทำงานหากคุณใช้ตัวแปรที่ไม่ได้กำหนดเป็นต้น) และสตริงเหล่านั้นจะต้องเริ่มต้นด้วยตัวอักษรและประกอบด้วยตัวอักษรและตัวเลขเท่านั้น

อาร์กิวเมนต์ "ตัวเอง" #0

คุณลักษณะที่รู้จักกันน้อยกว่านั้น#0มีอยู่และให้ฟังก์ชันวัตถุแก่คุณเอง สิ่งนี้มีประโยชน์จริง ๆ ใน quines และ quines ทั่วไป อันที่จริงแล้ว Mathematica quine ที่สั้นที่สุด (ที่ฉันรู้จัก) ก็คือ

ToString[#0][] & []

สิ่งที่น่ารำคาญเล็กน้อยคือมันจะไม่ให้อักขระที่คุณป้อน เช่นหากใช้@สำหรับแอปพลิเคชันฟังก์ชั่นมันจะยังคงแสดงผลเป็น[...]และช่องว่างจะถูกแทรกในบางสถานที่ โดยปกติจะทำให้ควินินค่อนข้างยาวกว่าที่คุณต้องการ แต่มันจะใช้ได้เสมอโดยการเล่นควินินก่อนแล้วจึงคัดลอกเอาท์พุทซึ่งตอนนี้น่าจะเป็นควินจริง

นอกเหนือจาก quines นี่ยังหมายความว่าคุณสามารถเขียนโค้ดแบบเรียกซ้ำโดยไม่ต้องตั้งชื่อฟังก์ชั่นของคุณ เปรียบเทียบการใช้งาน Fibonacci ทั้งสาม (ไร้เดียงสา แต่เล่นกอล์ฟ):

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

ลำดับของการขัดแย้ง

ตอนนี้นี่คือจุดเริ่มต้นของเวทมนตร์ที่แท้จริง ลำดับไม่ได้ถูกใช้บ่อยในการเล่นกอล์ฟเพราะSequenceเป็นชื่อที่ยาวเกินกว่าจะคุ้มค่ามากที่สุด แต่ฟังก์ชั่นบริสุทธิ์เป็นที่ที่พวกเขาเปล่งประกาย หากคุณไม่คุ้นเคยกับการเรียงลำดับโดยทั่วไปแล้วมันจะเหมือนกับเครื่องหมายในภาษาอื่น ๆ ถ้าคุณใช้ลำดับในListหรือรายการอาร์กิวเมนต์ของฟังก์ชั่นองค์ประกอบก็จะถูกขยายเป็นช่องแยกโดยอัตโนมัติ ดังนั้น

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

ตอนนี้ในฟังก์ชั่นบริสุทธิ์##หรือ##1เป็นลำดับของการขัดแย้งทั้งหมด ในทำนองเดียวกัน##2เป็นลำดับของข้อโต้แย้งทั้งหมดที่เริ่มต้นจากที่สอง##3ข้อโต้แย้งทั้งหมดที่เริ่มต้นจากที่สาม ฯลฯ ดังนั้นสำหรับการเริ่มต้นเราก็สามารถนำมาใช้อีกครั้งSequenceเป็น##&บันทึก 5 ไบต์ ในตัวอย่างการใช้งานสิ่งนี้ให้ทางเลือกแก่เราJoin@@list(ดูเคล็ดลับนี้ ) ซึ่งไม่ได้บันทึกไบต์ใด ๆ แต่เป็นการดีที่ควรทราบ:

 ##&@@@list

สิ่งนี้จะทำให้ระดับแรกของรายการซ้อนกันอย่างมีประสิทธิภาพ เราสามารถทำอะไรกับเรื่องนี้ได้อีก? นี่คือทางเลือกที่สั้นลง 2 ไบต์ไปที่RotateLeft:

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

สำหรับสิ่งเหล่านี้เพียงอย่างเดียวก็คุ้มค่าที่จะคำนึงถึงคุณลักษณะนี้ไว้ในใจ อย่างไรก็ตามเราทำได้ดีกว่า! ลำดับได้น่าสนใจจริง ๆ เมื่อพิจารณาว่าตัวดำเนินการถูกนำมาใช้จริงเป็นฟังก์ชันภายใต้ประทุน เช่นจริงประเมินa+b Plus[a,b]ดังนั้นถ้าเราให้ลำดับนั้น ...

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

เคล็ดลับนี้มีการใช้ในเคล็ดลับนี้เพื่อบันทึกไบต์Timesเนื่องจากการตีข่าวเป็นเทคนิคเพียงผู้ประกอบการ:

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

คุณยังสามารถใช้มันเพื่อบันทึกไบต์Unequalหากคุณมีค่าอักขระเดียวหรือตัวแปรที่คุณรู้ว่าไม่ได้อยู่ในข้อโต้แย้งของคุณ ( Nอาจจะทำงานใน 99% ของกรณี):

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

สิ่งนี้น่าสนใจยิ่งขึ้นกับตัวดำเนินการเอกและ-และ/- สองอันหลังถูกนำมาใช้จริงในแง่ของการคูณและการยกกำลัง นี่คือรายการของสิ่งที่คุณสามารถทำได้โดยที่คอลัมน์สุดท้ายถือว่าฟังก์ชั่นถูกส่งผ่านการขัดแย้ง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

ผู้ประกอบการอื่น ๆ ที่มีร่วมกัน!=, ==, ,&& ||คนน้อยกว่าปกติจะเก็บไว้ในใจ|, ,@* /*เพื่อสรุปนี่เป็นเคล็ดลับโบนัสเล็กน้อย:

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

ทดลองต่อไปกับสิ่งเหล่านี้และแจ้งให้เราทราบหากคุณพบแอปพลิเคชั่นที่มีประโยชน์หรือน่าสนใจอื่น ๆ !


15

Sqrt@2หรือ2^.5=>√2

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

#+#2&=>+##&

Flatten@a=> Join@@a(บางครั้ง)

Function[x,x^2]=> xx^2หรือ#^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
โปรดทราบว่าเมื่อทำการวัดจำนวนไบต์ให้ใช้และใช้แต่ละ 3 ไบต์ (สมมติว่าเป็น UTF8)
user202729

12

ผู้ประกอบการเป็นฟังก์ชั่น

แรงบันดาลใจจากการค้นพบล่าสุดของ Dennis สำหรับ Juliaฉันคิดว่าฉันจะมองเรื่องนี้สำหรับ Mathematica ฉันทราบว่า Mathematica กำหนดผู้ประกอบการที่ไม่ได้ใช้เป็นจำนวนมาก แต่ไม่เคยให้ความสนใจกับมันมากนัก

สำหรับการอ้างอิงรายการของตัวดำเนินการทั้งหมดสามารถดูได้ที่นี่ในรูปแบบของตารางนำหน้า สามเหลี่ยมในคอลัมน์สุดท้ายบ่งชี้ว่าตัวดำเนินการนั้นมีความหมายในตัวหรือไม่ ในขณะที่ไม่ทั้งหมดที่ไม่สามารถกำหนดได้ง่าย แต่ส่วนใหญ่สามารถ

สะดวกสบายมีโอเปอเรเตอร์ที่ไม่ได้ใช้สองตัวที่มี codepoint น้อยกว่า 256 ซึ่งสามารถใช้เป็นไบต์เดียวในไฟล์ต้นฉบับที่เข้ารหัส ISO 8859-1:

  • ± (0xB1) สามารถใช้เป็นตัวดำเนินการส่วนหน้าของ unary หรือตัวดำเนินการไบนารีแบบไบนารี
  • · (0xB7) สามารถใช้เป็นตัวดำเนินการตัวแปรหรือ n-ary infix สำหรับ n> 2

มีอีกหนึ่งเหตุผลที่จับได้: ด้วยเหตุผลแปลก ๆ บางอย่างเมื่อกำหนดโอเปอเรเตอร์เหล่านี้คุณต้องมีที่ว่างหนึ่งอันอยู่ข้างหน้าพวกเขามิฉะนั้น Mathematica จะพยายามแยกการคูณ เมื่อใช้พวกเขาคุณไม่จำเป็นต้องมีช่องว่างใด ๆ :

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

เปรียบเทียบกับ:

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

ดังนั้นนี่ช่วยประหยัดหนึ่งไบต์เมื่อกำหนดฟังก์ชันและสองไบต์เมื่อใช้งาน โปรดทราบว่าคำจำกัดความของ·จะไม่บันทึกไบต์สำหรับตัวถูกดำเนินการสี่ตัวและจะเริ่มคิดต้นทุนไบต์สำหรับตัวถูกดำเนินการเพิ่มเติม แต่การใช้งานอาจยังคงบันทึกไบต์ขึ้นอยู่กับลำดับความสำคัญของตัวดำเนินการที่ใช้ในอาร์กิวเมนต์ นอกจากนี้ยังเป็นการดีที่จะทราบว่าคุณสามารถกำหนดฟังก์ชัน Variadic ที่สามารถเรียกได้อย่างมีประสิทธิภาพมากขึ้น:

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

แต่โปรดทราบว่ามันเป็นไปไม่ได้ที่จะเรียกฟังก์ชัน Variadic เหล่านี้ด้วยอาร์กิวเมนต์เดียว (คุณสามารถทำได้CenterDot[x]หรือ##&[]·xแต่ถ้าคุณต้องการมีโอกาสที่ดีกว่าคุณจะได้ทางออกที่ดีกว่า)

แน่นอนว่านี่ไม่ได้บันทึกอะไรเลยสำหรับการแก้ปัญหาที่ฟังก์ชั่นที่ไม่ได้ตั้งชื่อ แต่บางครั้งคุณจำเป็นต้องกำหนดฟังก์ชั่นตัวช่วยสำหรับใช้ในภายหลังและบางครั้งมันสั้นลงในการกำหนดฟังก์ชั่นที่มีชื่อ ในกรณีดังกล่าวการใช้โอเปอเรเตอร์แทนสามารถบันทึกจำนวนไบต์ที่เหมาะสม

หมายเหตุว่าการใช้มาตรฐาน ISO 8859-1 ไฟล์ที่เข้ารหัสเหล่านี้ต้องมีการตั้งค่าให้เป็นค่าที่เข้ากันได้เช่นเริ่มต้นของ$CharacterEncoding Windows WindowsANSIในบางระบบค่าเริ่มต้นนี้UTF-8จะไม่สามารถอ่านจุดรหัสเหล่านี้ได้จากไบต์เดียว


นี่เป็นสิ่งที่ยอดเยี่ยมจริงๆฉันไม่รู้ว่า Mathematica มีรายชื่อผู้ให้บริการและยังรวมถึงความสำคัญของพวกเขาด้วย สองผู้ให้บริการที่คุณพบฉันแน่ใจว่าจะมีประโยชน์
ไมล์

8

การเลือกค่าตามจำนวนเต็ม

วิธีการไร้เดียงสาที่จะเลือกระหว่างyและzขึ้นอยู่กับว่าxเป็น0หรือ1เป็น

If[x<1,y,z]

อย่างไรก็ตามมีวิธีที่สั้นกว่า:

y[z][[x]]

งานนี้เพราะ[[0]]จะช่วยให้Headการแสดงออกในกรณีนี้yในขณะที่[[1]]เพียงแค่ช่วยให้องค์ประกอบแรก - zในกรณีนี้อาร์กิวเมนต์แรก

คุณสามารถใช้สิ่งนี้เพื่อเลือกค่ามากกว่าสองค่า:

u[v,w][[x]]

โปรดทราบว่าสิ่งนี้จะไม่ทำงานหากuเป็นฟังก์ชันที่ประเมินค่าจริง ๆ มันเป็นสิ่งสำคัญที่ Mathematica ยังคงu[v,w]เป็นเช่นเดิม อย่างไรก็ตามวิธีนี้ใช้งานได้ในกรณีส่วนใหญ่รวมถึงถ้าuเป็น a คือตัวเลขสตริงหรือรายการ

เครดิตสำหรับเคล็ดลับนี้ไปที่ alephalpha - ฉันค้นพบสิ่งนี้ในหนึ่งในคำตอบของเขา

หากใช้แบบx1 แทนเป็นศูนย์ให้ใช้

{y,z}[[x]]

หรือ

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

ในบางกรณีที่หายากคุณสามารถใช้ประโยชน์จากความจริงที่ว่าการคูณจะไม่ถูกประเมินสำหรับค่าบางอย่าง:

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

หมายเหตุว่าที่ Mathematica จริงจะสั่งซื้อข้อโต้แย้งของการคูณถ้ามันยังคง unevaluated ดังนั้นที่กล่าวมาเป็นเหมือนการ

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

8

ทางเลือกในการ Length

สิ่งนี้ถูกเขียนใหม่ทั้งหมดพร้อมคำแนะนำจาก LegionMammal978 และ Misha Lavrov ขอบคุณมากสำหรับพวกเขาทั้งคู่

ในหลายกรณีจะสั้นลงเล็กน้อยโดยการใช้Length Trแนวคิดพื้นฐานคือการเปลี่ยนอินพุตให้เป็นรายการของ1s เพื่อหาTrผลรวมเหล่านั้นซึ่งจะเท่ากับความยาวของรายการ

วิธีที่พบได้บ่อยที่สุดคือการใช้1^x(สำหรับรายการx) งานนี้Powerเป็นเพราะListableและ1^nสำหรับค่าอะตอมส่วนใหญ่nเป็นเพียง1(รวมถึงตัวเลขสตริงและสัญลักษณ์ทั้งหมด) ดังนั้นเราจึงสามารถบันทึกหนึ่งไบต์ด้วย:

Length@x
Tr[1^x]

ของหลักสูตรนี้อนุมานว่าคือการแสดงออกที่มีลำดับความสำคัญสูงกว่าx^

หากxมีเพียง0s และ1s เราสามารถบันทึก byte อื่นโดยใช้Factorial(สมมติว่าxมีลำดับความสำคัญสูงกว่า!):

Length@x
Tr[x!]

ในบางกรณีที่หายากxอาจมีความสำคัญต่ำกว่า^แต่ยังคงมีความสำคัญมากกว่าการคูณ ในกรณีที่ว่ามันยังจะมีความสำคัญต่ำกว่าดังนั้นเราจึงจำเป็นจริงๆที่จะเปรียบเทียบกับ@ ตัวอย่างของการดำเนินการดังกล่าวเป็นLength[x] .ในกรณีเหล่านี้คุณยังสามารถบันทึกไบต์ด้วยแบบฟอร์มนี้:

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

ในที่สุดข้อสังเกตบางประการเกี่ยวกับรายการประเภทนี้ใช้งานได้ใน:

ดังที่กล่าวไว้ด้านบนสิ่งนี้ใช้ได้กับรายการแบบเรียบที่มีเฉพาะตัวเลขสตริงและสัญลักษณ์เท่านั้น อย่างไรก็ตามมันจะทำงานกับบางรายการที่ลึกกว่าแม้ว่ามันจะคำนวณสิ่งที่แตกต่างออกไปเล็กน้อย สำหรับอาร์เรย์สี่เหลี่ยมn -D การใช้Trจะให้มิติที่สั้นที่สุด (ตรงข้ามกับอาร์เรย์แรก) ถ้าคุณรู้ว่ามิติด้านนอกสุดเป็นที่สั้นที่สุดหรือคุณรู้ว่าพวกเขากำลังทั้งหมดเดียวกันกว่าTr-expressions Lengthยังคงเทียบเท่ากับ


3
เพิ่งพบทางออกที่สั้นกว่านี้: Length@x == Tr[1^x]. ควรทำงานกับรายการส่วนใหญ่
LegionMammal978

@ LegionMammal978 มันเยี่ยมมากขอบคุณ :) ฉันจะแก้ไขในไม่ช้า
Martin Ender

1
สองครั้งฉันพบว่าตัวเองใช้Tr[x!]แทนTr[1^x]การบันทึกหนึ่งไบต์ในกรณีพิเศษที่xประกอบด้วยศูนย์และคน
Misha Lavrov

@MishaLavrov มันเรียบร้อยจริงๆ! :)
Martin Ender

7
  1. สำรวจโซลูชันแบบเรียกซ้ำ - Mathematica เป็นกระบวนทัศน์แบบหลากหลาย แต่วิธีการทำงานมักจะประหยัดที่สุด NestWhileอาจเป็นวิธีแก้ปัญหาที่กะทัดรัดมากในการค้นหาปัญหาNestWhileListและFoldListมีประสิทธิภาพเมื่อคุณต้องการส่งคืนหรือประมวลผลผลลัพธ์ของการทำซ้ำขั้นกลาง Map (/@), Apply (@@, @@@), MapThreadและจริงๆทุกอย่างบนวุลแฟรมของหน้าที่ Programmingหน้าเอกสารเป็นสิ่งที่มีศักยภาพ

  2. รูปแบบย่อสำหรับการเพิ่ม / ลด - ตัวอย่างเช่นแทนที่จะWhile[i<1,*code*;i++]ทำ
    While[i++<1,*code*]

  3. อย่าลืมคุณสามารถ pre-เพิ่มขึ้น / ลดลง - ยกตัวอย่างเช่นแทน--i i--บางครั้งวิธีนี้จะช่วยให้คุณประหยัดเวลาได้ไม่กี่ไบต์ในโค้ดที่ล้อมรอบโดยกำจัดการดำเนินการเตรียมการ

  4. ข้อสรุปของ David Carraher # 5: เมื่อใช้ฟังก์ชันเดียวกันหลายครั้งการกำหนดสัญลักษณ์ให้สามารถบันทึกเป็นไบต์ได้ ตัวอย่างเช่นหากคุณใช้ToExpressionโซลูชั่น 4 ครั้งt=ToExpressionคุณจะสามารถใช้งานได้ในt@*expression*ภายหลัง อย่างไรก็ตามก่อนที่คุณจะทำสิ่งนี้ให้พิจารณาว่าแอปพลิเคชันซ้ำของฟังก์ชั่นเดียวกันบ่งชี้โอกาสสำหรับวิธีเรียกซ้ำที่ประหยัดกว่าหรือไม่


MapThread\[Transpose]มักจะถูกแทนที่ด้วย TIO
user202729

7

อย่าใช้ถ้าคุณกำลังใช้{}@@@

ในบางกรณีคุณอาจพบนิพจน์เช่น:

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

เป็นไปได้ที่จะลดจำนวนไบต์ด้วยการเขียน:

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

Alternativesมีลำดับความสำคัญต่ำมากดังนั้นจึงเป็นเรื่องปกติที่จะเขียนนิพจน์ (ข้อยกเว้นที่น่าสังเกตก็คือฟังก์ชั่นบริสุทธิ์คุณสามารถใช้มันได้เฉพาะในองค์ประกอบด้านซ้ายสุดของAlternatives)

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

โปรดทราบว่าf@@a|b|c(แทนf@@{a,b,c}) ไม่ทำงานเพราะมีความสำคัญสูงกว่าApplyAlternative

f@@{a,b,c}ในกรณีนี้คุณก็ควรใช้


6

Mathematica 10 เท่านั้น

แบบฟอร์มผู้ประกอบการ

Mathematica 10 รองรับ "แบบฟอร์มผู้ปฏิบัติงาน" ซึ่งโดยทั่วไปหมายถึงฟังก์ชั่นบางอย่างที่สามารถแก้ไขได้ การปิดฟังก์ชั่นคือการสร้างฟังก์ชั่นใหม่โดยแก้ไขตัวดำเนินการตัวใดตัวหนึ่ง สมมติว่าคุณกำลังใช้s ที่SortBy[list, somereallylongfunction&]แตกต่างกันlistมากมาย ก่อนหน้านี้คุณอาจจะได้รับมอบหมายSortByให้sและฟังก์ชั่นบริสุทธิ์fเพื่อ

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

ตอนนี้คุณสามารถแกงเผ็ดSortByซึ่งหมายความว่าคุณสามารถทำได้

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

งานเดียวกันสำหรับจำนวนมากของฟังก์ชั่นอื่น ๆ ที่ใช้รายการหรือฟังก์ชั่นการโต้แย้งรวมถึง ( แต่ไม่ จำกัด เฉพาะการบริการ) Select, Map, Nearestฯลฯ

ybeltukov มากกว่าบน Mathematica.SE สามารถสร้างรายการที่สมบูรณ์ของสิ่งเหล่านี้ :

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

องค์ประกอบและความเหมาะสม

มีชวเลขใหม่สำหรับComposition( @*) และRightComposition( /*) ตัวอย่างที่เห็นได้ชัดของการประดิษฐ์ที่สามารถบันทึกอักขระได้ในสามบรรทัดต่อไปนี้

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

5

อย่าเขียนฟังก์ชัน 0 อาร์กิวเมนต์

ไม่จำเป็นต้องใช้รหัสเช่นนี้:

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

คุณสามารถใช้ตัวแปร:=เพื่อบังคับให้ทำการประเมินทางด้านขวาอีกครั้ง:

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

นอกจากนี้ยังหมายความว่าคุณสามารถตั้งชื่อแทนการกระทำใด ๆ ที่คุณทำบ่อย ๆ (แม้ว่าจะเป็นเพียงบางอย่างn++) ไปยังอักขระตัวเดียวที่มีราคา 5 ไบต์ ดังนั้นในกรณีที่n++จ่ายคืนหลังจากการใช้ครั้งที่สี่:

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

5

ใช้%เพื่อรับตัวแปรฟรี

เคล็ดลับนี้ใช้ได้เฉพาะเมื่อสภาพแวดล้อม REPL ของ Mathematica สามารถนำมาใช้ได้ %ไม่ได้ถูกกำหนดเมื่อมีการเรียกใช้รหัสเป็นสคริปต์

เมื่อคุณสามารถใช้ประโยชน์จากคุณสมบัติ REPL อย่าทำสิ่งนี้:

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

โปรดจำไว้ว่า Mathematica เก็บการแสดงออกล่าสุด (ขึ้นบรรทัดใหม่) ที่ประเมินใน%:

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

ขึ้นบรรทัดใหม่ค่าใช้จ่ายไบต์ แต่คุณจะประหยัดสองโดยการลบa=ดังนั้นโดยรวมนี้จะบันทึกหนึ่งไบต์

ในบางกรณี (เช่นเมื่อคุณต้องการพิมพ์ค่าของaต่อไป) คุณสามารถออกจากการ;บันทึกสองไบต์:

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

หนึ่งหรือสองไบต์อาจดูค่อนข้างเล็ก แต่นี่เป็นกรณีที่สำคัญเพราะมันทำให้การแสดงออกซ้ำ (ซึ่งเป็นเทคนิคที่พบบ่อยมาก) มีประโยชน์มากขึ้นเมื่อเล่นกอล์ฟ:

เทคนิคปกติของการแยกนิพจน์ซ้ำนั้นมีค่าใช้จ่ายสี่ไบต์ของค่าโสหุ้ยซึ่งจำเป็นต้องได้รับการบันทึกโดยการใช้นิพจน์เพิ่มเติม นี่คือตารางย่อของจำนวนการใช้งานขั้นต่ำของนิพจน์ (ตามความยาวของนิพจน์) สำหรับการแยกไปยังตัวแปรที่ระบุชื่อเพื่อบันทึกสิ่งใด ๆ :

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

โดยการใช้ตัวแปรที่ไม่มีชื่อมันจะเป็นไปได้ที่จะบันทึกสองสามไบต์บ่อยขึ้น:

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

ฉันไม่คิด%%หรือ%nสามารถนำไปใช้เล่นกอล์ฟได้เพราะถ้าคุณไม่ใช้อย่างน้อยสองครั้งคุณก็สามารถแสดงออกได้ในที่ที่ต้องการ x=และถ้าคุณใช้มันสองครั้งตัวละครเพิ่มเติมในชื่อตัวแปรยกเลิกออกเงินฝากออมทรัพย์จากถนัดบาง


โปรดทราบว่ามันไม่ทำงานในโหมดสคริปต์
alephalpha

@alephalpha โหมดสคริปต์คืออะไร
Martin Ender

สคริปต์ Mathematica
alephalpha

@alephalpha โอ้ถูกต้องฉันปิดสมองของฉันที่นั่นสักครู่ ... นั่นหมายความว่ามันไม่สามารถใช้งานได้เลยเว้นแต่ว่าจะมีสภาพแวดล้อม REPL
Martin Ender

5

ตรวจสอบว่ารายการเรียงลำดับหรือไม่

นี่เป็นข้อสรุปที่สำคัญของเคล็ดลับนี้แต่นี่เป็นงานทั่วไปที่เพียงพอที่ฉันคิดว่ามันรับประกันคำตอบของตัวเอง

วิธีการที่ไร้เดียงสาเพื่อตรวจสอบว่ารายการนั้นมีการใช้งานหรือไม่

OrderedQ@a

เราสามารถทำได้ดีกว่าหนึ่งไบต์

Sort@a==a

อย่างไรก็ตามสิ่งนี้ใช้ไม่ได้หากเราไม่มีสิ่งที่เราต้องการตรวจสอบในตัวแปรแล้ว (เราต้องการบางสิ่งSort[a=...]==aที่มีความยาวเกินความจำเป็น) อย่างไรก็ตามมีตัวเลือกอื่น:

#<=##&@@a

สิ่งที่ดีที่สุดคือสามารถใช้เพื่อตรวจสอบว่าอินพุตถูกเรียงกลับกันสำหรับจำนวนไบต์เดียวกันหรือไม่:

#>=##&@@a

สามารถบันทึกได้อีกหนึ่งไบต์ถ้าก) เรารู้ว่าองค์ประกอบของรายการนั้นแตกต่างกันและข) เรารู้ขอบเขตที่ต่ำกว่าระหว่าง 0 และ 9 (รวม; หรือขอบบนสำหรับลำดับที่เรียงกลับกัน):

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

หากต้องการดูว่าเหตุใดจึงใช้งานได้ตรวจสอบ "ลำดับของอาร์กิวเมนต์" ในเคล็ดลับลิงก์ที่ด้านบน


หรืออีกทางหนึ่ง (เข้มงวด) ##>0&@@aลดที่ถูกผูกไว้สำหรับย้อนกลับเรียงยังทำงาน: คล้ายกับขอบบนสำหรับการเรียงลำดับ
user202729

@ user202729 โอ้จุดที่ดีอย่าลังเลที่จะแก้ไข (มิฉะนั้นฉันจะพยายามทำในวันหยุดสุดสัปดาห์ถ้าจำได้)
Martin Ender

5

ทำซ้ำสตริง

แทนการใช้งานStringRepeat[str,n] (0Range[n]+str)<>""หรือถ้าstrไม่ได้ขึ้นอยู่กับข้อโต้แย้งสล็อตใด ๆ ได้ดียิ่งขึ้นเป็นArray[str&,n]<>""ตามนี้เคล็ดลับ


1
ข้อสรุป: แทนที่จะStringRepeat[s,n+1]ใช้Array[s&,n]<>s(แม้ว่าคุณจะn+1มีตัวแปรอยู่แล้วก็ตาม)
Martin Ender

ดีกว่าTable[str,n]<>""
attinat

5

หากคุณต้องการรายการตัวเลขเรียงกลับกันอย่าใช้

Reverse@Sort@x

แต่

-Sort@-x

เพื่อบันทึกหกไบต์ การเรียงลำดับตามค่าลบยังมีประโยชน์สำหรับSortByสถานการณ์:

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

2
เกี่ยวกับ-Sort@-xอะไร
JungHwan Min

1
@JungHwanMin โอ้เอ่อใช่แล้วมันดีกว่ามาก :)
Martin Ender

4

คุณสามารถใช้นิพจน์Breakที่สามารถบันทึกอักขระหนึ่งหรือสองตัว ตัวอย่าง ( รายละเอียดอื่น ๆ ที่ไม่ได้ตีกอล์ฟเพื่อความชัดเจน ):

result = False;
Break[]

สามารถเปลี่ยนเป็น

Break[result = False]

เพื่อบันทึกอักขระหนึ่งตัว หากการแสดงออกในคำถามไม่ได้มีความสำคัญต่ำกว่าฟังก์ชั่นการใช้งานคุณสามารถบันทึกตัวละครอื่น:

Print@x;
Break[]

สามารถเปลี่ยนเป็น

Break@Print@x

แม้ว่าจะไม่มีเอกสารก็ตาม แต่ข้อโต้แย้งที่Breakดูเหมือนว่าจะถูกส่งกลับโดยวนรอบซึ่งอาจนำไปสู่การออมที่มากขึ้น


4

ในการลบช่องว่างทั้งหมดออกจากสตริงsให้ใช้

StringSplit@s<>""

นั่นคือใช้StringSplitค่าเริ่มต้นของ (แยกเป็นองค์ประกอบที่ไม่ใช่ช่องว่าง) และเพียงแค่รวมพวกเขากลับมารวมกัน เช่นเดียวกันอาจยังสั้นที่สุดหากคุณต้องการกำจัดอักขระหรือสตริงย่อยอื่น ๆ :

s~StringSplit~"x"<>""

4

ทางเลือกในการ Range

งานที่พบบ่อยมากคือการใช้ฟังก์ชั่นบางอย่างกับทุกหมายเลขจาก 1 ถึง a n(โดยปกติจะให้เป็นอินพุต) โดยพื้นฐานแล้วมี 3 วิธีในการทำเช่นนี้ (ใช้ฟังก์ชันเอกลักษณ์ที่ไม่มีชื่อเป็นตัวอย่าง):

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

ฉันมักจะไปหาคนแรก (ด้วยเหตุผลอะไรก็ตาม) แต่นี่ไม่ค่อยเป็นทางเลือกที่ดีที่สุด

ใช้Arrayแทน

ตัวอย่างด้านบนแสดงว่าการใช้Arrayมีจำนวนไบต์เท่ากัน อย่างไรก็ตามมันมีข้อได้เปรียบที่เป็นนิพจน์เดียว โดยเฉพาะอย่างยิ่งถ้าคุณต้องการประมวลผลผลลัพธ์เพิ่มเติมด้วยฟังก์ชันfคุณสามารถใช้สัญลักษณ์นำหน้าซึ่งบันทึกไบต์ไว้Range:

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

นอกจากนี้คุณสามารถละเว้นวงเล็บในฟังก์ชันที่ไม่มีชื่อซึ่งคุณอาจต้องการRangeเช่น

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

หากคุณไม่ต้องการใช้งานเพิ่มเติม (หรือกับโอเปอเรเตอร์ที่มีลำดับความสำคัญน้อยกว่า) คุณสามารถเขียนArrayตัวเองในรูปแบบสัณฐานวิทยาและบันทึกไบต์ได้ด้วย:

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

ดังนั้นเป็นเกือบแน่นอนดีกว่าArrayRange

ใช้Tableแทน

ตอนนี้ตารางจะต้องสร้างขึ้น 3 ไบต์หรืออย่างน้อย 2 เมื่อสัญกรณ์มัดเป็นตัวเลือก:

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

เมื่อไม่ใช้สัญกรณ์ของ infix Tableอาจอนุญาตให้คุณละเว้นเครื่องหมายวงเล็บถ้าฟังก์ชันของคุณประกอบด้วยหลายข้อความ:

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

สิ่งนี้ยังคงอยู่อีกต่อไป แต่ให้การออมพิเศษด้วยในกรณีที่กล่าวถึงด้านล่าง

การประหยัดที่แท้จริงเกิดจากความจริงที่Tableทำให้ชื่อตัวแปรไม่ควรถูกไล่ออก บ่อยครั้งที่คุณมีฟังก์ชั่นที่ไม่ได้ตั้งชื่อซ้อนกันซึ่งคุณต้องการใช้ตัวแปรด้านนอกภายในหนึ่งในฟังก์ชั่นด้านใน เมื่อสิ่งนั้นเกิดขึ้นTableจะสั้นกว่าRange:

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

คุณไม่เพียง แต่บันทึกอักขระสำหรับการกำหนดiเท่านั้นคุณยังสามารถลดฟังก์ชันให้เป็นคำสั่งเดียวในกระบวนการซึ่งช่วยให้คุณใช้สัญกรณ์ที่ผูกไว้ด้านบน สำหรับการอ้างอิงArrayในกรณีนี้จะยาวกว่า แต่ก็ยังสั้นกว่าRange:

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

คุณจะใช้จริงเมื่อRangeใด

เมื่อใดก็ตามที่คุณไม่ต้องการการเรียกใช้ฟังก์ชันเพื่อประมวลผลค่าเช่นเมื่อการแมปสามารถทำได้ผ่านการดำเนินการแบบเวกเตอร์ ตัวอย่างเช่น

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

แน่นอนว่ามันสั้นกว่าเช่นกันถ้าคุณไม่ต้องการแมปฟังก์ชั่นใด ๆ เลยเช่น

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

ในที่สุดคนอื่นที่ใช้f/@Range[x]เป็นประจำ ...
LegionMammal978

4

การค้นหาจำนวนที่น้อยที่สุดที่ตรงตามเงื่อนไข

บางสิ่งที่สร้างเช่นi=1;While[cond[i],i++]นี้เป็นเรื่องปกติ แต่มีทางเลือกที่สั้นกว่าสองไบต์:

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

รหัสข้างต้นซ้ำ ๆ แทนตัวเลขiด้วยในขณะที่มันเป็นไปตามเงื่อนไขi+1 cond[i]ในกรณีนี้จะเริ่มต้นที่i1

โปรดทราบว่าจำนวนการทำซ้ำสูงสุดเริ่มต้นคือ 2 ^ 16 (= 65536) หากคุณต้องการการวนซ้ำมากกว่านั้นWhileจะดีกว่า ( MaxIterations->∞ยาวเกินไป)


4

การละเมิดการประเมินผลการลัดวงจร

บางครั้งคุณสามารถแทนที่Ifด้วยตัวดำเนินการเชิงตรรกะ

ตัวอย่างเช่นสมมติว่าคุณต้องการสร้างฟังก์ชันที่ตรวจสอบว่าตัวเลขนั้นเป็นจำนวนเฉพาะหรือไม่และพิมพ์2*(number) - 1ได้ถ้ามันเป็นจริง:

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

จะสั้นกว่านี้หากคุณใช้&&แทน:

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

แม้ว่าคุณจะมีหลายนิพจน์คุณยังคงบันทึกไบต์:

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

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

คุณสามารถใช้||สำหรับกรณีเมื่อคุณต้องการเงื่อนไขเป็นFalse:

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

เทคนิคเหล่านี้ทำงานเพราะผู้ประกอบการลอจิคัลสามารถลัดวงจร ; อาร์กิวเมนต์ที่สองและหลังจากนั้นไม่จำเป็นต้องเป็นนิพจน์บูลีนที่ถูกต้อง

ของหลักสูตรนี้ไม่ทำงานถ้าคุณต้องการค่าตอบแทนของIfหรือเมื่อคุณจำเป็นต้องใช้ทั้ง truthy Ifและข้อโต้แย้งของ


3

นี่คือรายการที่มีรูปแบบการป้อนข้อมูลของตัวดำเนินการที่สามารถย่อจำนวนมากได้ บางส่วนได้รับการกล่าวถึงในโพสต์อื่น ๆ แต่รายการมีความยาวและฉันมักจะประหลาดใจที่พบสิ่งใหม่ไม่กี่:


อย่างไรก็ตามวิธีนี้ใช้ได้เฉพาะเมื่อตัวดำเนินการใช้ UTF-8 น้อยกว่า
LegionMammal978

3

การใช้ Optional (:)

Optional (:) สามารถใช้เพื่อขยายรายการในการแทนที่โดยไม่ต้องกำหนดกฎแยกต่างหากสำหรับการขยาย

คำตอบของฉันนี้และคำตอบนี้โดย @ngenisisเป็นตัวอย่าง

การใช้

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

การแทนที่ข้างต้นก่อนใช้รูปแบบ{p___, a_, b_, q___}และค้นหาการจับคู่ที่bตรงกับเงื่อนไขที่แน่นอน

เมื่อไม่มีการแข่งขันดังกล่าวคือการหามันละเว้นและสำหรับแทนการค้นหาa_ ไม่รวมอยู่ในการค้นหาและจะถือว่ามีค่า{p___, b_, q___}a0

โปรดทราบว่าการค้นหารูปแบบที่สองจะใช้งานได้สำหรับbสิ่งที่เกิดขึ้นที่จุดเริ่มต้นของรายการเท่านั้น หากbค่าที่ตรงกับเงื่อนไขตรงกลางดังนั้น{p___, a_, b_, q___}(ซึ่งมีลำดับความสำคัญสูงกว่า) จะจับคู่กับเงื่อนไขแทน

การแทนที่นั้นเทียบเท่ากับการเตรียมการ0เมื่อbเงื่อนไขที่น่าพอใจเกิดขึ้นที่จุดเริ่มต้นของรายการ (เช่นไม่จำเป็นต้องกำหนดกฎแยกต่างหาก{b_, q___} /; cond[b] :> ...)


3

รู้ว่าเมื่อใด (และเมื่อไม่) ใช้ชื่ออาร์กิวเมนต์ของฟังก์ชันบริสุทธิ์

สำหรับ code golf การFunctionอ้างถึงแบบบริสุทธิ์นั้นมักจะอ้างถึงโดยใช้Slots; เช่น#สำหรับอาร์กิวเมนต์แรก#2สำหรับวินาทีและอื่น ๆ (ดูคำตอบนี้สำหรับรายละเอียดเพิ่มเติม)

ในหลายกรณีที่คุณต้องการจะทำรังFunctions ตัวอย่างเช่น1##&@@#&เป็นสิ่งFunctionที่รับรายการเป็นอาร์กิวเมนต์แรกและส่งออกผลิตภัณฑ์ขององค์ประกอบ นี่คือฟังก์ชันในTreeForm:

ป้อนคำอธิบายรูปภาพที่นี่

ข้อโต้แย้งที่ส่งผ่านไปยังระดับด้านบนFunctionเท่านั้นที่สามารถเติมSlots และSlotSequences ในปัจจุบันที่ระดับบนสุดซึ่งในกรณีนี้หมายถึงว่าSlotSequenceในชั้นจะไม่ได้มีวิธีการเข้าถึงข้อโต้แย้งระดับบนสุดใดFunctionFunction

ในบางกรณีคุณอาจต้องการให้ตัวFunctionซ้อนภายในอีกตัวหนึ่งFunctionสามารถอ้างถึงข้อโต้แย้งไปยังด้านนอกFunctionได้ ตัวอย่างเช่นคุณอาจต้องการสิ่งที่ต้องการArray[fun,...]&ที่ฟังก์ชั่นขึ้นอยู่กับข้อโต้แย้งที่ระดับบนสุดfun Functionสำหรับรูปธรรมขอบอกว่าควรจะให้ที่เหลือของตารางของการป้อนข้อมูลของแบบโมดูโลป้อนข้อมูลไปยังระดับด้านบนfun Functionวิธีหนึ่งในการทำสิ่งนี้ให้สำเร็จคือกำหนดอาร์กิวเมนต์ระดับสูงสุดให้กับตัวแปร:

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

เมื่อใดก็ตามที่xปรากฏในภายในFunction Mod[#^2,x]&ก็จะอ้างถึงอาร์กิวเมนต์แรกด้านนอกFunctionในขณะที่จะอ้างถึงอาร์กิวเมนต์แรกภายใน# Functionวิธีที่ดีกว่าคือการใช้ความจริงที่Functionมีสองรูปแบบการโต้แย้งที่อาร์กิวเมนต์แรกเป็นสัญลักษณ์หรือรายการของสัญลักษณ์ที่จะเป็นตัวแทนของข้อโต้แย้งที่มีชื่อเพื่อFunction(เมื่อเทียบกับชื่อที่ไม่มีชื่อSlot) สิ่งนี้จะช่วยเราสามไบต์ในกรณีนี้:

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

เป็นสามไบต์ใช้อักขระส่วนตัวที่เป็นตัวแทนของผู้ประกอบการมัดไบนารีU+F4A1 \[Function]คุณสามารถใช้รูปแบบไบนารีของFunctionภายในอื่นFunction:

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

นี่คือเทียบเท่ากับข้างต้น เหตุผลก็คือถ้าคุณใช้อาร์กิวเมนต์ที่มีชื่อดังนั้นSlots และSlotSequencesจะถือว่าเป็นของถัดไปFunctionข้างต้นซึ่งไม่ได้ใช้อาร์กิวเมนต์ที่มีชื่อ

ตอนนี้เพียงเพราะเราสามารถทำรังFunctionด้วยวิธีนี้ไม่ได้หมายความว่าเราควรทำเสมอ ตัวอย่างเช่นหากเราต้องการเลือกองค์ประกอบเหล่านั้นของรายการที่น้อยกว่าอินพุตเราอาจถูกล่อลวงให้ทำสิ่งต่อไปนี้:

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

จริง ๆ แล้วมันจะสั้นกว่าที่จะใช้Casesและหลีกเลี่ยงความต้องการซ้อนกันFunctionทั้งหมด:

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

2

คุณสามารถบันทึกไบต์โดยการทำงานรอบPrependหรือPrependTo:

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

หรือ

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

น่าเสียดายที่นี่ไม่ได้ช่วยอะไรที่เกิดขึ้นบ่อยAppendนักซึ่งดูเหมือนว่าจะเทียบเท่ากับArray.push()ภาษาอื่นที่สั้นที่สุด


2

Mathematica 10.2: BlockMapคือPartition+Map

เคล็ดลับนี้อาจมีชื่อว่า "อ่านบันทึกย่อประจำรุ่นทั้งหมด" (สำหรับการอ้างอิงนี่คือบันทึกย่อประจำรุ่นสำหรับ 10.2และนี่คือรุ่น 10.3 ของวันนี้ )

อย่างไรก็ตามแม้กระทั่งรุ่นย่อยที่มีคุณสมบัติใหม่มากมายและหนึ่งในคุณสมบัติที่มีประโยชน์มากขึ้น (สำหรับการเล่นกอล์ฟ) จาก 10.2 เป็นBlockMapฟังก์ชั่นใหม่ มันผสมผสานกันอย่างลงตัวPartitionและMapเป็นสิ่งที่ยอดเยี่ยมสำหรับนักกอล์ฟเนื่องจากPartitionมีการใช้งานบ่อยและเป็นชื่อฟังก์ชั่นที่ยาวมาก ๆ ฟังก์ชั่นใหม่จะไม่สั้นลงPartitionด้วยตัวเอง แต่เมื่อใดก็ตามที่คุณต้องการแมปฟังก์ชั่นเข้ากับพาร์ติชั่น (ซึ่งอาจเกิดขึ้นบ่อยกว่าไม่) คุณสามารถบันทึกไบต์หรือสอง:

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

การออมจะยิ่งใหญ่ขึ้นเมื่อตำแหน่งใหม่ของฟังก์ชันที่ไม่มีชื่อช่วยให้คุณประหยัดวงเล็บบางตัว:

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

น่าเสียดายที่ฉันไม่รู้ว่าทำไมไม่เพิ่มBlockApplyในขณะที่อยู่ในนั้น

นอกจากนี้โปรดทราบว่าBlockMapไม่สนับสนุนพารามิเตอร์ที่ 4 ที่คุณสามารถใช้Partitionเพื่อรับรายการวงจร:

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และคุณใช้nเวลามันปกติจะใช้ถึงl * nไบต์

อย่างไรก็ตามหากคุณเก็บไว้ในตัวแปรความยาว 1 มันจะใช้เวลาเพียง3 + l + nไบต์ (หรือ2 + l + nไบต์ถ้าคุณกำหนดตัวแปรที่คุณไม่ต้องการCompoundExpression (;)หรือวงเล็บ)


ตัวอย่างเช่นลองพิจารณาปัญหาง่าย ๆ การหาช่วงเวลาคู่ที่น้อยกว่า N

เราสามารถเขียน 54 byte solution ได้:

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

ในตัวอย่างนี้ใช้ฟังก์ชั่นPrimeQสามครั้ง

โดยการกำหนดPrimeQชื่อตัวแปรจำนวนไบต์สามารถลดลงได้ ทั้งสองอย่างต่อไปนี้คือ 48 ไบต์ (54 - 6 ไบต์):

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

2

เพื่อให้ได้รายการคีย์ - ค่าที่สูงขึ้นให้ใช้SortแทนSortBy

สำหรับรายการเช่นlist = {{1, "world"}, {0, "universe"}, {2, "country"}}คำสั่งสามข้อความต่อไปนี้เกือบจะเทียบเท่ากัน

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

รวมSelectและSortBy

บางครั้งเราจำเป็นต้องเลือกรายการจากชุดที่มีขนาดใหญ่กว่าและเรียงลำดับเพื่อค้นหาขั้นต่ำ / สูงสุด ภายใต้สถานการณ์บางอย่างการดำเนินการสองอย่างสามารถรวมกันเป็นหนึ่งเดียว

ยกตัวอย่างเช่นอย่างน้อยสองงบต่อไปนี้เกือบจะเทียบเท่ากัน

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/0คือComplexInfinityซึ่ง "ใหญ่" กว่าจำนวนจริงทั้งหมด

สำหรับรายการคีย์ - ค่าตัวอย่างเช่น:

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

1

ความแบนArrayด้วย##&

เมื่อใช้ Array หลายมิติเพื่อคำนวณรายการผลลัพธ์ที่ต้องทำให้แบนให้ใช้##&เป็นอาร์กิวเมนต์ที่สี่ นี้แทนที่หัวของอาร์เรย์ที่มี##&(เทียบเท่าSequence) แทนListเพื่อให้ผลสุดท้ายจะเป็น (แบน) Sequenceผล

เปรียบเทียบสองมิติ

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

แน่นอนว่า Join@@Array[f,dims] ยังคงเป็น 2 (หรือ 3 ถ้าโน้ตมัดสามารถนำมาใช้) {Array[f,dims,1,##&]}ไบต์สั้นกว่า

ในสามมิติขึ้นไป{Array[f,dims,origin,##&]}จะสั้นกว่าทางเลือกเสมอแม้ว่าแหล่งกำเนิดจะเป็น 1

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

1

ค่าเริ่มต้น

ค่าเริ่มต้นจัดการกับอาร์กิวเมนต์รูปแบบที่ขาดหายไปอย่างมีประสิทธิภาพ ตัวอย่างเช่นถ้าเราต้องการจับคู่รูปแบบExp[c_*x]ในกฎสำหรับค่าใด ๆ ของcnaïve

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

ใช้หลายไบต์มากกว่าถ้าเราใช้ค่าเริ่มต้นcเมื่อใดก็ตามที่มันหายไป:

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

c_.การใช้ค่าเริ่มต้นจะถูกระบุด้วยจุดหลังจากที่รูปแบบ:

ค่าเริ่มต้นมีความเกี่ยวข้องกับการดำเนินงาน: ในตัวอย่างข้างต้นการดำเนินการจะTimesในc_.*xและค่าที่ขาดหายไปc_จะนำมาจึงจากค่าเริ่มต้นที่เกี่ยวข้องกับการTimesซึ่งเป็น 1. Plusค่าเริ่มต้นเป็น 0:

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

สำหรับPowerเลขชี้กำลังค่าเริ่มต้นคือ 1:

x + x^2 /. x^n_. -> p[n]
(*    p[1] + p[2]    *)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.