คุณมีเคล็ดลับทั่วไปสำหรับการเล่นกอล์ฟใน Mathematica หรือไม่? ฉันกำลังมองหาแนวคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะกับ Mathematica (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ)
คุณมีเคล็ดลับทั่วไปสำหรับการเล่นกอล์ฟใน Mathematica หรือไม่? ฉันกำลังมองหาแนวคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะกับ Mathematica (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ)
คำตอบ:
เคล็ดลับด้านล่างแตกต่างกันไปจากที่ประหยัดที่สุดไปสู่การใช้บ่อยที่สุด:
ใช้คำสั่งระดับสูงของ Mathematica ถ้าเป็นไปได้แม้คำสั่งใหญ่ ๆ :
MorphologicalComponents: Code-Golf: Count Islands
ความสามารถในการจัดการภาพ: เช่นวันนี้ (24 กันยายน) เป็นวันเกิดของฮอนด้า
Subsets
IntegerPartitions
มาตรการระยะทางและความคล้ายคลึงกัน:เช่นEuclideanDistanceสามารถเป็นตัวช่วยไบต์ หมายเหตุ แต่ที่มันมักจะสั้นจะเขียนTotal@Abs[a-b]แทนa~ManhattanDistance~bและแทนMax@Abs[a-b]a~ChessboardDistance~b
ใช้Graphics and Textสำหรับ Ascii art: เช่นการเขียนโปรแกรม Star!
และสร้างนาฬิกาอะนาล็อก
สัญลักษณ์เฉพาะ:
สัญลักษณ์ลอจิกและตั้งค่าการดำเนินงานแทนชื่อแบบยาว: ⋂, ⋃, ∧, ∨
MapและApply: /@, //@. @@,@@@
สัญลักษณ์คำนำหน้าและมัด:
Print@"hello" แทน Print["hello"]
a~f~b แทน f[a,b]
เมื่อฟังก์ชั่นใช้เพียงครั้งเดียวฟังก์ชั่นแท้อาจประหยัดอักขระหรือสอง
การเข้าร่วมสตริงในรายการ ""<>{"a","b","c"}แทนStringJoin@{"a","b","c"}
ใช้ประโยชน์จากฟังก์ชั่นที่ฟังได้ รายการยิ่งยาวยิ่งดี
{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}}
ฟังก์ชันในตัวบางตัวที่มีชื่อยาวสามารถแทนที่ด้วยนิพจน์ที่สั้นลง
ตัวอย่างเช่น:
Total => TrTranspose=> Threadหรือ\[Transpose]True => 1<2False => 1>2Times => 1##&Alternatives => $|##&IntegerQ => ⌊#⌋==#&a[[1]] => #&@@aa[[All,1]] => #&@@@aConstantArray[a,n]=> Array[a&,n]หรือTable[a,{n}]Union@a=> {}⋃aหรือa⋃aToExpression@n=> FromDigits@nถ้าnเป็นตัวเลขDivisible[n,m] => m∣nFromDigits[n,2]=> Fold[#+##&,n]ถ้าnเป็นรายการของ0s และ1sComplex@z=> {1,I}.zซึ่งzเป็นรายการของแบบฟอร์ม{x,y}Thread[{{a,b},{c,d}}]== Thread[List[{a,b},{c,d}]]== {List[a,c],List[b,d]}== {{a,c},{b,d}}==Transpose[{{a,b},{c,d}}]
Foldเคล็ดลับสำหรับการFromDigitsทำงานกับฐานอื่น ๆ 10ยกเว้น เช่นFromDigits[n,5]-> Fold[4#+##&,n](พร้อมโบนัสการบันทึกไบต์พิเศษสำหรับฐาน100และ1000)
U+F3C7ในความเป็นจริงตัวละครตัวนี้คือ
Echoเป็นตัวเลือกเพราะจะพิมพ์>>(และที่ว่าง) ไปยัง STDOUT ก่อนที่จะพิมพ์สตริงจริง
Complex[x,y] => {1,I}.{x,y}ฉันคิดว่าx+y*Iสั้นกว่ามากที่มีผลเหมือนกันหรือไม่
นี่เป็นเวกเตอร์ทั่วไปที่ใช้งานได้:
{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
1^{,,,} 0{,,,}+1
{,,}^0ที่ทำให้มันสั้นที่สามค่าและคุณยังสามารถใช้ ฉันจะแก้ไขโพสต์
เมื่อตีกอล์ฟรหัสคุณมักจะใช้วิธีการทำงานที่คุณใช้ฟังก์ชั่นที่ไม่ระบุชื่อ (บริสุทธิ์) กับ&ไวยากรณ์ชวเลข มีหลายวิธีในการเข้าถึงอาร์กิวเมนต์ของฟังก์ชั่นดังกล่าวและคุณมักจะสามารถปัดทิ้งสองไบต์ด้วยการเข้าใจถึงความเป็นไปได้
คุณอาจจะรู้สิ่งนี้ถ้าคุณเคยใช้ฟังก์ชั่นบริสุทธิ์มาก่อน nอาร์กิวเมนต์ TH จะเรียกว่าเป็น#nและทำหน้าที่เป็นนามแฝงสำหรับ# #1ดังนั้นถ้าพูดว่าคุณต้องการที่จะเขียนฟังก์ชั่นที่ใช้เป็นพารามิเตอร์ฟังก์ชั่นอื่นและการโต้แย้ง (เพื่อส่งผ่านอาร์กิวเมนต์ไปยังฟังก์ชั่นนั้น) ให้ใช้
#@#2&
สิ่งนี้ใช้ไม่ได้กับจำนวนลบ (เช่นคุณอาจใช้เมื่อเข้าถึงรายการ)
หนึ่งในฟีเจอร์ภาษาใหม่ที่สำคัญใน 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
ทดลองต่อไปกับสิ่งเหล่านี้และแจ้งให้เราทราบหากคุณพบแอปพลิเคชั่นที่มีประโยชน์หรือน่าสนใจอื่น ๆ !
Sqrt@2หรือ2^.5=>√2
a[[1]]=>a〚1〛
#+#2&=>+##&
Flatten@a=> Join@@a(บางครั้ง)
Function[x,x^2]=> xx^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
〚และ〛ใช้แต่ละ 3 ไบต์ (สมมติว่าเป็น UTF8)
แรงบันดาลใจจากการค้นพบล่าสุดของ 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จะไม่สามารถอ่านจุดรหัสเหล่านี้ได้จากไบต์เดียว
วิธีการไร้เดียงสาที่จะเลือกระหว่าง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]]
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ยังคงเทียบเท่ากับ
Length@x == Tr[1^x]. ควรทำงานกับรายการส่วนใหญ่
Tr[x!]แทนTr[1^x]การบันทึกหนึ่งไบต์ในกรณีพิเศษที่xประกอบด้วยศูนย์และคน
สำรวจโซลูชันแบบเรียกซ้ำ - Mathematica เป็นกระบวนทัศน์แบบหลากหลาย แต่วิธีการทำงานมักจะประหยัดที่สุด NestWhileอาจเป็นวิธีแก้ปัญหาที่กะทัดรัดมากในการค้นหาปัญหาNestWhileListและFoldListมีประสิทธิภาพเมื่อคุณต้องการส่งคืนหรือประมวลผลผลลัพธ์ของการทำซ้ำขั้นกลาง Map (/@), Apply (@@, @@@), MapThreadและจริงๆทุกอย่างบนวุลแฟรมของหน้าที่ Programmingหน้าเอกสารเป็นสิ่งที่มีศักยภาพ
รูปแบบย่อสำหรับการเพิ่ม / ลด - ตัวอย่างเช่นแทนที่จะWhile[i<1,*code*;i++]ทำWhile[i++<1,*code*]
อย่าลืมคุณสามารถ pre-เพิ่มขึ้น / ลดลง - ยกตัวอย่างเช่นแทน--i i--บางครั้งวิธีนี้จะช่วยให้คุณประหยัดเวลาได้ไม่กี่ไบต์ในโค้ดที่ล้อมรอบโดยกำจัดการดำเนินการเตรียมการ
ข้อสรุปของ David Carraher # 5: เมื่อใช้ฟังก์ชันเดียวกันหลายครั้งการกำหนดสัญลักษณ์ให้สามารถบันทึกเป็นไบต์ได้ ตัวอย่างเช่นหากคุณใช้ToExpressionโซลูชั่น 4 ครั้งt=ToExpressionคุณจะสามารถใช้งานได้ในt@*expression*ภายหลัง อย่างไรก็ตามก่อนที่คุณจะทำสิ่งนี้ให้พิจารณาว่าแอปพลิเคชันซ้ำของฟังก์ชั่นเดียวกันบ่งชี้โอกาสสำหรับวิธีเรียกซ้ำที่ประหยัดกว่าหรือไม่
{}@@@ในบางกรณีคุณอาจพบนิพจน์เช่น:
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}ในกรณีนี้คุณก็ควรใช้
แบบฟอร์มผู้ประกอบการ
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]
ไม่จำเป็นต้องใช้รหัสเช่นนี้:
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
%เพื่อรับตัวแปรฟรีเคล็ดลับนี้ใช้ได้เฉพาะเมื่อสภาพแวดล้อม 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=และถ้าคุณใช้มันสองครั้งตัวละครเพิ่มเติมในชื่อตัวแปรยกเลิกออกเงินฝากออมทรัพย์จากถนัดบาง
นี่เป็นข้อสรุปที่สำคัญของเคล็ดลับนี้แต่นี่เป็นงานทั่วไปที่เพียงพอที่ฉันคิดว่ามันรับประกันคำตอบของตัวเอง
วิธีการที่ไร้เดียงสาเพื่อตรวจสอบว่ารายการนั้นมีการใช้งานหรือไม่
OrderedQ@a
เราสามารถทำได้ดีกว่าหนึ่งไบต์
Sort@a==a
อย่างไรก็ตามสิ่งนี้ใช้ไม่ได้หากเราไม่มีสิ่งที่เราต้องการตรวจสอบในตัวแปรแล้ว (เราต้องการบางสิ่งSort[a=...]==aที่มีความยาวเกินความจำเป็น) อย่างไรก็ตามมีตัวเลือกอื่น:
#<=##&@@a
สิ่งที่ดีที่สุดคือสามารถใช้เพื่อตรวจสอบว่าอินพุตถูกเรียงกลับกันสำหรับจำนวนไบต์เดียวกันหรือไม่:
#>=##&@@a
สามารถบันทึกได้อีกหนึ่งไบต์ถ้าก) เรารู้ว่าองค์ประกอบของรายการนั้นแตกต่างกันและข) เรารู้ขอบเขตที่ต่ำกว่าระหว่าง 0 และ 9 (รวม; หรือขอบบนสำหรับลำดับที่เรียงกลับกัน):
0<##&@@a
5>##&@@a
หากต้องการดูว่าเหตุใดจึงใช้งานได้ตรวจสอบ "ลำดับของอาร์กิวเมนต์" ในเคล็ดลับลิงก์ที่ด้านบน
##>0&@@aลดที่ถูกผูกไว้สำหรับย้อนกลับเรียงยังทำงาน: คล้ายกับขอบบนสำหรับการเรียงลำดับ
แทนการใช้งานStringRepeat[str,n] (0Range[n]+str)<>""หรือถ้าstrไม่ได้ขึ้นอยู่กับข้อโต้แย้งสล็อตใด ๆ ได้ดียิ่งขึ้นเป็นArray[str&,n]<>""ตามนี้เคล็ดลับ
StringRepeat[s,n+1]ใช้Array[s&,n]<>s(แม้ว่าคุณจะn+1มีตัวแปรอยู่แล้วก็ตาม)
Table[str,n]<>""
หากคุณต้องการรายการตัวเลขเรียงกลับกันอย่าใช้
Reverse@Sort@x
แต่
-Sort@-x
เพื่อบันทึกหกไบต์ การเรียงลำดับตามค่าลบยังมีประโยชน์สำหรับSortByสถานการณ์:
Reverse@SortBy[x,Last]
SortBy[x,-Last@#&]
-Sort@-xอะไร
คุณสามารถใช้นิพจน์Breakที่สามารถบันทึกอักขระหนึ่งหรือสองตัว ตัวอย่าง ( รายละเอียดอื่น ๆ ที่ไม่ได้ตีกอล์ฟเพื่อความชัดเจน ):
result = False;
Break[]
สามารถเปลี่ยนเป็น
Break[result = False]
เพื่อบันทึกอักขระหนึ่งตัว หากการแสดงออกในคำถามไม่ได้มีความสำคัญต่ำกว่าฟังก์ชั่นการใช้งานคุณสามารถบันทึกตัวละครอื่น:
Print@x;
Break[]
สามารถเปลี่ยนเป็น
Break@Print@x
แม้ว่าจะไม่มีเอกสารก็ตาม แต่ข้อโต้แย้งที่Breakดูเหมือนว่าจะถูกส่งกลับโดยวนรอบซึ่งอาจนำไปสู่การออมที่มากขึ้น
ในการลบช่องว่างทั้งหมดออกจากสตริงsให้ใช้
StringSplit@s<>""
นั่นคือใช้StringSplitค่าเริ่มต้นของ (แยกเป็นองค์ประกอบที่ไม่ใช่ช่องว่าง) และเพียงแค่รวมพวกเขากลับมารวมกัน เช่นเดียวกันอาจยังสั้นที่สุดหากคุณต้องการกำจัดอักขระหรือสตริงย่อยอื่น ๆ :
s~StringSplit~"x"<>""
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]เป็นประจำ ...
บางสิ่งที่สร้างเช่นi=1;While[cond[i],i++]นี้เป็นเรื่องปกติ แต่มีทางเลือกที่สั้นกว่าสองไบต์:
1//.i_/;cond[i]:>i+1
รหัสข้างต้นซ้ำ ๆ แทนตัวเลขiด้วยในขณะที่มันเป็นไปตามเงื่อนไขi+1 cond[i]ในกรณีนี้จะเริ่มต้นที่i1
โปรดทราบว่าจำนวนการทำซ้ำสูงสุดเริ่มต้นคือ 2 ^ 16 (= 65536) หากคุณต้องการการวนซ้ำมากกว่านั้นWhileจะดีกว่า ( MaxIterations->∞ยาวเกินไป)
บางครั้งคุณสามารถแทนที่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และข้อโต้แย้งของ
นี่คือรายการที่มีรูปแบบการป้อนข้อมูลของตัวดำเนินการที่สามารถย่อจำนวนมากได้ บางส่วนได้รับการกล่าวถึงในโพสต์อื่น ๆ แต่รายการมีความยาวและฉันมักจะประหลาดใจที่พบสิ่งใหม่ไม่กี่:
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] :> ...)
สำหรับ code golf การFunctionอ้างถึงแบบบริสุทธิ์นั้นมักจะอ้างถึงโดยใช้Slots; เช่น#สำหรับอาร์กิวเมนต์แรก#2สำหรับวินาทีและอื่น ๆ (ดูคำตอบนี้สำหรับรายละเอียดเพิ่มเติม)
ในหลายกรณีที่คุณต้องการจะทำรังFunctions ตัวอย่างเช่น1##&@@#&เป็นสิ่งFunctionที่รับรายการเป็นอาร์กิวเมนต์แรกและส่งออกผลิตภัณฑ์ขององค์ประกอบ นี่คือฟังก์ชันในTreeForm:
ข้อโต้แย้งที่ส่งผ่านไปยังระดับด้านบนFunctionเท่านั้นที่สามารถเติมSlots และSlotSequences ในปัจจุบันที่ระดับบนสุดซึ่งในกรณีนี้หมายถึงว่าSlotSequenceในชั้นจะไม่ได้มีวิธีการเข้าถึงข้อโต้แย้งระดับบนสุดใดFunction ๆFunction
ในบางกรณีคุณอาจต้องการให้ตัวFunctionซ้อนภายในอีกตัวหนึ่งFunctionสามารถอ้างถึงข้อโต้แย้งไปยังด้านนอกFunctionได้ ตัวอย่างเช่นคุณอาจต้องการสิ่งที่ต้องการArray[fun,...]&ที่ฟังก์ชั่นขึ้นอยู่กับข้อโต้แย้งที่ระดับบนสุดfun Functionสำหรับรูปธรรมขอบอกว่าควรจะให้ที่เหลือของตารางของการป้อนข้อมูลของแบบโมดูโลป้อนข้อมูลไปยังระดับด้านบนfun Functionวิธีหนึ่งในการทำสิ่งนี้ให้สำเร็จคือกำหนดอาร์กิวเมนต์ระดับสูงสุดให้กับตัวแปร:
(x=#;Array[Mod[#^2,x]&,...])&
เมื่อใดก็ตามที่xปรากฏในภายในFunction Mod[#^2,x]&ก็จะอ้างถึงอาร์กิวเมนต์แรกด้านนอกFunctionในขณะที่จะอ้างถึงอาร์กิวเมนต์แรกภายใน# Functionวิธีที่ดีกว่าคือการใช้ความจริงที่Functionมีสองรูปแบบการโต้แย้งที่อาร์กิวเมนต์แรกเป็นสัญลักษณ์หรือรายการของสัญลักษณ์ที่จะเป็นตัวแทนของข้อโต้แย้งที่มีชื่อเพื่อFunction(เมื่อเทียบกับชื่อที่ไม่มีชื่อSlot) สิ่งนี้จะช่วยเราสามไบต์ในกรณีนี้:
xArray[Mod[#^2,x]&,...]
เป็นสามไบต์ใช้อักขระส่วนตัวที่เป็นตัวแทนของผู้ประกอบการมัดไบนารีU+F4A1 \[Function]คุณสามารถใช้รูปแบบไบนารีของFunctionภายในอื่นFunction:
Array[xMod[x^2,#],...]&
นี่คือเทียบเท่ากับข้างต้น เหตุผลก็คือถ้าคุณใช้อาร์กิวเมนต์ที่มีชื่อดังนั้นSlots และSlotSequencesจะถือว่าเป็นของถัดไปFunctionข้างต้นซึ่งไม่ได้ใช้อาร์กิวเมนต์ที่มีชื่อ
ตอนนี้เพียงเพราะเราสามารถทำรังFunctionด้วยวิธีนี้ไม่ได้หมายความว่าเราควรทำเสมอ ตัวอย่างเช่นหากเราต้องการเลือกองค์ประกอบเหล่านั้นของรายการที่น้อยกว่าอินพุตเราอาจถูกล่อลวงให้ทำสิ่งต่อไปนี้:
Select[...,xx<#]&
จริง ๆ แล้วมันจะสั้นกว่าที่จะใช้Casesและหลีกเลี่ยงความต้องการซ้อนกันFunctionทั้งหมด:
Cases[...,x_/;x<#]&
คุณสามารถบันทึกไบต์โดยการทำงานรอบPrependหรือPrependTo:
l~Prepend~x
{x}~Join~l
{x,##}&@@l
หรือ
l~PrependTo~x
l={x}~Join~l
l={x,##}&@@l
น่าเสียดายที่นี่ไม่ได้ช่วยอะไรที่เกิดขึ้นบ่อยAppendนักซึ่งดูเหมือนว่าจะเทียบเท่ากับArray.push()ภาษาอื่นที่สั้นที่สุด
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... *)
หากคำตอบของคุณสิ้นสุดลงโดยใช้ฟังก์ชั่นหรือการแสดงออกเดียวกันหลายครั้งคุณอาจต้องการพิจารณาจัดเก็บไว้ในตัวแปร
หากการแสดงออกของคุณมีความยาว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])&]&
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]
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
ค่าเริ่มต้นจัดการกับอาร์กิวเมนต์รูปแบบที่ขาดหายไปอย่างมีประสิทธิภาพ ตัวอย่างเช่นถ้าเราต้องการจับคู่รูปแบบ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] *)
(Norm[#-#2]&)EuclideanDistance