Lời khuyên cho việc chơi golf trong Ruby


62

Những lời khuyên chung nào bạn có thể đưa ra cho việc chơi golf trong Ruby?

Tôi đang tìm kiếm những ý tưởng có thể được áp dụng cho các vấn đề về golf nói chung dành riêng cho Ruby. (Ví dụ: "Xóa nhận xét" sẽ không phải là câu trả lời.)

Xin vui lòng gửi một lời khuyên cho mỗi câu trả lời.


Ai đó cần viết một ngôn ngữ gọi là Rub, sử dụng một ký tự Unicode duy nhất cho mỗi mã thông báo Ruby, giống như Jelly và Pyth :)
Mark Thomas

Câu trả lời:


46
  • Những con số 100-126 có thể được viết như ?dđể ?~ở 1.8.
  • Trên một lưu ý tương tự nếu bạn cần một chuỗi ký tự đơn trong 1.9? X ngắn hơn "x".
  • Nếu bạn cần in một chuỗi mà không nối thêm một dòng mới, $><<"string"thì ngắn hơn print"string".
  • Nếu bạn cần đọc nhiều dòng đầu vào $<.map{|l|...}thì ngắn hơn while l=gets;...;end. Ngoài ra, bạn có thể sử dụng $<.readđể đọc tất cả cùng một lúc.
  • Nếu bạn phải đọc từ một tệp $<getssẽ đọc từ tệp thay vì stdin nếu tên tệp được đặt trong ARGV. Vì vậy, cách tốt nhất để thực hiện lại catsẽ là : $><<$<.read.

1
? x mang lại mã ascii nói chung, do đó bạn thực sự có thể nhận được tất cả các bản in thành chữ số trong hai ký tự. 1.9 thì khác, 'a'.ord mang lại số ascii, nhưng dài hơn bốn byte so với phiên bản thập phân.
Hiato

8
Một cách thậm chí còn tốt hơn để thực hiện catlà để trống tệp ruby ​​(0 byte) và nhấn mạnh rằng nó nên được chạy từ dòng lệnh với -pcờ.
daniero

1
hoặc, từ câu trả lời của chính @ daniero ,puts *$<
Không phải là Charles

1
Vậy trong 1.8, tất cả những gì tôi phải làm là đi? ~ Và nó sẽ trả về 126?
Nghệ thuật đơn giản đẹp

5
Bạn có thể vượt ra ngoài 126 bằng cách sử dụng suy nghĩ như hoặc , hoặc nếu bạn đủ điên rồ:?﷽.ord=65021
Nghệ thuật đơn giản đẹp

32

Sử dụng toán tử splat để lấy đuôi và đầu của một mảng:

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

Điều này cũng hoạt động theo cách khác:

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

Sử dụng *phương thức với một chuỗi trên một mảng để nối các phần tử:

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

27
  • Sử dụng abortđể chấm dứt chương trình và in một chuỗi thành STDERR - ngắn hơn putstheo sau bởiexit
  • Nếu bạn đọc một dòng với gets, thì bạn có thể sử dụng ~/$/để tìm độ dài của nó (điều này không tính một dòng mới nếu nó tồn tại)
  • Sử dụng []để kiểm tra xem một chuỗi có chứa chuỗi khác không:'foo'['f'] #=> 'f'
  • Sử dụng trthay vì gsubcho thay thế nhân vật khôn ngoan:'01011'.tr('01','AB') #=> 'ABABB'
  • Nếu bạn cần xóa các dòng mới, hãy sử dụng chopthay vìchomp

2
+1 cho abort~/$/
J -_- L

Vui lòng giải thích cách sử dụng~/$/
Mathieu CAROFF

@MathieuCAROFF mỗi khi bạn gọi gets, kết quả của nó được lưu trong $_biến. /regex/ ~= stringtrả về chỉ số của trận đấu đầu tiên Gọi ~một regex là tương đương với /regex/ ~= $_. Vì vậy, nó sẽ là một cái gì đó giống nhưs=gets;l= ~/$/
Cyoce

20

Kết thúc của bạn end.

Cố gắng loại bỏ endkhỏi mã của bạn.

Đừng sử dụng def...endđể xác định chức năng. Tạo lambda với toán tử mới -> trong Ruby 1.9. (Toán tử -> là "lambda stabby" hoặc "tên lửa dash" .) Điều này giúp tiết kiệm 5 ký tự cho mỗi chức năng.

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

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

Các cuộc gọi phương thức là c nhoặc c(n). Lambda gọi là c[n]. Thay đổi từng c nđến c[n]chi phí 1 nhân vật, vì vậy nếu bạn có thể sử dụng c nnhiều hơn 5 lần, sau đó tiếp tục phương pháp này.

Tất cả các phương pháp lấy do...endkhối có thể lấy {...}khối thay thế. Điều này tiết kiệm 3 đến 5 ký tự. Nếu mức độ ưu tiên {...}quá cao, thì hãy sử dụng dấu ngoặc đơn để sửa nó.

# 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','}

Thay thế if...else...endbằng toán tử ternary ?: . Nếu một nhánh có hai hoặc nhiều câu lệnh, hãy gói chúng trong ngoặc đơn.

# 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')

Bạn có thể không có whilehoặc untilvòng lặp, nhưng nếu bạn làm vậy, hãy viết chúng ở dạng sửa đổi.

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

Là dấu ngoặc đơn xung quanh puts'statement 3'cần thiết?
Cyoce

15

Ngoài ra với w0lf

Khi làm việc với mảng, .compactcó thể được thay thế bằng -[nil]để lưu 2 ký tự.

Kết hợp với ở trên -> bạn có thể làm cho nó thậm chí ngắn hơn -[p]để lưu 2 ký tự khác.


14

Sử dụng các biến được xác định trước ngắn bất cứ nơi nào có thể, ví dụ $*thay vì ARGV. Có một danh sách tốt về chúng ở đây , cùng với rất nhiều thông tin hữu ích khác.


12

Khi bạn đang sử dụng phép nội suy chuỗi, (như bạn nên đăng bài của Martin Büttner ), bạn không cần dấu ngoặc nhọn nếu đối tượng của bạn có sigil ( $, @) phía trước nó. Hữu ích cho các biến huyền diệu như $_, $&, $1vv:

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

Vì vậy, nếu bạn cần in một biến nhiều hơn bạn sử dụng nó, bạn có thể lưu một số byte.

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

Nếu bạn cần tìm xem một phần tử cụ thể ecó nằm trong phạm vi không r, bạn có thể sử dụng

r===e

thay vì dài hơn:

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

hoặc là

r.member?(e)

hoặc là

r.include?(e)

3
r===eThậm chí còn không ngắn hơn?
akuhn

@akuhn Vâng, đúng vậy. Ngắn hơn nhiều. Cảm ơn bạn đã chỉ ra điều đó, nó đã giúp tôi rút ngắn mã của mình xuống 10 ký tự, rất lớn: codegolf.stackexchange.com/a/6125 / 3527
Cristian Lupascu

1
Không có gì. Tất cả mọi thứ có thể được sử dụng trong một tuyên bố chuyển đổi đã được ===thực hiện.
akuhn

10

$_ là dòng đọc cuối cùng.

  • print - nếu không có đối số cho nội dung in của $_
  • ~/regexp/ - viết tắt của $_=~/regexp/

Trong Ruby 1.8, bạn có bốn phương thức Kernelhoạt động trên $_:

  • chop
  • chomp
  • sub
  • gsub

Trong Ruby 1.9, bốn phương thức này chỉ tồn tại nếu tập lệnh của bạn sử dụng -nhoặc -p.

Nếu bạn muốn in một số biến thường xuyên thì hãy sử dụng trace_var(:var_name){|a|p a}


2
Chúng chỉ khả dụng khi bạn chạy Ruby với tùy chọn -phoặc -n. Tài liệu tham khảo.
Darren Stone

1
Có vẻ như trace_varchỉ hoạt động với các biến $ toàn cầu
daniero

10

Sử dụng phép nội suy chuỗi!

  1. Để thay thế to_s. Nếu bạn cần dấu ngoặc đơn xung quanh bất cứ thứ gì bạn muốn biến thành chuỗi, to_sdài hơn hai byte so với phép nội suy chuỗi:

    (n+10**i).to_s
    "#{n+10**i}"
    
  2. Để thay thế nối. Nếu bạn nối một cái gì đó được bao quanh bởi hai chuỗi khác, phép nội suy có thể giúp bạn tiết kiệm một byte:

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

    Cũng hoạt động nếu điều trung gian được nối chính nó, nếu bạn chỉ di chuyển phép nối bên trong phép nội suy (thay vì sử dụng nhiều phép nội suy):

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

10

Tránh lengthtrongif a.length<n

lengthlà 6 byte, một chút tốn kém trong mã golf. trong nhiều tình huống, thay vào đó, bạn có thể kiểm tra xem mảng có bất cứ thứ gì tại một điểm nhất định không. nếu bạn vượt qua chỉ số cuối cùng bạn sẽ nhận được nil, một giá trị falsey.

Vì vậy, bạn có thể thay đổi:

if a.length<5đến if !a[4]-5 byte

hoặc là

if a.length>5đến if a[5]-6 byte

hoặc là

if a.length<nđến if !a[n-1]-3 byte

hoặc là

if a.length>nđến if a[n]-6 byte

Lưu ý : sẽ chỉ hoạt động với một mảng của tất cả các giá trị trung thực. có nilhoặc falsetrong mảng có thể gây ra vấn đề.


4
Tôi luôn luôn sử dụng sizenhưng điều này chắc chắn tốt hơn BTW, làm việc cho Stringquá.
manatwork 7/12/2015

10

Đừng sử dụng truefalsetừ khóa.

Sử dụng:

  • !pcho true(cảm ơn, lịch sử!)
  • !0cho false. Nếu tất cả những gì bạn cần là một giá trị giả, thì bạn chỉ cần sử dụng p(trả về nil).

để tiết kiệm một số ký tự.


1
Trừ khi bạn thực sự cần true(nghĩa là nếu một giá trị trung thực là đủ, như trong điều kiện if), bạn thậm chí không cần !!.
Martin Ender

4
Và tương tự, p(đánh giá nil) là một giá trị falsey ngắn hơn. Có nghĩa là cách ngắn nhất để có được true!p.
lịch sử

@histocrat điểm tốt! Tôi đã chỉnh sửa câu trả lời của mình.
Cristian Lupascu


9

Nếu bạn cần để có được một số từ ARGV, gethoặc một cái gì đó tương tự để làm một cái gì đó nhiều lần, thay vì gọi to_ivào nó, bạn có thể chỉ cần sử dụng ?1.upto x{do something x times}trong đó x là một chuỗi.

Vì vậy, sử dụng ?1.upto(a){}thay vì x.to_i.times{}sẽ giúp bạn tiết kiệm 2 ký tự.

Bạn cũng có thể viết lại những thứ như p 1 while 1hoặc p 1 if 1như p 1while 1hoặcp 1if 1

Ví dụ đó không hữu ích lắm, nhưng nó có thể được sử dụng cho những thứ khác.

Ngoài ra, nếu bạn cần gán phần tử đầu tiên của một mảng cho một biến, a,=csẽ lưu hai ký tự trái ngược vớia=c[0]


9

Các tính năng mới trong Ruby 2.3 và 2.4

Thật tốt khi theo kịp các tính năng ngôn ngữ mới sẽ giúp ích cho trò chơi golf của bạn. Có một vài người tuyệt vời trong Rubies mới nhất.

Ruby 2.3

Toán tử điều hướng an toàn: &.

Khi bạn gọi một phương thức có thể trả về nilnhưng bạn muốn xâu chuỗi các cuộc gọi phương thức bổ sung nếu không, bạn sẽ lãng phí byte xử lý niltrường hợp:

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

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

"Toán tử điều hướng an toàn" dừng chuỗi các lệnh gọi phương thức nếu một lệnh trả về nilvà trả về nilcho toàn bộ biểu thức:

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

Array#dig & Hash#dig

Truy cập sâu vào các yếu tố lồng nhau, với một tên ngắn đẹp:

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

Trả về nilnếu nó đi vào ngõ cụt:

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

Enumerable#grep_v

Nghịch đảo ngược lại Enumerable#greptất cả các yếu tố không khớp với đối số đã cho (so với ===). Giống như grep, nếu một khối được đưa ra, kết quả của nó được trả về thay thế.

(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

Trả về một Proc mang lại giá trị cho khóa đã cho, có thể khá tiện dụng:

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]

Ruby 2.4

Ruby 2.4 chưa ra mắt, nhưng nó sẽ sớm ra mắt và có một số tính năng nhỏ tuyệt vời. (Khi nó được phát hành, tôi sẽ cập nhật bài đăng này với một số liên kết đến các tài liệu.) Tôi đã tìm hiểu về hầu hết những điều này trong bài đăng blog tuyệt vời này .

Enumerable#sum

Không còn nữa arr.reduce(:+). Bây giờ bạn có thể làm arr.sum. Nó nhận một đối số giá trị ban đầu tùy chọn, mặc định là 0 cho các phần tử Số ( [].sum == 0). Đối với các loại khác, bạn sẽ cần cung cấp một giá trị ban đầu. Nó cũng chấp nhận một khối sẽ được áp dụng cho từng phần tử trước khi thêm:

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

Integer#digits

Điều này trả về một mảng các chữ số của một số theo thứ tự có ý nghĩa từ nhỏ nhất đến lớn nhất:

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

So với, nói 123.to_s.chars.map(&:to_i).reverse, điều này là khá tốt đẹp.

Là một phần thưởng, nó cần một đối số cơ số tùy chọn:

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

Comparable#clamp

Liệu những gì nó nói trên tin:

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

Vì nó có thể so sánh, bạn có thể sử dụng nó với bất kỳ lớp nào có thể so sánh, ví dụ:

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

String#unpack1

Tiết kiệm 2 byte hơn .unpack(...)[0]:

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

Lập luận chính xác dùng cho Numeric#ceil, floortruncate

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

Nhiều bài tập trong điều kiện

Điều này gây ra lỗi trong các phiên bản trước của Ruby, nhưng được phép trong 2.4.

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

Golf Math::E.ceil(1)để Math::E.ceil 1, và tương tự như vậy cho floortruncate.
Đơn giản là nghệ thuật đẹp

1
@SimplyBeautitableArt Tôi hy vọng rằng ai đó chơi gôn trong Ruby sẽ có thể tự thực hiện bước nhảy vọt đó.
Jordan

Enumerable#sum, .flatten.sumngắn hơn 2 byte so với.sum{|a,b|a+b}
Asone Tuhid

(-Math::E).truncate(1)tương đương với -Math::E.truncate(1)cái đó ngắn hơn 1 byte
Asone Tuhid

1
&.có thể được sử dụng với tính năng đăng ký như thế này a&.[]i(ngắn hơn 1 byte a&.at i). Mặc dù, nếu bắt buộc phải có dấu ngoặc, a||a[i]thì 1 byte ngắn hơn a&.[](i)hoặca&.at(i)
Asone Tuhid

7

Ký hiệu khoa học thường có thể được sử dụng để cạo một hoặc hai char:

x=1000
#versus
x=1e3

9
Lưu ý: Điều này sẽ trả về giá trị Float (1000.0) thay vì Integer, điều này có thể gây ra kết quả không chính xác với số lượng lớn.
Dogbert

4
Ah, tốt đẹp 1e2là tốt hơn so với 100.0khi cần một tỷ lệ phần trăm.
Phrogz

Tương tự như nguyên tắc này, 1.0*là 1 char ngắn hơn.to_f
Unihedron

7

Sử dụng các phương thức toán tử thay vì dấu ngoặc đơn

Hãy nói rằng bạn muốn thể hiện a*(b+c). Bởi vì ưu tiên, a*b+csẽ không làm việc (rõ ràng). Cách tuyệt vời của Ruby là có các nhà khai thác khi các phương pháp giải cứu! Bạn có thể sử dụng a.*b+cđể làm cho mức độ ưu tiên *thấp hơn mức đó +.

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

Điều này cũng có thể làm việc với các toán tử !~toán tử (những thứ như unary +hoặc unary -không hoạt động vì các phương thức của chúng là -@+@, tiết kiệm ()nhưng thêm vào .@)

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

6

Sử dụng ||thay thế or&&thay vào đó and.

Bên cạnh một ký tự từ andbạn có thể lưu các khoảng trắng (và có lẽ là dấu ngoặc) xung quanh toán tử.

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

Nếu bạn lặp trên một mảng bạn thường sử dụng each. Nhưng mapcác vòng lặp cũng trên một mảng và nó ngắn hơn một ký tự.


6

Tôi vừa thử một thử thách golf mã TDD tức là Viết mã ngắn nhất để vượt qua thông số kỹ thuật. Thông số kỹ thuật giống như

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

Vì lợi ích của môn đánh gôn, người ta không cần phải tạo mô-đun hoặc lớp.

Thay vì

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

người ta có thể làm

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

Lưu 13 ký tự!


7
Hà, rất kỹ lưỡng. Không chỉ bạn thêm các hành vi cần thiết để PigLatin, mà còn để @pig_latin, $pig_latin'pig'['latin'].
lịch sử

@histocrat: Bây giờ tôi hiểu rồi. Đó là bởi vì translateđã được xác định trên nil.
Eric Duminil

6

Kernel # p là một phương thức thú vị.

Sử dụng p varthay vì puts var. Điều này hoạt động hoàn hảo với số nguyên và số float, nhưng không phải với tất cả các loại. Nó in dấu ngoặc kép quanh chuỗi, có lẽ không phải là điều bạn muốn.

Được sử dụng với một đối số duy nhất, ptrả về đối số sau khi in.

Được sử dụng với nhiều đối số, ptrả về các đối số trong một mảng.

Sử dụng p(không có đối số) thay vì nil.


10
Thật không may, p 'some string'bản in "some string"và không chỉ some stringthường bị người khác chỉ trích.
Patrick Oscarity

1
Về cơ bản p slà giống như puts s.inspect, nhưng nó trở lạis
Cyoce

6

Đừng sử dụng #each. Bạn có thể lặp qua tất cả các yếu tố tốt với #map. Vì vậy, thay vì

ARGV.each{|x|puts x}

bạn có thể làm tương tự với ít byte hơn.

ARGV.map{|x|puts x}

Tất nhiên, trong trường hợp này puts $*sẽ còn ngắn hơn.


Có những chữ cho số hữu tỷ và số phức:

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

=> true
true
true

Bạn có thể sử dụng hầu hết các byte trong chuỗi. "\x01"(6 byte) có thể được rút ngắn thành ""(3 byte). Nếu bạn chỉ cần một byte này, điều này có thể rút ngắn hơn nữa thành ?(2 byte).

Với cùng một mã thông báo, bạn có thể nhận được các dòng mới ngắn hơn như thế này:

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

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

Bạn có thể sử dụng ?\n?\tcũng vậy, ngắn hơn một byte so với "\n""\t". Đối với obfuscation, cũng có? \ S, một không gian.


Sử dụng hằng số thay vì chuyển các đối số xung quanh, ngay cả khi bạn cần thay đổi chúng. Thông dịch viên sẽ đưa ra cảnh báo cho stderr , nhưng ai quan tâm. Nếu bạn cần xác định thêm các biến liên quan đến nhau, bạn có thể xâu chuỗi chúng như thế này:

A=C+B=7+C=9

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

Cái này ngắn hơn C=9;B=16;A=17hay C=0;B=C+7;A=C+B.


Nếu bạn cần một vòng lặp vô hạn, sử dụng loop{...}. Các vòng có độ dài không xác định có thể ngắn hơn với các vòng khác:

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

while'
'!=f(gets);end

Một số thủ thuật gsub / regrec thêm. Sử dụng các '\1'ký tự thoát đặc biệt thay vì một khối:

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

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

Và các biến đặc biệt, $1vv nếu bạn cần thực hiện các hoạt động. Hãy nhớ rằng chúng được xác định không chỉ trong khối:

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

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

Loại bỏ khoảng trắng, dòng mới và dấu ngoặc đơn. Bạn có thể bỏ qua khá nhiều trong ruby. Nếu nghi ngờ, hãy luôn thử nếu nó hoạt động mà không có, và hãy nhớ rằng điều này có thể phá vỡ một số cú pháp chỉnh sửa tô sáng ...

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

"Xin vui lòng gửi một lời khuyên cho mỗi câu trả lời." Cũng ?\ntốt, nhưng không thực sự ngắn hơn so với thực sự đặt một ký tự dòng mới trong dấu ngoặc kép. (tương tự cho tab)
Martin Ender

puts$*thậm chí còn ngắn hơn.
Cyoce

Tôi biết bạn đã cố gắng chứng minh một điểm nhưng tôi khá chắc chắn rằng ví dụ cuối cùng giống nhưx+=1;$*<<A
Asone Tuhid

6

Tuy nhiên, một cách khác để sử dụng toán tử splat: nếu bạn muốn gán một mảng bằng chữ duy nhất, *thì ở phía bên trái ngắn hơn dấu ngoặc ở phía bên phải:

a=[0]
*a=0

Với nhiều giá trị, bạn thậm chí không cần toán tử splat (cảm ơn histocrat đã sửa lỗi cho tôi về điều đó):

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

Trường hợp thứ hai không thực sự cần splat.
lịch sử

@histocrat Oh wow, tôi nghĩ giá trị thứ hai sẽ bị loại bỏ trong trường hợp đó.
Martin Ender

1
Tôi không thể tin rằng tôi đã không biết những điều này trong suốt thời gian tôi chơi golf ở Ruby.
Doorknob

6

Khi một thách thức yêu cầu bạn xuất ra nhiều dòng, bạn không phải lặp qua các kết quả của mình để in từng dòng, ví dụ như một mảng. Các putsphương pháp sẽ san bằng một mảng và in mỗi phần tử trên một dòng riêng biệt.

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

Kết hợp toán tử splat với #pbạn có thể làm cho nó thậm chí ngắn hơn:

p *a

Toán tử splat (về mặt kỹ thuật *@, tôi nghĩ vậy) cũng đưa các liệt kê không phải là mảng của bạn vào mảng:

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

đấu với

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

1
*@không phải là một phương pháp, splat là cú pháp đường
Asone Tuhid

6

Lưu một số byte khi loại bỏ các phần tử lặp lại của một mảng

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

Nếu bạn sẽ sử dụng một mảng trống []trong một biến, bạn có thể lưu nhiều byte hơn:

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

2
Đối với trường hợp đầu tiên, a&angắn hơn 1 byte
Asone Tuhid

5

Sử dụng Goruby thay vì Ruby, giống như phiên bản rút gọn của Ruby. Bạn có thể cài đặt nó với rvm thông qua

rvm install goruby

Goruby cho phép bạn viết hầu hết mã của mình như bạn đang viết Ruby, nhưng có thêm chữ viết tắt. Để tìm ra từ viết tắt ngắn nhất có sẵn cho một cái gì đó, bạn có thể sử dụng phương thức trợ giúp shortest_abbreviation, ví dụ:

shortest_abbreviation :puts
#=> "pts"

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

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

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

Cũng rất tiện dụng là bí danh saycho putsmà tự nó có thể được viết tắt với s. Vì vậy, thay vì

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

bây giờ bạn có thể viết

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

để in bảng chữ cái trong thủ đô (đó không phải là ví dụ tốt). Bài đăng trên blog này giải thích nhiều thứ hơn và một số hoạt động bên trong nếu bạn muốn đọc thêm.

PS: đừng bỏ lỡ hphương pháp ;-)


Hơn 2 năm sau và cuối cùng tôi cũng đã tìm ra câu trả lời này khiến tôi nhớ đến ...
ngầmmonailail

5

Để tham gia một mảng, thay vì điều này

[...].join

làm cái này

[...]*''

giúp tiết kiệm 2 byte. Để tham gia với một phân cách sử dụng

[...]*?,

5

Số đăng ký!

Tôi mới phát hiện ra điều này ngày hôm qua. n[i]trả về nbit của ivị trí thứ -th. Thí dụ:

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

Và bây giờ bạn có thể sử dụng nhiều đối số hơn, chẳng hạn nhưn[0..3]
Nghệ thuật đơn giản đẹp

4

Bạn có thể lưu 2 ký tự và sử dụng

[*(...)]

thay vì

(...).to_a

Ví dụ: giả sử chúng ta có một phạm vi mà chúng ta muốn dưới dạng một mảng:

(1..2000).to_a

Chỉ cần làm như thế này:

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

Và bây giờ bạn có phạm vi của bạn như là một mảng.


5
Tôi nghĩ rằng [*1..2000]công việc, quá?
Lynn

4

<< lừa

a.push x

có thể rút ngắn thành:

a<<x

cho -4 byte.


2
Lưu ý: điều này cũng hoạt động cho Strings
Cyoce

4

Array#assoc/rassoc

Khi bạn có một mảng các mảng và muốn tìm mảng con bắt đầu bằng một giá trị cụ thể, đừng sử dụng Enumerable#find, hãy sử dụng Array#assoc:

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

Đây cũng là một sự thay thế tốt cho Enumerable#any?một số tình huống.

Array#rassoc thực hiện điều tương tự, nhưng kiểm tra phần tử cuối cùng của mảng phụ:

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

Đối với a.any?dòng trong rassoc ví dụ, |x,|làm gì? Nó khác với |x|như thế nào?
Cyoce

@Cyoce Khối tham số destructuring theo quy tắc tương tự như destructuring chuyển nhượng, do đó, nó giống như x=[1,2]vs x,=[1,2]. Sử dụng ví dụ của tôi ở trên, với |x|, trong lần lặp đầu tiên xsẽ là [0,"foo"]. Với |x,y|, xsẽ 0ysẽ "foo". Tương tự như vậy, với |x,|, xsẽ được 0. Nói cách khác, nó nói "đặt phần tử đầu tiên vào xvà ném phần còn lại đi.
Jordan

Lưu ý rằng nó không hoạt động ngược lại, ví dụ như |,y|SyntaxError, ergo |_,y|. Nhưng tôi vừa mới nhận ra rằng nó |*,y|hoạt động, sạch hơn so với sử dụng một biến có tên _(nhưng không ngắn hơn).
Jordan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.