เคล็ดลับการเล่นกอล์ฟในจูเลีย


20

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

คำตอบ:


19

หมายเหตุ: ด้านล่างอาจมีเคล็ดลับที่ล้าสมัยเนื่องจาก Julia ยังไม่เสถียรในแง่ของโครงสร้าง แต่อย่างใด

เทคนิคเล็กน้อยในการบันทึกอักขระบางตัว

  1. ผู้ประกอบการเกินพิกัดด้วยฟังก์ชั่ไบนารีที่ใช้บ่อย ตัวอย่างเช่นหากคุณต้องการแบ่งจำนวนเต็มจำนวนมากและไม่จำเป็นต้องใช้การหารผกผันให้ใช้\ =divและคุณสามารถพิมพ์a\bแทนdiv(a,b)ได้ สังเกตพื้นที่ - นี่เป็นสิ่งจำเป็นเพื่อหลีกเลี่ยงการแยกวิเคราะห์เป็นตัวดำเนินการ "\ =" โปรดทราบด้วยว่าหากโอเวอร์โหลดที่ระดับพรอมต์ของ REPL ให้ใช้(\)=Base.(\)หรือ\ =Base. \เพื่อรีเซ็ต หมายเหตุ: บางฟังก์ชั่นมีตัวดำเนินการที่กำหนดไว้ล่วงหน้าของ UTF-8 เช่น÷for divตามที่ Alex A.
  2. ใช้ ^ กับสตริงเงื่อนไขสำหรับการส่งออก นั่นคือแทนที่จะa>0?"Hi":""ใช้"Hi"^(a>0)เพื่อบันทึกหนึ่งไบต์หรือสำหรับบูลีน a ใช้"Hi"^aเพื่อบันทึกสามไบต์
  3. (บาง) ร้านค้าขนาดเล็กเวกเตอร์ขนาดคงเป็นตัวแปรที่แยกต่างหาก ตัวอย่างเช่นa=split("Hi there"," ")คุณอาจหลีกเลี่ยงa[1]และa[2]โดยการใช้a,b=split("Hi there"," ")ซึ่งสามารถอ้างอิงเป็นaและbบันทึกสามไบต์สำหรับการใช้งานแต่ละครั้งในราคาเพียงอักขระพิเศษสองตัวที่ได้รับมอบหมาย เห็นได้ชัดว่าอย่าทำเช่นนี้หากคุณสามารถทำงานกับการดำเนินการเวกเตอร์ได้
  4. องค์ประกอบแรกของการเข้าถึงอาร์เรย์ด้วย[] - สำหรับอาร์เรย์แสดงออกเทียบเท่ากับA[] A[1]โปรดทราบว่าสิ่งนี้ใช้ไม่ได้กับ Strings หากคุณต้องการได้ตัวอักษรตัวแรกหรือ Tuples
  5. อย่าใช้ isEmpty สำหรับอาร์เรย์ Tuples หรือ Strings - แทนการใช้==[]สำหรับอาร์เรย์และ==()สำหรับ tuples; ในทำนองเดียวกันสำหรับการลบ, การใช้งานและ!=[] !=()สำหรับสตริงใช้==""สำหรับที่ว่างเปล่า แต่ใช้>""สำหรับที่ไม่ว่างเปล่าเนื่องจาก "" เป็นคำศัพท์ก่อนหน้าสตริงอื่น ๆ
  6. ใช้ลัดวงจรประกอบการบูลีนที่เหมาะสมในสถานที่ของ "ถ้า" มันอาจจะน้อยกว่า Julia ที่เฉพาะเจาะจงเล็กน้อย แต่ควรคำนึงถึงเรื่องนี้ด้วย x<=1&&"Hi"สามารถเขียนเป็นx>1||"Hi"บันทึกอักขระ (ตราบใดที่การส่งคืนบูลีนไม่สำคัญ)
  7. ไม่ได้ใช้ในการตรวจสอบมีการปรากฏตัวของตัวละครในสตริง - ถ้าคุณกำลังถูก จำกัด ไปยัง ASCII พื้นฐานให้ใช้มากกว่าin('^',s) contains(s,"^")หากคุณสามารถใช้อักขระอื่นคุณสามารถบันทึกได้อีกเล็กน้อย'^'∈sแต่โปรดทราบว่ามีขนาด 3 ไบต์ใน UTF-8
  8. กำลังมองหาค่าต่ำสุด / สูงสุดในอาร์เรย์หรือไม่ อย่าใช้ขั้นต่ำหรือสูงสุด - แทนที่จะใช้minimum(x)หรือmaximum(x)ใช้min(x...)หรือmax(x...)เพื่อโกนอักขระหนึ่งตัวออกจากรหัสของคุณหากคุณรู้ว่าxจะมีองค์ประกอบอย่างน้อยสององค์ประกอบ หรือถ้าคุณรู้ว่าองค์ประกอบทั้งหมดxจะไม่เป็นลบให้ใช้minabs(x)หรือmaxabs(x)
  9. หากเป็นไปได้และได้รับอนุญาตจากความท้าทายให้ใช้ newline จริงแทน \ n - โปรดทราบว่าสิ่งนี้จะทำให้โค้ดของคุณอ่านยากขึ้นและอาจหมายความว่าคุณต้องจัดเตรียมเวอร์ชัน "ungolfed" เพื่อให้ผู้คนเข้าใจได้จริง มัน.
  10. วางตัวเลือกหลังสตริง regex - หากคุณต้องการมีสตริง regex ในโหมดหลายบรรทัดเช่นห้ามพิมพ์r"(?m)match^ this"พิมพ์r"match^ this"mบันทึกตัวอักษรสามตัว
  11. ย้อนกลับอาร์เรย์ 1-D โดยใช้ flipud - reverse(x)ยาวกว่าหนึ่งไบต์flipud(x)และจะทำงานแบบเดียวกันดังนั้นหลังจึงดีกว่า
  12. หากเป็นไปได้ให้ใช้การต่อเรียงอาร์เรย์แทนการกด!, unshift !, ผนวก!, หรือเติม! - สำหรับอาร์เรย์ปกติสามารถทำได้อย่างง่ายดาย สำหรับอาร์เรย์ของชนิดใด ๆ ที่มีองค์ประกอบมากมายที่คุณจะต้องวงเล็บปีกการอบอาร์เรย์เพิ่ม (นั่นคือ{[1,2]}ไม่ได้{1,2}) - จูเลีย 0.4 Any[[1,2]]คุณจะต้อง
  13. ใช้การทำดัชนีอาเรย์เพื่อรับขนาดของอาเรย์หรือสตริง - เมื่อคุณใช้endภายในการทำดัชนีอาเรย์มันจะถูกแปลงโดยอัตโนมัติตามความยาวของอาเรย์ / สตริง ดังนั้นแทนที่จะk=length(A)ใช้A[k=end]เพื่อบันทึก 3 ตัวอักษร โปรดทราบว่าสิ่งนี้อาจไม่เป็นประโยชน์หากคุณต้องการใช้ k ทันที วิธีนี้ยังใช้งานได้ในหลายมิติกรณี - A[k=end,l=end]จะได้ขนาดของแต่ละมิติของA- อย่างไรก็ตาม(k,l)=size(A)จะสั้นกว่าหนึ่งไบต์ในกรณีนี้ดังนั้นให้ใช้เฉพาะเมื่อคุณต้องการเข้าถึงองค์ประกอบสุดท้ายในเวลาเดียวกันทันที
  14. รับดัชนี iterator ใช้อาร์เรย์จัดทำดัชนี - คล้ายกับ 13 คุณยังสามารถได้รับการ iterator ที่ตรงกับความยาวของอาร์เรย์โดยใช้A[k=1:end]ซึ่งในกรณีนี้จะถือการจับคู่k iterator 1:length(A)สิ่งนี้มีประโยชน์เมื่อคุณต้องการใช้อาร์เรย์Aในเวลาเดียวกัน
  15. อย่าใช้การรวบรวมเพื่อแปลงสตริงเป็นอาร์เรย์อาร์คแทนที่จะcollect(A)ใช้[A...]ซึ่งจะทำสิ่งเดียวกันและบันทึก 4 ไบต์
  16. ต้องการตัวเลขที่แปลงเป็นสตริงหรือไม่? ใช้"$(s[i])"หรือdec(s[i])สำหรับนิพจน์หรือตัวแปรหลายตัวอักษรและ"$i"สำหรับตัวแปรอักขระเดี่ยว
  17. ใช้?:แทน&&หรือ||สำหรับการกำหนดเงื่อนไข - นั่นคือถ้าคุณต้องการที่จะดำเนินการได้รับมอบหมายเท่านั้นบนเงื่อนไขบางอย่างที่คุณสามารถบันทึกหนึ่งไบต์โดยการเขียนcond?A=B:1มากกว่าcond&&(A=B)หรือมากกว่าcond?1:A=B cond||(A=B)โปรดทราบว่าที่1นี่เป็นค่าตัวอย่าง
  18. ใช้unionหรือแทนunique - union(s)จะทำเช่นเดียวกับunique(s)และบันทึกไบต์ในกระบวนการ หากคุณสามารถใช้อักขระที่ไม่ใช่ ASCII แล้ว∪(s)จะทำสิ่งเดียวกันและมีค่าใช้จ่ายเพียง 3 ไบต์แทน 5 unionไบต์ใน

2
โอ้ฉันจะรักเคล็ดลับแรกนั้นใน Python ได้อย่างไร
Seequ

คุณสามารถแบ่งช่องว่างโดยใช้เพียงsplit("Hi there")เพราะอาร์กิวเมนต์รูปแบบเริ่มต้นที่ช่องว่าง
Alex A.

@AlexA - ฉันรู้ แต่มันไม่ได้เป็นจุดสิ้นสุดของปลายและเคล็ดลับที่ใช้อย่างเท่าเทียมกันทั้งสองวิธี
เกลน O

จุดที่ 12 เปลี่ยนไปใน 0.5
Lyndon White

@Oinabox - ฉันไม่แปลกใจฉันค่อนข้างแน่ใจว่าบางส่วนของพวกเขาจะล้าสมัยในขณะนี้ ตอนแรกฉันเขียนคำแนะนำส่วนใหญ่สำหรับ 0.3 ฉันคิดว่า
เกลน O

15

กำหนดผู้ประกอบการใหม่เพื่อกำหนดฟังก์ชั่น

การกำหนดตัวดำเนินการใหม่สามารถบันทึกไบต์จำนวนมากในวงเล็บและเครื่องหมายจุลภาค

ตัวดำเนินการ unary แบบเรียกซ้ำ

สำหรับตัวอย่างที่ไม่แตกต่างกันให้เปรียบเทียบการประยุกต์ใช้แบบเรียกซ้ำต่อไปนี้ของลำดับ 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

แต่นั่นยาวยาว อย่างไรก็ตามมันใช้งานได้ถ้าเราผ่านการลอยตัวเป็นอาร์กิวเมนต์ซ้ายและจำนวนเต็มเป็นอาร์กิวเมนต์ที่ถูกต้อง


11
  1. อย่าล่อลวงด้วยปัจจัย (n)ฟังก์ชั่นไลบรารี่พื้นฐานที่ล่อลวงfactor(n)มีข้อบกพร่องร้ายแรง: มันจะคืนค่าการแยกตัวประกอบของจำนวนเต็มของคุณในรูปแบบที่ไม่เรียงลำดับ Dictดังนั้นจึงจำเป็นต้องมีค่าใช้จ่ายสูงcollect(keys())และcollect(values())อาจcatเป็นsortไปได้ที่จะได้รับข้อมูลที่คุณต้องการ ในหลายกรณีอาจมีราคาถูกกว่าที่จะพิจารณาจากแผนกการทดลอง เศร้า แต่จริง

  2. ใช้แผนที่ mapเป็นทางเลือกที่ดีในการวนซ้ำ ระวังความแตกต่างระหว่างmapและmap!และใช้ประโยชน์จากฟังก์ชั่นแบบแทนที่เมื่อคุณทำได้

  3. ใช้ mapreduce ช่วย mapreduceขยายการทำงานของแผนที่ให้ดียิ่งขึ้นและสามารถเป็นตัวช่วยประหยัดไบต์ที่สำคัญได้

  4. ฟังก์ชั่นนิรนามนั้นยอดเยี่ยมมาก! .. โดยเฉพาะเมื่อผ่านไปยังmapฟังก์ชั่นดังกล่าว

  5. ฟังก์ชันอาเรย์สะสม cumprod , ฟังก์ชันที่cumsumมีรสชาติcumminและชื่ออื่นที่คล้ายกันเปิดใช้งานการดำเนินการสะสมตามมิติที่ระบุของอาเรย์ n-Dim (หรือ * un * ถูกระบุหากอาร์เรย์เป็น 1-d)

  6. สัญกรณ์สั้น ๆ สำหรับใด ๆเมื่อคุณต้องการเลือกทุกมิติของอาเรย์หลายมิติ (หรือ Dict) เช่นA[Any,2]คุณสามารถบันทึกไบต์โดยใช้A[:,2]

  7. ใช้สัญกรณ์บรรทัดเดียวสำหรับฟังก์ชั่นแทนคุณfunction f(x) begin ... endมักจะทำให้ง่ายขึ้นf(x)=(...)

  8. ใช้ผู้ประกอบการที่สามมันสามารถประหยัดพื้นที่สำหรับการแสดงออก If-Then-Else คำเตือน:ในขณะที่เป็นไปได้ในบางภาษาคุณไม่สามารถตัดส่วนหลังลำไส้ใหญ่ในจูเลียได้ นอกจากนี้ตัวดำเนินการเป็นระดับนิพจน์ใน Julia ดังนั้นคุณไม่สามารถใช้เพื่อดำเนินการตามเงื่อนไขของรหัสทั้งหมดได้
    if x<10 then true else false endVS
    x<10?true:false


3
"ใช้ผู้ประกอบการที่ประกอบไปด้วย" บนโลกได้อย่างไรโดยเฉพาะจูเลีย? มันเกี่ยวข้องกับทุกภาษาที่มี
Peter Taylor

5
มันเกี่ยวข้องกับมัน หลายภาษามีแผนที่ฟังก์ชั่นที่ไม่ระบุชื่อหรือบริสุทธิ์บางอย่างของชวเลขสำหรับ / ทั้งหมด, ฟังก์ชั่นสะสม ฯลฯ หากเราลดทุกกระทู้ที่เป็นเคล็ดลับคุณสมบัติเฉพาะที่ไม่ซ้ำกับภาษานั้นจะมีเนื้อหาเคล็ดลับน้อยมาก .
Jonathan Van Matre

3
เอ้ยเป็นเพียงฟังก์ชันที่ใช้งานได้ทั้งหมดสำหรับผู้เริ่มต้นซึ่งทุกอย่างจะส่งกลับค่าดังนั้น op แบบสามส่วนจะซ้ำซ้อน หากคุณต้องมีตัวอย่างเฉพาะ: Go, Haskell, Scala, Lua, VB, Prolog, PL / SQL ... แม้แต่ Python ก็ไม่ได้มีหลายรุ่น ในภาษาที่ใกล้เคียงซึ่งมีเคล็ดลับที่กล่าวถึงผู้ประกอบการที่ประกอบไปด้วยไตรภาคของพวกเขามีเหตุผลอะไรที่คุณเลือกที่จะมาเป็นจังหวัดในเหมือง?
Jonathan Van Matre

3
เอาล่ะอย่างน้อยคุณก็เป็นคนงงงวยที่มีโอกาสเท่ากัน ヘ ( ̄ ー  ̄ ヘ)
Jonathan Van Matre

1
ฉันขอแนะนำให้ปรับปลาย 3 ได้ไหม mapreduce มีความยาวมากกว่า mapfoldl หรือ mapfoldr และสามารถมีพฤติกรรมที่แตกต่างกันไปขึ้นอยู่กับการใช้งาน mapfoldl และ mapfoldr มีความสัมพันธ์ซ้ายและขวา (ตามลำดับ) อย่างสม่ำเสมอจึงเป็นทางเลือกที่ดีกว่า สิ่งนี้ใช้โดยทั่วไปเพื่อลด (ใช้ foldl หรือ foldr)
เกลน O

9

ทำซ้ำมากกว่าฟังก์ชั่น

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

ตัวอย่างเช่นหากต้องการสร้างตารางการบวกการลบการคูณและการหารสำหรับตัวเลขธรรมชาติตั้งแต่ 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ตัวเลขที่ซับซ้อนที่ต้องการทั้งหมด

ตัวอย่างในการแข่งขันจริง


6
  1. บางครั้งคำหลักสามารถติดตามค่าคงที่ได้ทันทีโดยไม่จำเป็นต้องเว้นวรรคหรืออัฒภาค ตัวอย่างเช่น:

    n->(for i=1:n n-=1end;n)

    หมายเหตุการขาดพื้นที่ระหว่างที่และ1 endนี้ยังเป็นจริงสำหรับที่เกิดขึ้นหลังจากที่มีการวงเล็บใกล้คือend)end

  2. ดำเนินการหารจำนวนเต็มโดยใช้÷มากกว่าdiv()หรือมากเกินไปตัวดำเนินการ โปรดทราบว่า÷มีค่า 2 ไบต์ใน UTF-8

  3. ใช้vec()หรือA[:](สำหรับบางอาร์เรย์A) แทนที่จะreshape()เป็นไปได้

  4. สร้างฟังก์ชั่นแทนโปรแกรมเต็มรูปแบบเมื่อได้รับอนุญาตในกฎการท้าทาย มันสั้นกว่าที่จะกำหนดฟังก์ชั่นที่รับอินพุตมากกว่าการกำหนดตัวแปรโดยการอ่านจาก stdin ตัวอย่างเช่น:

    n->(n^2-1)
    n=read(STDIN,Int);n^2-1
  5. ตัวแปรสามารถเพิ่มขึ้นภายในอาร์กิวเมนต์ไปยังฟังก์ชัน ตัวอย่างเช่นต่อไปนี้คือคำตอบของฉันสำหรับการค้นหาเลขฐานสองแบบ 1 เบาบางถัดไป :

    n->(while contains(bin(n+=1),"11")end;n)

    ซึ่งสั้นกว่าการเพิ่มขึ้นnภายในวง


6
  1. ไม่ต้องพิมพ์return f(x)=x+4เป็นเหมือน f(x)=return x+4แต่สั้นกว่า Julia จะส่งคืนผลลัพธ์ของคำสั่งล่าสุดเสมอ
  2. ใช้ = แทนใน [x for x in 1:4]มีความยาวเกิน 3 อักขระ แต่เทียบเท่า[x for x=1:4]

5

ใช้การเรียกฟังก์ชั่นการออกอากาศ

เปิดตัวใน Julia 0.5 มันเป็นเหมือนแผนที่ แต่ใช้ตัวอักษรน้อยลงและออกอากาศพฤติกรรมเหนือสิ่งอื่น - ซึ่งหมายความว่าคุณสามารถเขียนแลมบ์ดาน้อยลงเพื่อจัดการกับสิ่งต่าง ๆ

ค่อนข้างมากกว่า:

  • map(f,x) - 8 ตัวอักษร
  • f.(x) - 5 ตัวอักษร

ยังดีกว่า:

  • map(a->g(a,y),x) - 16 ตัวอักษร
  • g.(x,[y]) - 9 ตัวอักษร
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.