คุณมีเคล็ดลับทั่วไปสำหรับการเล่นกอล์ฟใน 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
=> 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
เป็นรายการของ0
s และ1
sComplex@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
ในกรณีนี้ (อาจเร็วกว่านี้ขึ้นอยู่กับข้อกำหนดก่อนหน้า)
เหตุผลที่งานนี้คือการที่,
แนะนำสองข้อโต้แย้งในรายการ แต่ข้อโต้แย้งละเว้น (ที่ใดก็ได้ในมาติกา) เป็นนัยNull
s นอกจากนี้การคูณ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 คือAssociation
s ซึ่งโดยทั่วไปแล้วเป็นแผนที่ค่าคีย์ที่มีประเภทของคีย์โดยพลการเขียนเช่น
<| 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 - ฉันค้นพบสิ่งนี้ในหนึ่งในคำตอบของเขา
หากใช้แบบx
1 แทนเป็นศูนย์ให้ใช้
{y,z}[[x]]
หรือ
{u,v,w}[[x]]
ในบางกรณีที่หายากคุณสามารถใช้ประโยชน์จากความจริงที่ว่าการคูณจะไม่ถูกประเมินสำหรับค่าบางอย่าง:
{"abc","def"}[[x]]
("abc""def")[[x]]
หมายเหตุว่าที่ Mathematica จริงจะสั่งซื้อข้อโต้แย้งของการคูณถ้ามันยังคง unevaluated ดังนั้นที่กล่าวมาเป็นเหมือนการ
("def""abc")[[x]]
Length
สิ่งนี้ถูกเขียนใหม่ทั้งหมดพร้อมคำแนะนำจาก LegionMammal978 และ Misha Lavrov ขอบคุณมากสำหรับพวกเขาทั้งคู่
ในหลายกรณีจะสั้นลงเล็กน้อยโดยการใช้Length
Tr
แนวคิดพื้นฐานคือการเปลี่ยนอินพุตให้เป็นรายการของ1
s เพื่อหาTr
ผลรวมเหล่านั้นซึ่งจะเท่ากับความยาวของรายการ
วิธีที่พบได้บ่อยที่สุดคือการใช้1^x
(สำหรับรายการx
) งานนี้Power
เป็นเพราะListable
และ1^n
สำหรับค่าอะตอมส่วนใหญ่n
เป็นเพียง1
(รวมถึงตัวเลขสตริงและสัญลักษณ์ทั้งหมด) ดังนั้นเราจึงสามารถบันทึกหนึ่งไบต์ด้วย:
Length@x
Tr[1^x]
ของหลักสูตรนี้อนุมานว่าคือการแสดงออกที่มีลำดับความสำคัญสูงกว่าx
^
หากx
มีเพียง0
s และ1
s เราสามารถบันทึก 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}
) ไม่ทำงานเพราะมีความสำคัญสูงกว่าApply
Alternative
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
ดังนั้นเป็นเกือบแน่นอนดีกว่าArray
Range
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]
ในกรณีนี้จะเริ่มต้นที่i
1
โปรดทราบว่าจำนวนการทำซ้ำสูงสุดเริ่มต้นคือ 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___}
a
0
โปรดทราบว่าการค้นหารูปแบบที่สองจะใช้งานได้สำหรับb
สิ่งที่เกิดขึ้นที่จุดเริ่มต้นของรายการเท่านั้น หากb
ค่าที่ตรงกับเงื่อนไขตรงกลางดังนั้น{p___, a_, b_, q___}
(ซึ่งมีลำดับความสำคัญสูงกว่า) จะจับคู่กับเงื่อนไขแทน
การแทนที่นั้นเทียบเท่ากับการเตรียมการ0
เมื่อb
เงื่อนไขที่น่าพอใจเกิดขึ้นที่จุดเริ่มต้นของรายการ (เช่นไม่จำเป็นต้องกำหนดกฎแยกต่างหาก{b_, q___} /; cond[b] :> ...
)
สำหรับ code golf การFunction
อ้างถึงแบบบริสุทธิ์นั้นมักจะอ้างถึงโดยใช้Slot
s; เช่น#
สำหรับอาร์กิวเมนต์แรก#2
สำหรับวินาทีและอื่น ๆ (ดูคำตอบนี้สำหรับรายละเอียดเพิ่มเติม)
ในหลายกรณีที่คุณต้องการจะทำรังFunction
s ตัวอย่างเช่น1##&@@#&
เป็นสิ่งFunction
ที่รับรายการเป็นอาร์กิวเมนต์แรกและส่งออกผลิตภัณฑ์ขององค์ประกอบ นี่คือฟังก์ชันในTreeForm
:
ข้อโต้แย้งที่ส่งผ่านไปยังระดับด้านบนFunction
เท่านั้นที่สามารถเติมSlot
s และSlotSequence
s ในปัจจุบันที่ระดับบนสุดซึ่งในกรณีนี้หมายถึงว่า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,#],...]&
นี่คือเทียบเท่ากับข้างต้น เหตุผลก็คือถ้าคุณใช้อาร์กิวเมนต์ที่มีชื่อดังนั้นSlot
s และ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]
ในกฎสำหรับค่าใด ๆ ของc
naï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