คุณมีเคล็ดลับทั่วไปอะไรสำหรับการเล่นกอล์ฟในจูเลีย ฉันกำลังมองหาความคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะกับ Julia (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ)
คุณมีเคล็ดลับทั่วไปอะไรสำหรับการเล่นกอล์ฟในจูเลีย ฉันกำลังมองหาความคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะกับ Julia (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ)
คำตอบ:
หมายเหตุ: ด้านล่างอาจมีเคล็ดลับที่ล้าสมัยเนื่องจาก Julia ยังไม่เสถียรในแง่ของโครงสร้าง แต่อย่างใด
เทคนิคเล็กน้อยในการบันทึกอักขระบางตัว
\ =div
และคุณสามารถพิมพ์a\b
แทนdiv(a,b)
ได้ สังเกตพื้นที่ - นี่เป็นสิ่งจำเป็นเพื่อหลีกเลี่ยงการแยกวิเคราะห์เป็นตัวดำเนินการ "\ =" โปรดทราบด้วยว่าหากโอเวอร์โหลดที่ระดับพรอมต์ของ REPL ให้ใช้(\)=Base.(\)
หรือ\ =Base. \
เพื่อรีเซ็ต หมายเหตุ: บางฟังก์ชั่นมีตัวดำเนินการที่กำหนดไว้ล่วงหน้าของ UTF-8 เช่น÷
for div
ตามที่ Alex A.a>0?"Hi":""
ใช้"Hi"^(a>0)
เพื่อบันทึกหนึ่งไบต์หรือสำหรับบูลีน a ใช้"Hi"^a
เพื่อบันทึกสามไบต์a=split("Hi there"," ")
คุณอาจหลีกเลี่ยงa[1]
และa[2]
โดยการใช้a,b=split("Hi there"," ")
ซึ่งสามารถอ้างอิงเป็นa
และb
บันทึกสามไบต์สำหรับการใช้งานแต่ละครั้งในราคาเพียงอักขระพิเศษสองตัวที่ได้รับมอบหมาย เห็นได้ชัดว่าอย่าทำเช่นนี้หากคุณสามารถทำงานกับการดำเนินการเวกเตอร์ได้[]
- สำหรับอาร์เรย์แสดงออกเทียบเท่ากับA[]
A[1]
โปรดทราบว่าสิ่งนี้ใช้ไม่ได้กับ Strings หากคุณต้องการได้ตัวอักษรตัวแรกหรือ Tuples==[]
สำหรับอาร์เรย์และ==()
สำหรับ tuples; ในทำนองเดียวกันสำหรับการลบ, การใช้งานและ!=[]
!=()
สำหรับสตริงใช้==""
สำหรับที่ว่างเปล่า แต่ใช้>""
สำหรับที่ไม่ว่างเปล่าเนื่องจาก "" เป็นคำศัพท์ก่อนหน้าสตริงอื่น ๆx<=1&&"Hi"
สามารถเขียนเป็นx>1||"Hi"
บันทึกอักขระ (ตราบใดที่การส่งคืนบูลีนไม่สำคัญ)in('^',s)
contains(s,"^")
หากคุณสามารถใช้อักขระอื่นคุณสามารถบันทึกได้อีกเล็กน้อย'^'∈s
แต่โปรดทราบว่า∈
มีขนาด 3 ไบต์ใน UTF-8minimum(x)
หรือmaximum(x)
ใช้min(x...)
หรือmax(x...)
เพื่อโกนอักขระหนึ่งตัวออกจากรหัสของคุณหากคุณรู้ว่าx
จะมีองค์ประกอบอย่างน้อยสององค์ประกอบ หรือถ้าคุณรู้ว่าองค์ประกอบทั้งหมดx
จะไม่เป็นลบให้ใช้minabs(x)
หรือmaxabs(x)
r"(?m)match^ this"
พิมพ์r"match^ this"m
บันทึกตัวอักษรสามตัวreverse(x)
ยาวกว่าหนึ่งไบต์flipud(x)
และจะทำงานแบบเดียวกันดังนั้นหลังจึงดีกว่า{[1,2]}
ไม่ได้{1,2}
) - จูเลีย 0.4 Any[[1,2]]
คุณจะต้องend
ภายในการทำดัชนีอาเรย์มันจะถูกแปลงโดยอัตโนมัติตามความยาวของอาเรย์ / สตริง ดังนั้นแทนที่จะk=length(A)
ใช้A[k=end]
เพื่อบันทึก 3 ตัวอักษร โปรดทราบว่าสิ่งนี้อาจไม่เป็นประโยชน์หากคุณต้องการใช้ k ทันที วิธีนี้ยังใช้งานได้ในหลายมิติกรณี - A[k=end,l=end]
จะได้ขนาดของแต่ละมิติของA
- อย่างไรก็ตาม(k,l)=size(A)
จะสั้นกว่าหนึ่งไบต์ในกรณีนี้ดังนั้นให้ใช้เฉพาะเมื่อคุณต้องการเข้าถึงองค์ประกอบสุดท้ายในเวลาเดียวกันทันทีA[k=1:end]
ซึ่งในกรณีนี้จะถือการจับคู่k
iterator 1:length(A)
สิ่งนี้มีประโยชน์เมื่อคุณต้องการใช้อาร์เรย์A
ในเวลาเดียวกันcollect(A)
ใช้[A...]
ซึ่งจะทำสิ่งเดียวกันและบันทึก 4 ไบต์"$(s[i])"
หรือdec(s[i])
สำหรับนิพจน์หรือตัวแปรหลายตัวอักษรและ"$i"
สำหรับตัวแปรอักขระเดี่ยว?:
แทน&&
หรือ||
สำหรับการกำหนดเงื่อนไข - นั่นคือถ้าคุณต้องการที่จะดำเนินการได้รับมอบหมายเท่านั้นบนเงื่อนไขบางอย่างที่คุณสามารถบันทึกหนึ่งไบต์โดยการเขียนcond?A=B:1
มากกว่าcond&&(A=B)
หรือมากกว่าcond?1:A=B
cond||(A=B)
โปรดทราบว่าที่1
นี่เป็นค่าตัวอย่างunion
หรือ∪
แทนunique
- union(s)
จะทำเช่นเดียวกับunique(s)
และบันทึกไบต์ในกระบวนการ หากคุณสามารถใช้อักขระที่ไม่ใช่ ASCII แล้ว∪(s)
จะทำสิ่งเดียวกันและ∪
มีค่าใช้จ่ายเพียง 3 ไบต์แทน 5 union
ไบต์ในsplit("Hi there")
เพราะอาร์กิวเมนต์รูปแบบเริ่มต้นที่ช่องว่าง
การกำหนดตัวดำเนินการใหม่สามารถบันทึกไบต์จำนวนมากในวงเล็บและเครื่องหมายจุลภาค
สำหรับตัวอย่างที่ไม่แตกต่างกันให้เปรียบเทียบการประยุกต์ใช้แบบเรียกซ้ำต่อไปนี้ของลำดับ Fibonacci:
F(n)=n>1?F(n-1)+F(n-2):n # 24 bytes
!n=n>1?!~-n+!(n-2):n # 20 bytes
!n=n>1?!~-n+!~-~-n:n # 20 bytes
ตัวดำเนินการที่นิยามใหม่ยังคงมีความสำคัญเริ่มต้น
โปรดทราบว่าเราไม่สามารถเพียงแค่สลับออก!
ในความโปรดปรานของ~
ตั้งแต่~
ถูกกำหนดไว้แล้วสำหรับจำนวนเต็มในขณะที่!
ถูกกำหนดไว้เฉพาะสำหรับ Booleans
แม้ไม่มีการเรียกซ้ำการกำหนดตัวดำเนินการใหม่จะสั้นกว่าการกำหนดฟังก์ชันไบนารี เปรียบเทียบคำจำกัดความต่อไปนี้ของการทดสอบการหารอย่างง่าย
f(x,y)=x==0?y==0:y%x==0 # 23 bytes
(x,y)->x==0?y==0:y%x==0 # 23 bytes
x->y->x==0?y==0:y%x==0 # 22 bytes
x\y=x==0?y==0:y%x==0 # 20 bytes
ต่อไปนี้แสดงวิธีการกำหนดตัวดำเนินการไบนารีใหม่เพื่อคำนวณฟังก์ชัน Ackermann:
A(m,n)=m>0?A(m-1,n<1||A(m,n-1)):n+1 # 35 bytes
^ =(m,n)->m>0?(m-1)^(n<1||m^~-n):n+1 # 36 bytes
| =(m,n)->m>0?m-1|(n<1||m|~-n):n+1 # 34 bytes
m\n=m>0?~-m\(n<1||m\~-n):n+1 # 28 bytes
โปรดทราบว่า^
ยิ่งใช้เวลานานกว่าการใช้ตัวระบุทั่วไปเนื่องจากลำดับความสำคัญสูงเกินไป
ดังที่ได้กล่าวมาก่อน
m|n=m>0?m-1|(n<1||m|~-n):n+1 # 28 bytes
จะไม่ทำงานสำหรับอาร์กิวเมนต์จำนวนเต็มเนื่องจาก|
มีการกำหนดไว้แล้วในกรณีนี้ คำจำกัดความของจำนวนเต็มสามารถเปลี่ยนแปลงได้ด้วย
m::Int|n::Int=m>0?m-1|(n<1||m|~-n):n+1 # 38 bytes
แต่นั่นยาวยาว อย่างไรก็ตามมันใช้งานได้ถ้าเราผ่านการลอยตัวเป็นอาร์กิวเมนต์ซ้ายและจำนวนเต็มเป็นอาร์กิวเมนต์ที่ถูกต้อง
อย่าล่อลวงด้วยปัจจัย (n)ฟังก์ชั่นไลบรารี่พื้นฐานที่ล่อลวงfactor(n)
มีข้อบกพร่องร้ายแรง: มันจะคืนค่าการแยกตัวประกอบของจำนวนเต็มของคุณในรูปแบบที่ไม่เรียงลำดับ Dict
ดังนั้นจึงจำเป็นต้องมีค่าใช้จ่ายสูงcollect(keys())
และcollect(values())
อาจcat
เป็นsort
ไปได้ที่จะได้รับข้อมูลที่คุณต้องการ ในหลายกรณีอาจมีราคาถูกกว่าที่จะพิจารณาจากแผนกการทดลอง เศร้า แต่จริง
ใช้แผนที่ map
เป็นทางเลือกที่ดีในการวนซ้ำ ระวังความแตกต่างระหว่างmap
และmap!
และใช้ประโยชน์จากฟังก์ชั่นแบบแทนที่เมื่อคุณทำได้
ใช้ mapreduce ช่วย mapreduce
ขยายการทำงานของแผนที่ให้ดียิ่งขึ้นและสามารถเป็นตัวช่วยประหยัดไบต์ที่สำคัญได้
ฟังก์ชั่นนิรนามนั้นยอดเยี่ยมมาก! .. โดยเฉพาะเมื่อผ่านไปยังmap
ฟังก์ชั่นดังกล่าว
ฟังก์ชันอาเรย์สะสม cumprod
, ฟังก์ชันที่cumsum
มีรสชาติcummin
และชื่ออื่นที่คล้ายกันเปิดใช้งานการดำเนินการสะสมตามมิติที่ระบุของอาเรย์ n-Dim (หรือ * un * ถูกระบุหากอาร์เรย์เป็น 1-d)
สัญกรณ์สั้น ๆ สำหรับใด ๆเมื่อคุณต้องการเลือกทุกมิติของอาเรย์หลายมิติ (หรือ Dict) เช่นA[Any,2]
คุณสามารถบันทึกไบต์โดยใช้A[:,2]
ใช้สัญกรณ์บรรทัดเดียวสำหรับฟังก์ชั่นแทนคุณfunction f(x) begin ... end
มักจะทำให้ง่ายขึ้นf(x)=(...)
ใช้ผู้ประกอบการที่สามมันสามารถประหยัดพื้นที่สำหรับการแสดงออก If-Then-Else คำเตือน:ในขณะที่เป็นไปได้ในบางภาษาคุณไม่สามารถตัดส่วนหลังลำไส้ใหญ่ในจูเลียได้ นอกจากนี้ตัวดำเนินการเป็นระดับนิพจน์ใน Julia ดังนั้นคุณไม่สามารถใช้เพื่อดำเนินการตามเงื่อนไขของรหัสทั้งหมดได้
if x<10 then true else false end
VS
x<10?true:false
สิ่งนี้อาจเป็นไปได้ในภาษาอื่น ๆ แต่มักจะยาวกว่าวิธีที่ตรงไปตรงมา อย่างไรก็ตามความสามารถของจูเลียในการกำหนดผู้ประกอบการที่ไม่เป็นเอกภาพและไบนารีทำให้มันค่อนข้างกอล์ฟ
ตัวอย่างเช่นหากต้องการสร้างตารางการบวกการลบการคูณและการหารสำหรับตัวเลขธรรมชาติตั้งแต่ 1 ถึง 10 เราสามารถใช้
[x|y for x=1:10,y=1:10,| =(+,-,*,÷)]
ซึ่งนิยามใหม่ของไบนารีประกอบการ|
เป็น+
, -
, *
และ÷
จากนั้นคำนวณx|y
สำหรับการดำเนินงานแต่ละคนและx
และy
ในช่วงที่ต้องการ
มันใช้งานได้กับผู้ประกอบการเอก ตัวอย่างเช่นในการคำนวณจำนวนเชิงซ้อน1 + 2i , 3-4i , -5 + 6iและ-7-8i , ค่าลบ, ค่าคอนจูเกตคอมเพล็กซ์และค่าผกผันคูณ
[~x for~=(+,-,conj,inv),x=(1+2im,3-4im,-5+6im,-7-8im)]
ซึ่งนิยามใหม่ของเอกภาคผู้ประกอบการ~
เป็น+
, -
, conj
และinv
จากนั้นคำนวณ~x
ตัวเลขที่ซับซ้อนที่ต้องการทั้งหมด
ลำดับหญิงและชาย (ไบนารี)
การเปลี่ยน Case (unary)
บางครั้งคำหลักสามารถติดตามค่าคงที่ได้ทันทีโดยไม่จำเป็นต้องเว้นวรรคหรืออัฒภาค ตัวอย่างเช่น:
n->(for i=1:n n-=1end;n)
หมายเหตุการขาดพื้นที่ระหว่างที่และ1
end
นี้ยังเป็นจริงสำหรับที่เกิดขึ้นหลังจากที่มีการวงเล็บใกล้คือend
)end
ดำเนินการหารจำนวนเต็มโดยใช้÷
มากกว่าdiv()
หรือมากเกินไปตัวดำเนินการ โปรดทราบว่า÷
มีค่า 2 ไบต์ใน UTF-8
ใช้vec()
หรือA[:]
(สำหรับบางอาร์เรย์A
) แทนที่จะreshape()
เป็นไปได้
สร้างฟังก์ชั่นแทนโปรแกรมเต็มรูปแบบเมื่อได้รับอนุญาตในกฎการท้าทาย มันสั้นกว่าที่จะกำหนดฟังก์ชั่นที่รับอินพุตมากกว่าการกำหนดตัวแปรโดยการอ่านจาก stdin ตัวอย่างเช่น:
n->(n^2-1)
n=read(STDIN,Int);n^2-1
ตัวแปรสามารถเพิ่มขึ้นภายในอาร์กิวเมนต์ไปยังฟังก์ชัน ตัวอย่างเช่นต่อไปนี้คือคำตอบของฉันสำหรับการค้นหาเลขฐานสองแบบ 1 เบาบางถัดไป :
n->(while contains(bin(n+=1),"11")end;n)
ซึ่งสั้นกว่าการเพิ่มขึ้นn
ภายในวง
return
f(x)=x+4
เป็นเหมือน f(x)=return x+4
แต่สั้นกว่า Julia จะส่งคืนผลลัพธ์ของคำสั่งล่าสุดเสมอ[x for x in 1:4]
มีความยาวเกิน 3 อักขระ แต่เทียบเท่า[x for x=1:4]
เปิดตัวใน Julia 0.5 มันเป็นเหมือนแผนที่ แต่ใช้ตัวอักษรน้อยลงและออกอากาศพฤติกรรมเหนือสิ่งอื่น - ซึ่งหมายความว่าคุณสามารถเขียนแลมบ์ดาน้อยลงเพื่อจัดการกับสิ่งต่าง ๆ
ค่อนข้างมากกว่า:
map(f,x)
- 8 ตัวอักษรf.(x)
- 5 ตัวอักษรยังดีกว่า:
map(a->g(a,y),x)
- 16 ตัวอักษรg.(x,[y])
- 9 ตัวอักษร