답변:
?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
다음exit
gets
사용할 수 있습니다 ~/$/
(마지막 줄 바꿈이있는 경우 계산하지 않습니다)[]
문자열에 다른 문자열이 포함되어 있는지 확인하는 데 사용하십시오 .'foo'['f'] #=> 'f'
tr
대신 사용하십시오 gsub
.'01011'.tr('01','AB') #=> 'ABABB'
chop
대신chomp
abort
과~/$/
~/$/
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
이 있습니다 $_
.
chop
chomp
sub
gsub
루비 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<n
length
코드 골프에서 약간 비싼 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 1
as 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#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
.
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|
작동하는 것을 깨달았습니다 _
.