Какие общие советы вы можете дать для игры в гольф в Ruby?
Я ищу идеи, которые могут быть применены к задачам по коду для гольфа в целом, которые характерны для Ruby. (Например, «Удалить комментарии» не будет ответом.)
Пожалуйста, оставьте один совет за ответ.
Ответы:
?d
до?~
1.8.$><<"string"
она корочеprint"string"
.$<.map{|l|...}
корочеwhile l=gets;...;end
. Также вы можете использовать,$<.read
чтобы прочитать все это сразу.$<
иgets
будете читать из файла вместо стандартного ввода, если имя файла вARGV
. Таким образом, golfiest способ переописатьcat
будет:$><<$<.read
.источник
cat
- оставить файл ruby полностью пустым (0 байт) и настаивать на том, чтобы его запускали из командной строки с-p
флагом.puts *$<
☺
или♫
, или если вы достаточно сумасшедший:?﷽.ord=65021
Используйте оператор splat, чтобы получить хвост и голову массива:
Это также работает по-другому:
Используйте
*
метод со строкой в массиве для объединения элементов:источник
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
для определения функций. Сделайте лямбду с оператором new -> в Ruby 1.9. (Оператор -> является «стабильной лямбда» или «тире ракета» .) Это сохраняет 5 символов для каждой функции.Вызов метода
c n
илиc(n)
. Лямбда звонки естьc[n]
. Сменяя другc n
наc[n]
затраты 1 символ, так что если вы можете использоватьc n
более чем в 5 раз, а затем сохранить этот метод.Все методы, которые принимают
do...end
блоки, могут{...}
вместо этого принимать блоки. Это сохраняет от 3 до 5 символов. Если приоритет{...}
слишком велик, используйте скобки, чтобы исправить это.Заменить
if...else...end
на троичный оператор?:
. Если в ветке есть два или более операторов, заключите их в скобки.Вероятно, у вас нет
while
илиuntil
циклов, но если у вас есть, то напишите их в форме модификатора.источник
puts'statement 3'
?Дополнение к w0lf
В сочетании с выше -> вы можете сделать его еще короче,
-[p]
чтобы сохранить еще 2 символа.источник
По возможности используйте короткие предопределенные переменные, например,
$*
вместоARGV
. Там хороший список из них здесь , наряду с большим количеством другой полезной информации.источник
Когда вы используете интерполяцию строк (как следует из публикации Мартина Бюттнера ), вам не нужны фигурные скобки, если перед вашим объектом стоит символ (
$
,@
). Полезно для магических переменных, таких как$_
,$&
и$1
т.д:Также, если вам нужно вывести переменную больше, чем вы ее используете, вы можете сохранить несколько байтов.
источник
Если вам нужно найти, находится ли определенный элемент
e
внутри диапазонаr
, вы можете использоватьвместо более длинного:
или же
или же
источник
r===e
Даже не короче?===
реализовано.$_
последняя прочитанная строка.print
- если аргумент не указан, выведите содержимое$_
~/regexp/
- Короче для$_=~/regexp/
В Ruby 1.8 у вас есть четыре метода,
Kernel
которые работают с$_
:chop
chomp
sub
gsub
В Ruby 1.9 эти четыре метода существуют, только если ваш скрипт использует
-n
или-p
.Если вы хотите печатать некоторую переменную часто, используйте
trace_var(:var_name){|a|p a}
источник
-p
или-n
. Ссылка.trace_var
работает только с глобальными переменными $Используйте строковую интерполяцию!
Заменить
to_s
. Если вам нужны круглые скобки вокруг того, что вы хотите превратить в строку,to_s
это на два байта больше, чем интерполяция строки:Заменить конкатенацию. Если вы объединяете что-то, окруженное двумя другими строками, интерполяция может сэкономить вам один байт:
Также работает, если промежуточное звено само объединено, если вы просто перемещаете объединение внутри интерполяции (вместо использования нескольких интерполяций):
источник
Избегайте
length
вif a.length<n
length
6 байт, немного дороже в коде гольф. во многих ситуациях вы можете вместо этого проверить, есть ли в массиве что-либо в данной точке. если выnil
пропустите последний индекс, который вы получите , значение Falsey.Так что вы можете изменить:
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
... Но это определенно лучше. Кстати, работаетString
тоже.Не используйте
true
иfalse
ключевые слова.Использование:
!p
заtrue
(спасибо, гистократ!)!0
дляfalse
. Если все, что вам нужно, это ложное значение, то вы можете просто использоватьp
(что возвращаетnil
).чтобы сохранить некоторые символы.
источник
true
(то есть, если истинного значения достаточно, как в условии if), вам даже не нужно!!
.p
(который оцениваетnil
) является более коротким значением Лжи. Это означает самый короткий путь , чтобы получитьtrue
это!p
.Создайте массивы, используя их,
a=i,*a
чтобы получить их в обратном порядке. Вам даже не нужно инициализироватьa
, и если вы делаете это, это не обязательно должен быть массив .источник
Если вы когда - нибудь понадобится , чтобы получить число от
ARGV
,get
или что - то подобное сделать что - то , что много раз, вместо вызоваto_i
на него, вы можете просто использовать ,?1.upto x{do something x times}
где х представляет собой строку.Таким образом, использование
?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]
источник
Новые функции в Ruby 2.3 и 2.4
Хорошо быть в курсе новых языковых функций, которые помогут вашей игре в гольф. В последних рубинах есть несколько замечательных.
Ruby 2.3
Оператор безопасной навигации:
&.
Когда вы вызываете метод, который может возвращать,
nil
но вы хотите связать дополнительные вызовы метода, если это не так, вы тратите впустую байты, обрабатываяnil
случай:«Оператор безопасной навигации» останавливает цепочку вызовов методов, если возвращается
nil
и возвращаетсяnil
для всего выражения:Array#dig
&Hash#dig
Глубокий доступ к вложенным элементам с красивым коротким именем:
Возвращает,
nil
если попадает в тупик:Enumerable#grep_v
Обратный
Enumerable#grep
-returns всех элементов , которые не соответствуют данному аргументу ( по сравнению с===
). Напримерgrep
, если дан блок, вместо него возвращается результат.Hash#to_proc
Возвращает Proc, который возвращает значение для данного ключа, что может быть очень удобно:
Ruby 2.4
Ruby 2.4 еще не выпущен, но он скоро появится и имеет несколько замечательных небольших функций. (Когда он выйдет, я дополню этот пост некоторыми ссылками на документы.) О большинстве из них я узнал из этого замечательного поста в блоге .
Enumerable#sum
Нет больше
arr.reduce(:+)
. Теперь вы можете просто сделатьarr.sum
. Он принимает необязательный аргумент начального значения, который по умолчанию равен 0 для числовых элементов ([].sum == 0
). Для других типов вам необходимо указать начальное значение. Он также принимает блок, который будет применен к каждому элементу перед добавлением:Integer#digits
Это возвращает массив цифр числа в порядке наименьшей значимости:
По сравнению, скажем
123.to_s.chars.map(&:to_i).reverse
, это довольно мило.В качестве бонуса он принимает необязательный аргумент radix:
Comparable#clamp
Делает то, что говорит на банке:
Поскольку он находится в Comparable, вы можете использовать его с любым классом, который включает Comparable, например:
String#unpack1
2-байтовая экономия более
.unpack(...)[0]
:Точность аргумент
Numeric#ceil
,floor
иtruncate
Многократное присваивание в условных выражениях
Это вызывает ошибку в более ранних версиях Ruby, но допускается в 2.4.
источник
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)
Научная запись часто может использоваться, чтобы сбрить полукокса или два:
источник
1e2
лучше, чем100.0
когда нужен процент.1.0*
на 1 символ короче.to_f
Используйте операторные методы вместо скобок
Допустим, вы хотите выразить
a*(b+c)
. Из-за приоритетаa*b+c
не сработает (очевидно). Крутой способ Руби иметь операторов как методы приходит на помощь! Вы можете использовать,a.*b+c
чтобы сделать приоритет*
ниже, чем у+
.Это может также работать с
!
и~
операторами ( такими вещами , как унарные+
или унарный-
не работает , потому что их методы-@
и+@
, экономя ,()
но добавление.@
)источник
Используйте
||
вместоor
и&&
вместоand
.Помимо одного символа
and
вы можете сохранить пробелы (и, возможно, скобки) вокруг оператора.Если вы зациклились на массиве, который вы обычно используете
each
. Ноmap
зацикливается также на массив, и он на один символ короче.источник
Я только что попытался выполнить тест TDD для игры в гольф, то есть написать кратчайший код для прохождения спецификаций. Спецификации были что-то вроде
Ради код-гольфа не нужно создавать модуль или класс.
Вместо
можно сделать
Спасает 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. Так что вместо
Вы можете сделать то же самое в меньшем количестве байтов.
Конечно, в этом случае
puts $*
будет еще короче.Существуют литералы для рациональных и комплексных чисел:
Вы можете использовать большинство байтов в строках.
"\x01"
(6 байтов) можно сократить до""
(3 байта). Если вам нужен только этот один байт, его можно сократить еще больше до?
(2 байта).Точно так же вы можете сократить перевод строки следующим образом:
Вы можете использовать
?\n
и?\t
также, который на один байт короче, чем"\n"
и"\t"
. Для запутывания, есть также? \ S, пробел.Используйте константы вместо передачи аргументов, даже если вам нужно их изменить. Переводчик будет предупреждать stderr , но кого это волнует. Если вам нужно определить больше переменных, связанных друг с другом, вы можете связать их в цепочку следующим образом:
Это короче
C=9;B=16;A=17
илиC=0;B=C+7;A=C+B
.Если вам нужен бесконечный цикл, используйте
loop{...}
. Петли неизвестной длины могут быть короче с другими петлями:Еще несколько трюков с gsub / regexp. Используйте специальные
'\1'
escape-символы вместо блока:И специальные переменные
$1
и т. Д., Если вам нужно выполнить операции. Имейте в виду, что они определены не только внутри блока:Избавьтесь от пробелов, переносов и скобок. Вы можете опустить немного в рубине. Если вы сомневаетесь, всегда пробуйте, если он работает без, и имейте в виду, что это может нарушить подсветку синтаксиса редактора ...
источник
?\n
это хорошо, но на самом деле не короче, чем ввод символа новой строки внутри кавычек. (то же самое для вкладки)puts$*
еще короче.x+=1;$*<<A
Еще один способ использования оператора splat: если вы хотите назначить один литерал массива,
*
то левая часть короче скобок с правой стороны:С несколькими значениями вам даже не нужен оператор splat (спасибо гистократу за поправку):
источник
Когда задача требует, чтобы вы вывели несколько строк, вам не нужно циклически просматривать результаты, чтобы напечатать каждую строку, например, массива.
puts
Метод будет выравниваться массив и распечатать каждый элемент в отдельной строке.Комбинируя оператор splat с
#p
вами, вы можете сделать его еще короче:Оператор splat (технически
*@
метод, я думаю) также преобразует ваши перечисляемые не-массивы в массивы:против
источник
*@
это не метод, сплат - это синтаксический сахарСохраните несколько байтов при удалении повторяющихся элементов массива
Если вы будете использовать пустой массив
[]
в переменной, вы можете сохранить еще больше байтов:источник
a&a
1 байт корочеИспользуйте Goruby вместо Ruby, что-то вроде сокращенной версии Ruby. Вы можете установить его с помощью RVM через
Goruby позволяет вам писать большую часть кода, как если бы вы писали на Ruby, но имеет встроенные дополнительные сокращения. Чтобы найти кратчайшие доступные сокращения для чего-либо, вы можете использовать вспомогательный метод
shortest_abbreviation
, например:Также очень удобен псевдоним,
say
дляputs
которого можно сокращенно обозначить егоs
. Так что вместотеперь вы можете написать
печатать алфавит прописными буквами (что не очень хороший пример). Этот пост в блоге объясняет больше вещей и некоторые внутренние детали, если вы заинтересованы в дальнейшем чтении.
PS: не пропустите
h
метод ;-)источник
Чтобы присоединиться к массиву, вместо этого
сделай это
который экономит 2 байта. Для объединения с разделителем используйте
источник
Номера для подписки!
Я только что обнаружил это вчера.
n[i]
возвращаетn
бит вi
-ой позиции. Пример:источник
n[0..3]
Вы можете сохранить 2 символа и использовать
вместо
Например, предположим, что у нас есть диапазон, который мы хотим использовать в качестве массива:
Просто сделайте это так:
И теперь у вас есть свой диапазон в виде массива.
источник
[*1..2000]
тоже работает?<< трюк
можно сократить до:
для -4 байта.
источник
String
sArray#assoc
/rassoc
Если у вас есть массив массивов и вы хотите найти подмассив, который начинается с определенного значения, не используйте
Enumerable#find
, используйтеArray#assoc
:Это также хорошая замена
Enumerable#any?
в некоторых ситуациях.Array#rassoc
делает то же самое, но проверяет последний элемент подмассива:источник
a.any?
строки вrassoc
примере, что делает|x,|
? Чем он отличается от|x|
?x=[1,2]
противx,=[1,2]
. Используя мой пример выше, с|x|
, в первой итерацииx
будет[0,"foo"]
. С|x,y|
,x
будет0
иy
будет"foo"
. Точно так же, с|x,|
,x
будет0
. Другими словами, он говорит , что «поставил первый элементx
и бросить все остальное прочь.|,y|
, это SyntaxError, ergo|_,y|
. Но я только сейчас понял, что|*,y|
работает, что чище, чем использование переменной с именем_
(но не короче).