답변:
?d에 ?~1.8.$><<"string"보다 짧습니다 print"string".$<.map{|l|...}보다 짧습니다 while l=gets;...;end. 또한 $<.read한 번에 읽을 수 있습니다 .$<그리고 gets파일 이름이있는 경우 파일 대신에 표준 입력에서 읽습니다 ARGV. 다시 구현하는 가장 골치 아픈 방법 cat은 다음과 같습니다 $><<$<.read.cat은 루비 파일을 완전히 비워두고 (0 바이트) -p플래그 와 함께 명령 행에서 실행해야한다고 주장하는 것 입니다.
puts *$<
☺또는 같은 생각을 사용 하거나 ♫충분히 미친 경우 126 이상을 갈 수 있습니다 :?﷽.ord=65021
abort프로그램을 종료하고 STDERR에 문자열을 인쇄 -보다 짧은 puts다음exitgets사용할 수 있습니다 ~/$/(마지막 줄 바꿈이있는 경우 계산하지 않습니다)[]문자열에 다른 문자열이 포함되어 있는지 확인하는 데 사용하십시오 .'foo'['f'] #=> 'f'tr대신 사용하십시오 gsub.'01011'.tr('01','AB') #=> 'ABABB'chop대신chompabort과~/$/
~/$/
gets는 호출 할 때마다 결과가 $_변수에 저장됩니다 . /regex/ ~= string첫 번째 일치 색인을 반환합니다. ~정규식을 호출 하는 것은와 같습니다 /regex/ ~= $_. 그래서 같은 것s=gets;l= ~/$/
end.end코드에서 제거 하십시오.
def...end함수를 정의 하는 데 사용하지 마십시오 . Ruby 1.9에서 new-> 연산자로 람다를 만드십시오. (-> 연산자는 "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)입니다. Lambda 통화는 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와 삼항 연산자 ?: . 지점에 둘 이상의 문이 있으면 괄호로 묶습니다.
# 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'필요합니까?
문자열 보간을 사용할 때 ( Martin Büttner의 게시물을 홍보해야 함 ) 객체 에 앞에 sigil ( $, @) 이 있으면 중괄호가 필요하지 않습니다 . 같은 마법의 변수에 유용 $_, $&, $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"
특정 요소가있는 경우 발견해야하는 경우 e범위 안에 r, 당신은 사용할 수 있습니다
r===e
더 이상 대신 :
r.cover?(e) # only works if `r.exclude_end?` is false
또는
r.member?(e)
또는
r.include?(e)
r===e도 짧아?
===구현되었습니다.
$_ 마지막 읽기 행입니다.
print -인쇄 내용이 주어진 인수가없는 경우 $_~/regexp/ -짧다 $_=~/regexp/Ruby 1.8에는 다음과 같은 네 가지 방법 Kernel이 있습니다 $_.
chopchompsubgsub루비 1.9, 이러한 네 가지 방법은 스크립트를 사용하는 경우에만 존재 -n나 -p.
변수를 자주 인쇄하려면 다음을 사용하십시오. trace_var(:var_name){|a|p a}
trace_var글로벌 $ 변수에서만 작동하는 것 같습니다
문자열 보간을 사용하십시오!
교체 to_s합니다. 문자열로 바꾸고 싶은 괄호가 필요한 to_s경우 문자열 보간보다 2 바이트가 더 깁니다.
(n+10**i).to_s
"#{n+10**i}"
연결을 교체합니다. 두 개의 다른 문자열로 둘러싸인 것을 연결하면 보간으로 1 바이트를 절약 할 수 있습니다.
"foo"+c+"bar"
"foo#{c}bar"
중간 보간 물 자체가 연결된 경우에도 보간 내에서 연결을 이동하면 (여러 보간을 사용하는 대신) 작동합니다.
"foo"+c+d+e+"bar"
"foo#{c+d+e}bar"
length에if a.length<nlength코드 골프에서 약간 비싼 6 바이트입니다. 많은 상황에서, 대신 주어진 지점에 배열이 있는지 확인할 수 있습니다. 마지막 색인을 nil지나면 false 값을 얻습니다 .
따라서 다음을 변경할 수 있습니다.
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어레이 내에 문제가 발생할 수있다.
size하지만… BTW도 작동합니다 String.
true및 false키워드를 사용하지 마십시오 .
사용하다:
!p대한 true(감사, histocrat!)!0에 대한 false. 필요한 값이 잘못된 값이면 간단히 p(을 반환 nil)을 사용할 수 있습니다 .일부 문자를 저장합니다.
true경우가 아니라면 (예 : if 조건에서와 같이 진실한 값으로 충분하다면)조차 필요하지 않습니다 !!.
p(로 평가되는 nil)는 더 짧은 잘못된 값입니다. 가장 짧은 방법 true은 !p입니다.
당신이 이제까지의 숫자를 얻기 위해 필요한 경우 ARGV, get또는 이와 유사한 일이 여러 번 대신 호출하는 것을 수행하는 to_i그것을, 당신은 그냥 사용할 수 ?1.upto x{do something x times}x는 문자열이 어디를.
그래서 사용하는 ?1.upto(a){}대신에 x.to_i.times{}당신이 개 문자를 저장합니다.
p 1 while 1또는 p 1 if 1as p 1while 1또는 as 와 같은 것을 다시 작성할 수도 있습니다.p 1if 1
이 예제는 그다지 유용하지는 않지만 다른 용도로 사용될 수 있습니다.
또한 배열의 첫 번째 요소를 변수에 할당 해야하는 경우 a,=c와 달리 두 문자를 저장합니다a=c[0]
골프 게임에 도움이되는 새로운 언어 기능을 숙지하는 것이 좋습니다. 최신 루비에는 몇 가지 위대한 것들이 있습니다.
&.반환 할 수있는 메소드를 호출 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는 아직 나오지 않았지만 곧 출시 될 예정입니다. (릴리스가 공개되면이 게시물을 문서에 대한 링크로 업데이트하겠습니다.) 이 훌륭한 블로그 게시물 에서 이들에 대해 대부분 배웠 습니다 .
Enumerable#sum더 이상 없습니다 arr.reduce(:+). 당신은 지금 할 수 있습니다 arr.sum. 선택적 초기 값 인수를 사용하며 숫자 요소 ( [].sum == 0)의 기본값은 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이것은 꽤 좋습니다.
보너스로 기수 인수를 선택적으로받습니다 :
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#unpack12 바이트 이상 절감 .unpack(...)[0]:
"👻💩".unpack(?U) # => [128123]
"👻💩".unpack(?U)[0] # => 128123
"👻💩".unpack1(?U) # => 128123
Numeric#ceil, floor및truncateMath::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.
Enumerable#sum, .flatten.sum보다 2 바이트 짧은.sum{|a,b|a+b}
(-Math::E).truncate(1)동등로 -Math::E.truncate(1)하는 1 바이트 짧다
&.이와 같이 아래 첨자와 함께 사용할 수 있습니다 a&.[]i(보다 1 바이트 더 짧은 a&.at i). 대괄호가 필요한 경우 a||a[i]1 바이트가 짧 a&.[](i)거나a&.at(i)
표현하고 싶다고합시다 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!
사용 ||대신 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배열도 반복하며 한 문자가 짧습니다.
방금 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
코드 골프를 위해 모듈이나 클래스를 만들 필요는 없습니다.
대신에
module PigLatin def self.translate s;'some code'end;end
하나는 할 수있다
def(PigLatin=p).translate s;'some code'end
13자를 저장합니다!
PigLatin아니라에 @pig_latin, $pig_latin하고 'pig'['latin'].
translate에 정의되어 있기 때문 입니다 nil.
커널 #p 는 재미있는 방법입니다.
p var대신에 사용하십시오 puts var. 이것은 정수 및 부동 소수점과 완벽하게 작동하지만 모든 유형에서는 작동하지 않습니다. 문자열 주위에 따옴표를 인쇄합니다. 원하는 것은 아닐 것입니다.
단일 인수와 함께 사용하면 p인쇄 후 인수를 반환합니다.
여러 인수와 함께 사용 p하면 배열의 인수를 반환합니다.
p대신 (인수없이)를 사용하십시오 nil.
p 'some string'인쇄 합니다. "some string"some string
p s와 동일 puts s.inspect하지만 반환s
#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 바이트) 로 단축 될 수 있습니다 . 이 1 바이트 만 필요한 경우 ?(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=17또는 보다 짧습니다 C=0;B=C+7;A=C+B.
무한 루프가 필요한 경우을 사용하십시오 loop{...}. 길이가 알려지지 않은 루프는 다른 루프보다 짧을 수 있습니다.
loop{break if'
'==f(gets)}
while'
'!=f(gets);end
좀 더 gsub / regexp 트릭. '\1'블록 대신 특수 이스케이프 문자를 사용하십시오 .
"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멋지지만 실제로 따옴표 안에 개행 문자를 넣는 것보다 짧지는 않습니다. (탭과 동일)
puts$*더 짧습니다.
x+=1;$*<<A
splat 연산자를 사용하는 또 다른 방법 : 단일 배열 리터럴을 지정 *하려면 왼쪽의 a 가 오른쪽의 대괄호보다 짧습니다.
a=[0]
*a=0
여러 값을 사용하면 splat 연산자가 필요하지 않습니다 (그것을 수정 해 준 histocrat 덕분에).
a=[1,2]
a=1,2
챌린지에 여러 줄을 출력해야하는 경우 배열의 각 줄을 인쇄하기 위해 결과 를 반복 하지 않아도됩니다 . 이 puts방법은 배열을 평평하게하고 각 요소를 별도의 줄에 인쇄합니다.
> a = %w(testing one two three)
> puts a
testing
one
two
three
splat 연산자를 결합하면 #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
*@방법은 아닙니다, 표시는 구문 설탕입니다
a.uniq # before
a|[] # after
^^
[]변수에 빈 배열 을 사용하는 경우 더 많은 바이트를 절약 할 수 있습니다.
a.uniq;b=[] # before
a|b=[] # after
^^^^^
a&a는 1 바이트 더 짧습니다
축약 된 Ruby 버전과 비슷한 Ruby 대신 Goruby를 사용하십시오. 다음을 통해 rvm으로 설치할 수 있습니다
rvm install goruby
Goruby를 사용하면 Ruby를 작성할 때와 같이 대부분의 코드를 작성할 수 있지만 추가 약어가 내장되어 있습니다. 가능한 가장 짧은 약어를 찾으려면 helper 메소드를 사용할 수 있습니다. 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
대문자로 알파벳을 인쇄하려면 (아주 좋은 예는 아닙니다). 이 블로그 게시물은 더 많은 내용을 읽고 싶다면 더 많은 내용과 일부 내부 작업을 설명합니다.
추신 : h방법을 놓치지 마십시오 ;-)
나는 방금 어제 이것을 발견했다. n[i]- 번째 위치 n에서의 비트를 반환합니다 i. 예:
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]
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|가요?
x=[1,2]vs 와 같습니다 x,=[1,2]. 와, 내 위의 예제를 사용하여 |x|첫 번째 반복에서하면 x될 것입니다 [0,"foo"]. 으로 |x,y|, x될 것입니다 0및 y있을 것입니다 "foo". 이와 함께 |x,|, x될 것입니다 0. 다시 말해, "첫 번째 요소를 넣고 x나머지는 버립니다."
|,y|SyntaxError, ergo 와 같이 반대로 작동하지 않습니다 |_,y|. 그러나 나는 방금 |*,y|작동하는 것을 깨달았습니다 _.