Советы по игре в гольф в Рёде


12

Röda - это язык сценариев на основе потоков, созданный fergusq .

Какие общие советы у вас есть для игры в гольф в Рёде? Я ищу идеи, которые могут быть применены к задачам кода-гольфа и которые, по крайней мере, несколько специфичны для Röda (например, «удалить комментарии» - это не ответ).

Пожалуйста, оставьте один совет за ответ.


Вы пытаетесь получить советы, чтобы победить меня в гольфе? : P (мне, вероятно, следует взглянуть на советы для страницы Python)
HyperNeutrino

Ух ты, вопрос от PCG.SE, который попал в Hot Network Questions и не является головоломкой / проблемой программирования! :)
Педро А

1
@HyperNeutrino Shhh .... :)
user41805

Ответы:


7

Используйте подчеркивание

Это, наверное, самый важный совет. Почти в каждой программе Röda для игры в гольф используются подчеркивания.

Синтаксис подчеркивания является синтаксическим сахаром для forциклов. Следующие строки кода эквивалентны:

ls""|fileLength x for x|sort|pull
ls""|fileLength _|sort|pull

Каждое подчеркивание добавляет новую переменную в невидимый forцикл вокруг оператора. Цикл извлекает одно значение из потока для каждой переменной / подчеркивания, а затем повторяется, пока не останется никаких значений.

Подчеркивания могут быть использованы где угодно в выражениях:

a[x:y+1]=[1]*(1+y-x) /* Sets range x..y (inclusive) */
seq x,y|a[_]=1       /* 6 bytes less */

Если вы должны ссылаться на одно и то же значение подчеркивания более одного раза или использовать значения в обратном порядке, вы можете поставить число после подчеркивания:

a|[_^_1]  /* maps x to x^x */
a|[_2-_1] /* maps each pair (x,y) to y-x, eg. [1,2,4,8] -> [1, 4] */

3

Некоторые точки с запятой / новые строки являются необязательными

При написании кода Röda обычно рекомендуется использовать новые строки или точки с запятой для разделения всех операторов. Однако при игре в гольф стоит знать, что не все точки с запятой действительно необходимы.

Вот неполный список мест, где точки с запятой / новые строки являются необязательными . Большинство из них не применяется , когда следующий оператор начинается с оператором ( (, [, +и т.д.).

  • После назначения
  • После вызова функции, когда есть хотя бы один аргумент (например, f x) или когда используются скобки (например, f())
  • Везде, если следующая строка / заявление будет начинаться с |, ), ]или}

Если следующий оператор начинается с оператора, точка с запятой / новая строка необязательна, если

  • Оператор является вызовом функции и используются скобки, например, {f(x)[y]}такой же, как {f(x);[y]}. Это работает только в контексте оператора, а не когда вызов функции является выражением.
  • Оператор является присваиванием и используются круглые скобки, например x=(y)[z], такие же, как x=(y);[z](это не то же самое, что x=((y)[z])).

И вот некоторые места, где, к сожалению, нужны переводы строк :

  • После ++и --.
  • После [...].

Часто можно сохранить байты путем реорганизации назначений. Например:

a=0;b=""c=[""]
b=""c=[b]a=0

x=f()y=i;z=a[0]
x=f()z=a[0]y=i

1

Используйте структуры управления суффиксами

Почти никогда не оптимально не использовать суффиксные операторы, которые вы можете использовать {...}вместо do...end.

Несколько примеров:

x|unless[not(_ in y)]do[0]else[1]done
x|[0]unless[not(_ in y)]else[1]

if[p<0]do c+=p;a-=p done
{c+=p;a-=p}if[p<0]

Вы можете сделать if[_ in y]вместо этого?
user41805

@KritixiLithos Нет, потому что я хочу, чтобы условие было ИЛИ, а не И. В настоящее время он проверяет, есть ли хотя бы одно значение, в xкотором оно находится y, но ваше условие проверяет, все ли значения в xтоже есть y. (Пример был скопирован отсюда ).
fergusq

1

Используйте поток для ввода

В тех случаях, когда входные данные представляют собой список элементов, может быть полезно извлечь значения из потока, а не получать их в виде массива.

В большинстве случаев элементы массива повторяются, помещая их в поток, а затем повторяя их, используя forцикл (или подчеркивание). Так как элементы все равно повторяются из потока, почему бы не определить, что они должны быть там с самого начала?

Например, чтобы вычислить сумму квадратов чисел на входе:

{|a|a|[_^2]|sum} /* Removing a redundant argument */
{[_^2]|sum}      /* saves 5 bytes */

1

Скобки необязательны в контексте оператора. Это применимо, даже если аргумент начинается с оператора. Например, [a()|sqrt-_]короче чем [a()|sqrt(-_)]. Скобки после aявляются обязательными, как aв контексте выражения, а не в контексте выражения.

Однако, письмо [a()|sqrt(_+1)*2]не представляется возможным, и дополнительные скобки необходимы , чтобы помочь анализатору: [a()|sqrt((_+1)*2)]. Часто такое выражение можно переписать так, чтобы оно не начиналось с круглых скобок:[a()|sqrt 2*(_+1)]


Можно ли также передавать несколько параметров в функции, не требуя скобок?
user41805

@KritixiLithos Да. Например. [a()|atan2 _,_]будет разрешено
fergusq

1

Используйте ,вместо ..в []/ pushзаявления

Связано: использовать ,вместоand

pushФункция (так же как и printфункция) может принимать любое число аргументов, и выводит каждый из них без каких - либо разделителей.

Так что это означает что-то вроде этого

["a"..b]        /*8 bytes (string "a" concatenated with variable b)*/

можно сократить до всего

["a",b]         /*7 bytes*/

сохранение 1 байта.


1

[]/ push>print

Никогда не используйте printзаявления. []Пуш-заявления всегда в гольфе. Разница между printи pushзаключается в том, что первый выводит завершающий символ новой строки, а второй - нет. Однако это можно обойти.

print"a"              /* 8 bytes */
["a                   /* 6 bytes; uses a literal newline */
"]

print"a",b            /* 10 bytes */
[`a$b                 /* 8 bytes; uses a literal newline and `` strings */
`]

1

Использование ``строк

В ""строках вам придется экранировать определенные символы, чтобы использовать их. Например, чтобы напечатать обратную косую черту, вы должны иметь строку вроде "\\". Существует один добавленный байт для экранирования обратной косой черты. Однако, если вы используете ``, вам не нужно экранировать этот символ и вы можете сохранить один байт.

print"\\"     /* 9 bytes */
print`\`      /* 8 bytes */

Мало того, вы можете кодировать переменные и выражения внутри ``строк, используя $variableNameили ${expression}функцию, отсутствующую в ""строках.

В этих примерах мы выводим строку, соединенную "a"со значением переменной, bс завершающей строкой .

["a",b,"      /* 11
"]               bytes   */
[`a$b         /* 8
`]               bytes; encodes b in the string using $b */

1

Используйте ,вместоand

Условия в Röda являются потоками и могут состоять из нескольких значений. Эти значения уменьшены до одного логического значения с and.

Это означает , что вы можете заменить andс ,в условиях толкнуть несколько значений потока:

x if[a and b]
x if[a,b]

Пустое состояние правдиво

Также возможно иметь условие, которое не содержит значений, что является правдой.

x while true
x while[]

1

Напишите списки замены в форме *"...;..."/";"

replaceФункция принимает обычно список строк в качестве аргументов. Однако, если список очень длинный, полезно просто сохранить в строке пары регулярное выражение / замена, а затем разбить строку и использовать оператор «звезда»:

replace"a","b","c","d"
replace*"a;b;c;d"/";"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.