เคล็ดลับการตีกอล์ฟในทับทิม


62

มีเคล็ดลับอะไรที่คุณสามารถให้เล่นกอล์ฟใน Ruby

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

กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ


มีคนต้องการที่จะเขียนภาษาที่เรียกว่าถูซึ่งใช้อักขระ Unicode เดียวสำหรับทุกโทเค็นทับทิม kinda เช่นเยลลี่และ Pyth :)
มาร์คโทมัส

คำตอบ:


46
  • หมายเลข 100-126 สามารถเขียนเป็น?dไป?~ใน 1.8
  • ในบันทึกย่อที่คล้ายกันหากคุณต้องการสตริงอักขระตัวเดียวใน 1.9? x จะสั้นกว่า "x"
  • หากคุณจำเป็นต้องพิมพ์สตริงโดยไม่ต้องต่อท้ายบรรทัดใหม่ให้สั้นกว่า$><<"string"print"string"
  • หากคุณจำเป็นต้องอ่านหลายบรรทัดของการป้อนข้อมูลจะสั้นกว่า$<.map{|l|...} while l=gets;...;endนอกจากนี้คุณสามารถใช้$<.readอ่านมันทั้งหมดในครั้งเดียว
  • หากคุณควรจะอ่านจากไฟล์$<และgetsจะอ่านจากไฟล์แทน stdin ARGVถ้าชื่อไฟล์ที่อยู่ใน ดังนั้นวิธีที่จะตีกอล์ฟให้ได้ผลที่สุดcatก็คือ: $><<$<.read.

1
? x ให้ผลผลิตรหัส ASCII โดยทั่วไปดังนั้นคุณจึงสามารถพิมพ์ได้ทั้งหมดเป็นหลักด้วยตัวอักษรสองตัว 1.9 จะแตกต่างกัน 'a'.ord ให้ผลเป็นตัวเลข ascii แต่มีความยาวมากกว่าสี่สิบสี่ไบต์
Hiato

8
วิธีเดียวที่นักกอล์ฟจะนำไปใช้catคือการปล่อยให้ไฟล์ทับทิมว่างเปล่าโดยสิ้นเชิง (0 ไบต์) และยืนยันว่าควรรันจากบรรทัดคำสั่งด้วย-pแฟล็ก
daniero

1
หรือจากตัวเอง @ daniero ของคำตอบ ,puts *$<
ไม่ว่าชาร์ลส์

1
ดังนั้นใน 1.8 สิ่งที่ฉันต้องทำคือไป? ~ และมันจะคืน 126
ศิลปะที่สวยงามเพียง

5
คุณสามารถไปเกิน 126 โดยใช้ความคิดเหมือนหรือหรือคุณบ้าพอ:?﷽.ord=65021
ศิลปะที่สวยงามเพียง

32

ใช้ตัวดำเนินการเครื่องหมายเพื่อรับส่วนท้ายและส่วนหัวของอาร์เรย์:

head, *tail = [1,2,3]
head => 1
tail => [2,3]

วิธีนี้ใช้งานได้อีกทาง:

*head, tail = [1,2,3]
head => [1,2]
tail => 3

ใช้*วิธีการที่มีสตริงในอาร์เรย์เพื่อเข้าร่วมองค์ประกอบ:

[1,2,3]*?,
=> "1,2,3"

27
  • ใช้abortเพื่อยกเลิกโปรแกรมและพิมพ์สตริงเป็น STDERR - สั้นกว่าputsตามด้วยexit
  • หากคุณอ่านบรรทัดด้วยgetsคุณสามารถใช้~/$/เพื่อค้นหาความยาวของมัน (นี่จะไม่นับบรรทัดใหม่หากมี)
  • ใช้[]เพื่อตรวจสอบว่าสตริงมีอีกอันหรือไม่:'foo'['f'] #=> 'f'
  • ใช้trแทนการgsubเปลี่ยนตัวอักขระที่ชาญฉลาด:'01011'.tr('01','AB') #=> 'ABABB'
  • หากคุณต้องการลบบรรทัดใหม่ต่อท้ายให้ใช้chopแทนchomp

2
+1 สำหรับabortและ~/$/
J -_- L

โปรดอธิบายวิธีใช้~/$/
Mathieu CAROFF

@MathieuCAROFF ทุกครั้งที่คุณโทรgetsผลลัพธ์จะถูกเก็บไว้ใน$_ตัวแปร /regex/ ~= stringส่งคืนดัชนีของการแข่งขันครั้งแรก โทร~ใน regex /regex/ ~= $_เทียบเท่ากับ ดังนั้นมันจะเป็นอย่างไรs=gets;l= ~/$/
Cyoce

20

endปลายของคุณ

ลองลบendจากรหัสของคุณ

อย่าใช้def...endเพื่อกำหนดฟังก์ชั่น สร้างแลมบ์ดาด้วยตัวดำเนินการใหม่ -> ใน Ruby 1.9 (ตัวดำเนินการ -> คือ"stabby lambda" หรือ "dash rocket" ) สิ่งนี้จะบันทึก 5 ตัวอักษรต่อฟังก์ชั่น

# 28 characters
def c n
/(\d)\1/=~n.to_s
end

# 23 characters, saves 5
c=->n{/(\d)\1/=~n.to_s}

เรียกวิธีการมีหรือc n โทรแลมบ์ดามีc(n) c[n]การเปลี่ยนอักขระแต่ละตัวc nให้มีc[n]ราคาเท่ากับ 1 ตัวอักษรดังนั้นหากคุณสามารถใช้งานได้c nมากกว่า 5 ครั้งให้ใช้วิธีนี้ต่อไป

วิธีการทั้งหมดที่ใช้do...endบล็อกสามารถใช้{...}บล็อกแทน วิธีนี้จะช่วยประหยัด 3 ถึง 5 ตัวอักษร หากลำดับความสำคัญของ{...}สูงเกินไปให้ใช้วงเล็บเพื่อแก้ไข

# 48 characters
(?a..?m).zip (1..5).cycle do|a|puts a.join','end

# WRONG: passes block to cycle, not zip
(?a..?m).zip (1..5).cycle{|a|puts a.join','}

# 45 characters, saves 3
(?a..?m).zip((1..5).cycle){|a|puts a.join','}

แทนที่if...else...endกับผู้ประกอบ ternary ?:ถ้าสาขามีสองคำสั่งหรือมากกว่าให้ห่อมันไว้ในวงเล็บ

# 67 characters
if a<b
puts'statement 1'
puts'statement 2'else
puts'statement 3'end

# 62 characters, saves 5
a<b ?(puts'statement 1'
puts'statement 2'):(puts'statement 3')

คุณอาจไม่มีwhileหรือuntilลูป แต่ถ้าคุณทำแล้วเขียนพวกเขาในรูปแบบปรับปรุง

(a+=1
b-=1)while a<b

วงเล็บputs'statement 3'จำเป็นหรือไม่?
Cyoce

15

นอกจากนี้เพื่อ w0lf

เมื่อทำงานกับอาร์เรย์คุณ.compactสามารถแทนที่ด้วย-[nil]เพื่อบันทึก 2 ตัวอักษร

รวมกับด้านบน -> คุณสามารถทำให้สั้นลงได้ด้วย-[p]เพื่อประหยัดอีก 2 ตัวอักษร


14

ใช้ตัวแปรที่กำหนดไว้สั้น ๆ หากทำได้เช่น$*แทนที่จะARGVใช้ มีรายการที่ดีของพวกเขาที่นี่พร้อมกับข้อมูลที่เป็นประโยชน์อื่น ๆ อีกมากมาย


12

เมื่อคุณใช้สตริงการแก้ไข (ตามที่คุณควร pr โพสต์มาร์ตินBüttnerของ ) คุณไม่จำเป็นต้องวงเล็บปีกกาถ้าวัตถุของคุณมีเครื่องหมาย ( $, @) ในด้านหน้าของมัน ที่เป็นประโยชน์สำหรับตัวแปรที่มีมนต์ขลังเหมือน$_, $&, $1ฯลฯ :

puts "this program has read #$. lines of input"

ดังนั้นหากคุณต้องการพิมพ์ตัวแปรมากกว่าที่คุณใช้อย่างอื่นคุณอาจบันทึกบางไบต์

a=42; puts "here is a: #{a}"; puts "here is a again: #{a}"
$b=43; puts "here is b: #$b"; puts "here is b again: #$b"

11

หากคุณต้องการค้นหาว่าองค์ประกอบเฉพาะeอยู่ในช่วงrหรือไม่คุณสามารถใช้

r===e

แทนอีกต่อไป:

r.cover?(e) # only works if `r.exclude_end?` is false

หรือ

r.member?(e)

หรือ

r.include?(e)

3
ไม่r===eสั้นกว่านี้ใช่ไหม
akuhn

@akuhn ใช่มันเป็น มากสั้น ขอบคุณที่ชี้ให้เห็นว่ามันช่วยให้ฉันย่อโค้ดของฉันลง 10 chars ซึ่งมีขนาดใหญ่มาก: codegolf.stackexchange.com/a/6125/3527
Cristian Lupascu

1
ไม่เป็นไร ทุกอย่างที่สามารถใช้ได้ในคำสั่ง switch ได้ถูก===นำไปใช้งาน
akuhn

10

$_ เป็นบรรทัดสุดท้ายที่อ่าน

  • print - หากไม่มีการโต้แย้งให้เนื้อหาการพิมพ์ของ $_
  • ~/regexp/ - ย่อจาก $_=~/regexp/

ใน Ruby 1.8 คุณมีสี่วิธีในการKernelทำงาน$_:

  • chop
  • chomp
  • sub
  • gsub

ในทับทิม 1.9 เหล่านี้สี่วิธีการที่มีอยู่เฉพาะในกรณีที่คุณใช้สคริปต์หรือ-n-p

หากคุณต้องการพิมพ์ตัวแปรบางตัวก็ให้ใช้ trace_var(:var_name){|a|p a}


2
สิ่งเหล่านี้จะใช้ได้เฉพาะเมื่อคุณรัน Ruby ด้วยตัวเลือก -pหรือ การอ้างอิง -n
Darren Stone

1
ดูเหมือนว่าtrace_varจะใช้ได้กับตัวแปร $ ทั่วโลกเท่านั้น
daniero

10

ใช้การแก้ไขสตริง!

  1. to_sจะเข้ามาแทนที่ หากคุณต้องการวงเล็บในสิ่งที่คุณต้องการเปลี่ยนเป็นสตริงto_sมีความยาวมากกว่าการแก้ไขสตริงสองไบต์

    (n+10**i).to_s
    "#{n+10**i}"
    
  2. เพื่อแทนที่การต่อข้อมูล หากคุณต่อสิ่งที่ล้อมรอบด้วยสตริงอื่นสองตัวการแก้ไขสามารถช่วยคุณหนึ่งไบต์:

    "foo"+c+"bar"
    "foo#{c}bar"
    

    นอกจากนี้ยังทำงานได้ถ้าสิ่งที่อยู่ตรงกลางของตัวเอง concatenated ถ้าคุณเพียงแค่ย้ายการเรียงต่อกันในการแก้ไข (แทนการใช้การแก้ไขหลาย ๆ ):

    "foo"+c+d+e+"bar"
    "foo#{c+d+e}bar"
    

10

หลีกเลี่ยงการlengthอยู่ในif a.length<n

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

ดังนั้นคุณสามารถเปลี่ยน:

if a.length<5ถึงif !a[4]-5 ไบต์

หรือ

if a.length>5ถึงif a[5]-6 ไบต์

หรือ

if a.length<nถึงif !a[n-1]-3 ไบต์

หรือ

if a.length>nถึงif a[n]-6 ไบต์

หมายเหตุ : จะทำงานกับอาร์เรย์ของค่าความจริงทั้งหมดเท่านั้น มีnilหรือfalseภายในอาร์เรย์อาจทำให้เกิดปัญหา


4
ฉันมักจะใช้size... แต่นี่ดีกว่าแน่นอน BTW ก็ใช้ได้Stringเช่นกัน
จัดการ

10

อย่าใช้trueและfalseคำหลัก

ใช้:

  • !pสำหรับtrue(ขอบคุณ histocrat!)
  • !0falseสำหรับ หากสิ่งที่คุณต้องการคือค่าที่ผิดพลาดคุณสามารถใช้p(ซึ่งคืนค่าnil)

เพื่อบันทึกตัวอักษร


1
ถ้าคุณต้องการจริงtrue(เช่นถ้าค่า truthy เป็นพอเช่นในถ้าเงื่อนไข), !!คุณไม่จำเป็นต้อง
Martin Ender

4
และในทำนองเดียวกันp(ซึ่งประเมินผลnil) เป็นค่าที่สั้นลง ซึ่งหมายความว่าทางที่สั้นที่สุดที่จะได้รับคือtrue !p
ฮิสโทแกต

@histocrat จุดดี! ฉันแก้ไขคำตอบของฉันแล้ว
Cristian Lupascu

9

สร้างอาร์เรย์โดยใช้a=i,*aเพื่อให้ได้ในลำดับที่กลับกัน คุณไม่จำเป็นต้องเริ่มต้นaและถ้าคุณทำมันไม่จำเป็นต้องเป็นอาร์เรย์


9

หากคุณต้องการที่จะได้รับหมายเลขจากARGV, getหรือสิ่งที่คล้ายกันที่จะทำอะไรบางอย่างที่หลายต่อหลายครั้งแทนการโทรto_iในนั้นคุณก็สามารถใช้?1.upto x{do something x times}ที่ x เป็นสตริง

ดังนั้นการใช้?1.upto(a){}แทนที่จะx.to_i.times{}ช่วยให้คุณประหยัด 2 ตัวอักษร

คุณยังสามารถเขียนสิ่งต่าง ๆ เช่นp 1 while 1หรือp 1 if 1เป็นp 1while 1หรือp 1if 1

ตัวอย่างนั้นไม่มีประโยชน์มาก แต่สามารถใช้เพื่อสิ่งอื่นได้

นอกจากนี้หากคุณต้องการกำหนดองค์ประกอบแรกของอาร์เรย์ให้กับตัวแปรa,=cจะบันทึกอักขระสองตัวตรงข้ามกับa=c[0]


9

คุณสมบัติใหม่ใน Ruby 2.3 และ 2.4

มันเป็นการดีที่จะอยู่เคียงข้างคุณสมบัติภาษาใหม่ที่จะช่วยให้เกมกอล์ฟของคุณ มีบางอย่างที่ยอดเยี่ยมในทับทิมล่าสุด

ทับทิม 2.3

ผู้ประกอบการนำทางที่ปลอดภัย: &.

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

arr = ["zero", "one", "two"]
x = arr[5].size
# => NoMethodError: undefined method `size' for nil:NilClass

x = arr[5].size rescue 0
# => 0

"โอเปอเรเตอร์ที่ปลอดภัย" จะหยุดการเรียกใช้เมธอดหากหนึ่งส่งคืนnilและส่งคืนnilสำหรับนิพจน์ทั้งหมด

x = arr[5]&.size || 0
# => 0

Array#dig & Hash#dig

เข้าถึงองค์ประกอบที่ซ้อนกันอย่างลึกซึ้งด้วยชื่อย่อที่ดี:

o = { foo: [{ bar: ["baz", "qux"] }] }
o.dig(:foo, 0, :bar, 1) # => "qux"

ผลตอบแทนnilถ้ามันชนตาย:

o.dig(:foo, 99, :bar, 1) # => nil

Enumerable#grep_v

การผกผันของEnumerable#grep- ส่งคืนองค์ประกอบทั้งหมดที่ไม่ตรงกับอาร์กิวเมนต์ที่กำหนด (เทียบกับ===) เช่นgrepถ้าบล็อกได้รับผลลัพธ์จะถูกส่งคืนแทน

(1..10).grep_v 2..5 # => [1, 6, 7, 8, 9, 10]
(1..10).grep_v(2..5){|v|v*2} # => [2, 12, 14, 16, 18, 20]

Hash#to_proc

ส่งคืน Proc ที่ให้ค่าสำหรับคีย์ที่กำหนดซึ่งสามารถทำได้ค่อนข้างดี:

h = { N: 0, E: 1, S: 2, W: 3 }
%i[N N E S E S W].map(&h)
# => [0, 0, 1, 2, 1, 2, 3]

ทับทิม 2.4

Ruby 2.4 ยังไม่ออก แต่จะเปิดตัวเร็ว ๆ นี้พร้อมคุณสมบัติเล็ก ๆ น้อย ๆ (เมื่อวางจำหน่ายฉันจะอัปเดตโพสต์นี้พร้อมลิงก์ไปยังเอกสาร) ฉันเรียนรู้เกี่ยวกับส่วนใหญ่ในโพสต์บล็อกที่ยอดเยี่ยมนี้

Enumerable#sum

ไม่มีอีกarr.reduce(:+)แล้ว arr.sumขณะนี้คุณสามารถเพียงแค่ทำ ใช้อาร์กิวเมนต์ตัวเลือกค่าเริ่มต้นซึ่งมีค่าเริ่มต้นเป็น 0 สำหรับองค์ประกอบที่เป็นตัวเลข ( [].sum == 0) สำหรับประเภทอื่นคุณจะต้องระบุค่าเริ่มต้น นอกจากนี้ยังยอมรับบล็อกที่จะใช้กับแต่ละองค์ประกอบก่อนเพิ่ม:

[[1, 10], [2, 20], [3, 30]].sum {|a,b| a + b }
# => 66

Integer#digits

ส่งคืนอาร์เรย์ของตัวเลขในลำดับที่มีนัยสำคัญน้อยไปหามาก:

123.digits # => [3, 2, 1]

เปรียบเทียบกับพูดว่า123.to_s.chars.map(&:to_i).reverseมันดีทีเดียว

เป็นโบนัสจะใช้อาร์กิวเมนต์ตัวเลือก Radix:

a = 0x7b.digits(16) # => [11, 7]
a.map{|d|"%x"%d} # => ["b", "7"]

Comparable#clamp

ทำในสิ่งที่พูดบนกระป๋องหรือไม่:

v = 15
v.clamp(10, 20) # => 15
v.clamp(0, 10) # => 10
v.clamp(20, 30) # => 20

เนื่องจากอยู่ใน Comparable คุณสามารถใช้กับคลาสใดก็ได้ที่มี Comparable เช่น:

?~.clamp(?A, ?Z) # => "Z"

String#unpack1

ประหยัด 2 ไบต์มากกว่า.unpack(...)[0]:

"👻💩".unpack(?U)    # => [128123]
"👻💩".unpack(?U)[0] # => 128123
"👻💩".unpack1(?U)   # => 128123

อาร์กิวเมนต์แม่นยำสำหรับNumeric#ceil, floorและtruncate

Math::E.ceil(1) # => 2.8
Math::E.floor(1) # => 2.7
(-Math::E).truncate(1) # => -2.7

การมอบหมายหลายอย่างในเงื่อนไข

สิ่งนี้ทำให้เกิดข้อผิดพลาดใน Ruby รุ่นก่อนหน้า แต่ได้รับอนุญาตใน 2.4

(a,b=1,2) ? "yes" : "no" # => "yes"
(a,b=nil) ? "yes" : "no" # => "no"

กอล์ฟMath::E.ceil(1)การMath::E.ceil 1และเช่นเดียวกันสำหรับและfloor truncate
ศิลปะที่สวยงามเรียบง่าย

1
@SimplyBeautifulArt ฉันคาดหวังว่าคนที่เล่นกอล์ฟใน Ruby จะสามารถกระโดดได้เอง
จอร์แดน

สำหรับEnumerable#sum, .flatten.sum2 ไบต์สั้นกว่า.sum{|a,b|a+b}
Asone Tuhid

(-Math::E).truncate(1)เทียบเท่ากับ-Math::E.truncate(1)ที่สั้นกว่า 1 ไบต์
Asone Tuhid

1
&.สามารถใช้กับตัวห้อยแบบนี้a&.[]i(สั้นกว่า 1 ไบต์a&.at i) แม้ว่าหากจำเป็นต้องใช้ตัวยึดจะa||a[i]มีขนาด 1 ไบต์สั้นกว่าa&.[](i)หรือa&.at(i)
Asone Tuhid

7

สัญกรณ์ทางวิทยาศาสตร์มักจะสามารถใช้ในการโกนถ่านหรือสอง:

x=1000
#versus
x=1e3

9
หมายเหตุ: สิ่งนี้จะส่งคืนค่า Float (1000.0) แทน Integer ซึ่งอาจทำให้ผลลัพธ์ที่ไม่ถูกต้องมีจำนวนมาก
Dogbert

4
อ๊ะดี1e2กว่า100.0เมื่อต้องการเปอร์เซ็นต์
Phrogz

คล้ายกับหลักการนี้1.0*คือ 1 ตัวอักษรสั้นกว่า.to_f
Unihedron

7

ใช้วิธีการตัวดำเนินการแทนวงเล็บ

a*(b+c)สมมติว่าคุณต้องการที่จะแสดง เนื่องจากความสำคัญกว่าa*b+cจะไม่ทำงาน (ชัด) วิธีที่ยอดเยี่ยมของ Ruby ในการมีผู้ปฏิบัติงานเป็นวิธีการเพื่อช่วยชีวิต! คุณสามารถใช้a.*b+cเพื่อให้ความสำคัญของการต่ำกว่าที่ของ*+

a*(b+c) # too long
a*b+c   # wrong
a.*b+c  # 1 byte saved!

นอกจากนี้ยังสามารถทำงานกับ!และ~ตัวดำเนินการ (สิ่งต่าง ๆ เช่นเอก+หรือเอก-ไม่ทำงานเพราะวิธีการของพวกเขา-@และ+@ประหยัด()แต่เพิ่ม.@)

(~x).to_s # too long
~x.to_s   # error
x.~.to_s  # 1 byte saved!

6

ใช้||แทนorและแทน&&and

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

p true and false ? 'yes' :'no'   #-> true (wrong result)
p (true and false) ? 'yes' :'no' #-> 'no'
p true&&false ? 'yes' :'no'      #-> 'no', saved 5 characters


p true or false ? 'yes' :'no'   #-> true (wrong result)
p (true or false) ? 'yes' :'no' #-> 'yes'
p true||false ? 'yes' :'no'      #-> 'yes', saved 4 characters

eachหากคุณวงในอาร์เรย์ปกติคุณจะใช้ แต่จะmapวนซ้ำไปเรื่อย ๆ ในอาเรย์และมันก็สั้นกว่าตัวละครตัวหนึ่ง


6

ฉันเพิ่งลองรหัสกอล์ฟ - ท้าทาย TDD เช่นเขียนรหัสที่สั้นที่สุดเพื่อให้สเป็คผ่าน รายละเอียดเป็นอะไรที่ชอบ

describe PigLatin do
  describe '.translate' do
    it 'translates "cat" to "atcay"' do
      expect(PigLatin.translate('cat')).to eq('atcay')
    end
    # And similar examples for .translate
  end
end

เพื่อประโยชน์ของ code-golf เราไม่จำเป็นต้องสร้างโมดูลหรือคลาส

แทน

module PigLatin def self.translate s;'some code'end;end

หนึ่งสามารถทำได้

def(PigLatin=p).translate s;'some code'end

บันทึกได้ 13 ตัวอักษร!


7
ฮาถี่มาก ไม่เพียง แต่คุณเพิ่มพฤติกรรมที่จำเป็นในการPigLatinแต่ยัง@pig_latin, และ$pig_latin 'pig'['latin']
ฮิสโทแกต

@histocrat: ตอนนี้ฉันเข้าใจแล้ว ก็เพราะได้รับการกำหนดไว้ในtranslate nil
Eric Duminil

6

เคอร์เนล # pเป็นวิธีการที่สนุก

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

ใช้กับอาร์กิวเมนต์เดี่ยวpส่งคืนอาร์กิวเมนต์หลังจากพิมพ์

ใช้กับอาร์กิวเมนต์หลายตัวpส่งคืนอาร์กิวเมนต์ในอาร์เรย์

ใช้p(ที่มีการขัดแย้งใด) nilแทน


10
น่าเสียดายที่p 'some string'พิมพ์"some string"และไม่เพียง แต่some stringถูกวิจารณ์โดยคนอื่นบ่อยๆ
Patrick Oscity

1
โดยพื้นฐานแล้วp sจะเหมือนกันputs s.inspectแต่จะกลับมาs
Cyoce

6

อย่าใช้ #each คุณสามารถวนซ้ำองค์ประกอบทั้งหมดได้ดีด้วย #map ดังนั้นแทนที่จะ

ARGV.each{|x|puts x}

คุณสามารถทำเช่นเดียวกันในไบต์น้อย

ARGV.map{|x|puts x}

แน่นอนในกรณีนี้puts $*จะยิ่งสั้นลง


มีตัวอักษรสำหรับจำนวนตรรกยะและจำนวนเชิงซ้อน:

puts 3/11r == Rational(3,11)
puts 3.3r == Rational(66,20)
puts 1-1.i == Complex(1,-1)

=> true
true
true

คุณสามารถใช้ไบต์ส่วนใหญ่ภายในสตริง "\x01"(6 ไบต์) สามารถย่อให้เหลือ""(3 ไบต์) หากคุณต้องการเพียงหนึ่งไบต์สิ่งนี้สามารถย่อให้สั้นลงไปอีก?(2 ไบต์)

ในทำนองเดียวกันคุณสามารถขึ้นบรรทัดใหม่ให้สั้นลงเช่นนี้

(0..10).to_a.join'
'

 => "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10"

คุณสามารถใช้?\nและ?\tได้เป็นอย่างดีซึ่งเป็นหนึ่งไบต์สั้นกว่าและ"\n" "\t"สำหรับความงงงวยยังมีช่องว่าง?


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

A=C+B=7+C=9

=> A=17, B=16, C=9

นี่คือสั้นกว่าหรือC=9;B=16;A=17C=0;B=C+7;A=C+B


loop{...}หากคุณจำเป็นต้องห่วงอนันต์ใช้ ลูปที่มีความยาวที่ไม่รู้จักอาจสั้นกว่ากับลูปอื่น ๆ :

loop{break if'
'==f(gets)}

while'
'!=f(gets);end

เทคนิค gsub / regexp เพิ่มเติม ใช้'\1'อักขระ escape พิเศษแทนบล็อก:

"golf=great short=awesome".gsub(/(\w+)=(\w+)/,'(\1~>\2)')

"golf=great short=awesome".gsub(/(\w+)=(\w+)/){"(#{$1}~>#{$2})")

และตัวแปรพิเศษ$1เป็นต้นหากคุณต้องการดำเนินการ โปรดทราบว่ามีการกำหนดไว้ไม่เพียง แต่ภายในบล็อกเท่านั้น:

"A code-golf challenge." =~ /(\w+)-(\w+)/
p [$1,$2,$`,$']

=> ["code", "golf", "A ", " challenge."] 

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

x+=1if$*<<A==????::??==??

"กรุณาโพสต์หนึ่งคำตอบต่อคำตอบ" นอกจากนี้ยัง?\nเป็นสิ่งที่ดี แต่ไม่ได้จริงๆสั้นกว่าจริงใส่ตัวอักษรขึ้นบรรทัดใหม่ให้อยู่ในเครื่องหมาย (เหมือนกันสำหรับแท็บ)
Martin Ender

และputs$*ยิ่งสั้น
Cyoce

ฉันรู้ว่าคุณกำลังพยายามพิสูจน์จุด แต่ฉันค่อนข้างแน่ใจว่าตัวอย่างสุดท้ายเป็นเช่นเดียวกับx+=1;$*<<A
Asone Tuhid

6

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

a=[0]
*a=0

ด้วยค่าหลายค่าคุณไม่จำเป็นต้องใช้ตัวดำเนินการ splat (ด้วย histocrat สำหรับการแก้ไขในส่วนนั้น):

a=[1,2]
a=1,2

กรณีหลังไม่จำเป็นต้องมีเครื่องหมาย
ฮิสโทแคต

@histocrat โอ้ว้าวฉันคิดว่าค่าที่สองจะถูกยกเลิกในกรณีนั้น
Martin Ender

1
ฉันไม่อยากจะเชื่อเลยว่าฉันไม่ได้รู้จักสิ่งเหล่านี้ตลอดเวลาที่ฉันเล่นกอล์ฟในรูบี
Doorknob

6

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

> a = %w(testing one two three)
> puts a
testing
one
two
three

การรวมตัวดำเนินการสีแดงกับ#pคุณสามารถทำให้มันสั้นลงได้:

p *a

ผู้ประกอบการ splat (ในทางเทคนิค*@แล้วฉันคิดว่า) มันจะแปลงค่าตัวเลขที่ไม่ใช่อาร์เรย์ของคุณไปเป็นอาร์เรย์:

> p a.lazy.map{|x|x*2}
#<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:map>

VS

> p *a.lazy.map{|x|x*2}
2
4
6

1
*@ไม่ใช่วิธี splat คือน้ำตาล syntactic
Asone Tuhid

6

บันทึกบางไบต์เมื่อลบองค์ประกอบที่ซ้ำกันของอาร์เรย์

a.uniq # before
a|[]   # after
    ^^

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

a.uniq;b=[] # before
a|b=[]      # after
      ^^^^^

2
สำหรับกรณีแรกa&aจะสั้นกว่า 1 ไบต์
Asone Tuhid

5

ใช้ Goruby แทน Ruby ซึ่งเป็นสิ่งที่คล้ายกับ Ruby รุ่นย่อ คุณสามารถติดตั้งได้ด้วย rvm ผ่านทาง

rvm install goruby

Goruby อนุญาตให้คุณเขียนรหัสส่วนใหญ่ของคุณตามที่คุณต้องการจะเขียน Ruby แต่มีตัวย่อเพิ่มเติมอยู่ภายในเพื่อค้นหาคำย่อที่มีให้สั้นที่สุดสำหรับบางสิ่งคุณสามารถใช้วิธีผู้ช่วยshortest_abbreviationตัวอย่างเช่น

shortest_abbreviation :puts
#=> "pts"

Array.new.shortest_abbreviation :map
#=> "m"

String.new.shortest_abbreviation :capitalize
#=> "cp"

Array.new.shortest_abbreviation :join
#=> "j"

นอกจากนี้ยังมีประโยชน์มากเป็นนามแฝงsayสำหรับที่ตัวเองสามารถย่อด้วยputs sดังนั้นแทนที่จะ

puts [*?a..?z].map(&:capitalize).join

ตอนนี้คุณสามารถเขียน

s [*?a..?z].m(&:cp).j

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

PS: อย่าพลาดhวิธี ;-)


มากกว่า 2 ปีต่อมาและในที่สุดฉันก็ค้นพบสิ่งที่คำตอบนี้ทำให้ฉันนึกถึง ...
undergroundmonorail

5

หากต้องการเข้าร่วมอาร์เรย์แทนที่จะเป็นเช่นนี้

[...].join

ทำเช่นนี้

[...]*''

ซึ่งช่วยประหยัด 2 ไบต์ เพื่อเข้าร่วมกับการใช้ตัวคั่น

[...]*?,

5

หมายเลขตัวห้อย!

ฉันเพิ่งค้นพบเมื่อวานนี้ n[i]ส่งกลับnบิตของiตำแหน่งที่ -th ตัวอย่าง:

irb(main):001:0> n = 0b11010010
=> 210
irb(main):002:0> n[0]
=> 0
irb(main):003:0> n[1]
=> 1
irb(main):004:0> n[2]
=> 0
irb(main):005:0> n[3]
=> 0
irb(main):006:0> n[4]
=> 1
irb(main):007:0> n[5]
=> 0

และตอนนี้คุณสามารถใช้อาร์กิวเมนต์เพิ่มเติมเช่นn[0..3]
ศิลปะที่สวยงามเพียงแค่

4

คุณสามารถบันทึก 2 ตัวอักษรและใช้งานได้

[*(...)]

แทน

(...).to_a

ตัวอย่างเช่นสมมติว่าเรามีช่วงที่เราต้องการเป็นอาร์เรย์:

(1..2000).to_a

เพียงทำแบบนี้:

[*1..2000]  #  Parentheses around the (ran..ge) is not needed!

และตอนนี้คุณมีช่วงของคุณเป็นอาร์เรย์


5
ฉันคิดว่าได้[*1..2000]ผลเช่นกัน?
ลินน์

4

<< เคล็ดลับ

a.push x

สามารถย่อให้เหลือ:

a<<x

สำหรับ -4 ไบต์


2
หมายเหตุ: สิ่งนี้ใช้ได้กับStrings
Cyoce

4

Array#assoc/rassoc

เมื่อคุณมีอาร์เรย์ของอาร์เรย์และต้องการหาอาร์เรย์ย่อยที่เริ่มต้นด้วยค่าเฉพาะอย่าใช้Enumerable#findใช้Array#assoc:

a = [[0,"foo"],[0,"bar"],[1,"baz"],[0,"qux"]]
a.find{|x,|x==1} # => [1,"baz"]
a.assoc(1) # => [1,"baz"]

นี่ก็เป็นการทดแทนที่ดีสำหรับEnumerable#any?ในบางสถานการณ์

Array#rassoc ทำสิ่งเดียวกัน แต่ตรวจสอบองค์ประกอบสุดท้ายของอาร์เรย์ย่อย:

a = [[123,"good"],[456,"good"]]
a.any?{|*,x|x=="bad"} # => false
a.rassoc("bad") # => nil

สำหรับa.any?บรรทัดในrassoc ตัวอย่างจะ|x,|ทำอะไร? แตกต่างจาก|x|อย่างไร
Cyoce

@Cyoce บล็อกพารามิเตอร์ destructuring ตามกฎเช่นเดียวกับที่ได้รับมอบหมาย destructuring ดังนั้นมันก็เหมือนVSx=[1,2] x,=[1,2]โดยใช้ตัวอย่างของฉันข้างต้นด้วย|x|ในซ้ำแรกจะเป็นx [0,"foo"]ด้วย|x,y|, xจะเป็น0และจะเป็นy "foo"ในทำนองเดียวกันกับ|x,|, จะx 0กล่าวอีกนัยหนึ่งก็คือ "ใส่องค์ประกอบแรกเข้าxและโยนส่วนที่เหลือออกไป
จอร์แดน

โปรดทราบว่ามันไม่ทำงานในสิ่งที่ตรงกันข้ามเช่น|,y|เป็น SyntaxError, เออร์|_,y|โก แต่ตอนนี้ฉันเพิ่งรู้ว่าใช้|*,y|งานได้ดีกว่าการใช้ตัวแปรชื่อ_(แต่ไม่สั้นกว่า)
Jordan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.