Советы по игре в гольф в шелухе


15

Husk - совершенно новый язык игры в гольф, созданный пользователями PPCG Leo и Zgarb . Он начал становиться все более и более конкурентоспособным, часто оставаясь близким или даже опережая языки, известные как очень лаконичные, такие как Jelly и 05AB1E.

Давайте перечислим некоторые из техник игры в гольф, которые несколько специфичны для Husk. Как всегда, пожалуйста, оставьте один совет за ответ.



1
@totallyhuman первый ответ Husk Все еще не что новое
H.PWiz

Ответы:


10

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

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

Примеры:

≠  Numbers: Absolute difference
   Chars:   Absolute difference of code points
   Lists:   First Index where the differ

Comparisons <, >, ≤, ≥:

For strict comparisons:
Numbers,Chars:  max 0 (the appropriate difference¹)
Lists: The first index where the comparison between the two lists is true

For non-strict comparisons:
Numbers,Chars: max 0 (the appropriate difference + 1)
Lists: Either the result of the strict comparison or, if they are equal,
       the length of the list + 1

ṗ  Index into the list of prime numbers

V  The index of the first element for which the condition is true

€  The first index of that element/substring in the list

£  Works like €

&  Given two arguments of the same type will return the second argument if false,
   otherwise will return the first argument

|  Given two arguments of the same type will return the second argument if true,
   otherwise will return the first argument

¦  Return the quotient if divisibility holds

Λ,E,Ë  Will all return length+1 in truthy cases

Char predicates:
□,±,√,D,½  will each return the codepoint of its argument on truthy cases

¹ соответствующая разница означает разницу кодовых точек для символов. Это также относится к порядку аргументов. т.е. <x y, будетx-y


7

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

Как вы, возможно, уже знаете, [₀-₉]+|[₀-₉]это регулярное выражение для синтаксиса для вызова линии, отличной от той, в которой вы сейчас находитесь.

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

Таблица функций:

+----------+----------+
|Index     |Function  |
+----------+----------+
|1         |´ (argdup)|
+----------+----------+
|2         |` (flip)  |
+----------+----------+
|3         |m (map)   |
+----------+----------+
|4         |z (zip)   |
+----------+----------+
|5         |S (hook)  |
+----------+----------+

Строки в вашем коде помечены соответствующими 0-значными индексами сверху вниз. Если M <N , где M является этикетка и N это количество строк в коде, метка просто представляет собой функцию , определенную в строке М . Если N ≤ M <N * 6 , он представляет функцию из таблицы выше по индексу ⌊M ÷ N⌋ с функцией, определенной в строке M mod N, в качестве первого аргумента. Если N * 6 ≤ M , возникает ошибка индекса.


5

Лямбда может быть короче новых функций

Как вы, вероятно, знаете, если у вас есть многострочная программа, вы можете ссылаться на строки с индексами ₀…₉, например, в случае

f
g

будет ссылаться на функцию g. Теперь, если вы всегда применяете входные данные к функции g(и используете ее несколько раз); что-то вроде этого:

f₁⁰[...]g₁⁰[...]
h

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

λf⁰[...]g⁰[...])h

Обратное также может быть правдой

В случае самореферентной лямбды ( φχψ) есть особый случай, когда вы применяете входные данные непосредственно к рекурсивной функции, в этих случаях вам лучше использовать индекс вместо определения новой лямбды и использования .


5

Использование Γ

Основное использование встроенной функции Γ, известной как сопоставление с образцом в списках или деконструкция списка , состоит в том, чтобы разбить список на голову и хвост и применить к ним двоичную функцию. Это соответствует идиоме паттерна Хаскелла

f (x : xs) = <something>
f [] = <something else>

где <something>это выражение , содержащее x, xsи , возможно f. Есть 4 перегрузки Γ, каждая из которых работает немного по-своему.

list

Первая перегрузка, listпринимает значение aи двоичную функцию f. Он возвращает новую функцию, которая принимает список, возвращает, aесли он пуст, и вызывает fголову и хвост , если он не пуст . Например, Γ_1€принимает список, возвращает, -1если он пуст, и индекс первого появления первого элемента в хвосте, если нет.

listN

Вторая перегрузка, listNаналогична list, за исключением того, что aона опущена, и вместо нее используется значение по умолчанию возвращаемого типа. Например, Γ€эквивалентно Γ0€, поскольку числовое значение по умолчанию - 0.

На практике listNиспользуется чаще, чем list, поскольку значение по умолчанию либо не имеет значения, либо именно то, что вам нужно. Распространенная картина Γ~αβγ, где αβγтри функция; это относится βк первому элементу и γк хвосту и объединяет результаты с α. Он был использован, например, в этом ответе . Другие шаблоны включают в себя Γo:αприменение αтолько к первому элементу и Γ·:mαприменение αко всем элементам, кроме первого. Последний был использован в этом ответе .

listF

Третья перегрузка немного сложнее. Мол list, он принимает значение aи функцию fи возвращает новую функцию, gкоторая принимает список. Однако на этот раз он fполучает дополнительный аргумент функции, который gсам по себе, и может вызывать его для любого значения (включая, но не ограничиваясь этим, конец списка ввода). Это означает, что listFреализует общую схему рекурсии в списках. listFиспользуется не очень часто, поскольку явная рекурсия с list/ listNобычно такой же длины или короче, как в этом ответе .

listNF

listNFявляется listFто , что listNэто list: вход aопущен, а значение по умолчанию типа возвращаемого используются вместо этого. В редких случаях он может быть короче правого сгиба, например, в этом ответе .

В качестве примера рекурсивных версий Γфункция Γλ·:o⁰↔перетасовывает список в следующем порядке: первый, последний, второй, второй-последний, третий, третий-последний и так далее. Попробуйте онлайн! Функция f- это явная лямбда λ·:o⁰↔, аргументом которой является вся функция. Что fделает, так это обратный хвост , затем рекурсивный вызов главной функции o⁰и, наконец, возврат головы ·:. Конечно, Γ·:o₀↔это на байт короче, но не работает, если строка содержит что-то еще, кроме этой функции.


3

Комбинаторы могут применяться к функциям высшего порядка

Предположим, у вас есть список целых чисел X , и вы хотите подсчитать общее количество элементов X , которые больше длины (X) . Counting элементы , которые удовлетворяют предикат делаются с функциями высшего порядка #, но здесь предикат (будучи больше длинами (X) ) зависит от X . Решение состоит в том, чтобы применить комбинатор к #и функцию , o>Lкоторая проверяет , является ли список короче , чем число. В функции Ṡ#o>Lсписок X передается o>L, частично примененная функция передается #, а X задается #как второй аргумент.

В общем случае, если αфункция высшего порядка, βбинарная функция и γунарная функция Ṡαβэквивалентны псевдокоду Haskell

\x -> α (\y -> β x y) x

§αβγ эквивалентно

\x -> α (\y -> β x y) (γ x)

и ~αβγэквивалентно

\x y -> α (\z -> β x z) (γ y)

до тех пор, пока типы совпадают.

В качестве другого конкретного примера §►δṁ≠Pнаходит перестановку списка X, которая максимизирует сумму абсолютных разностей с соответствующими значениями X ( δṁ≠объединяет два списка с использованием абсолютной разности и берет сумму).


3

Значения по умолчанию для шелухи

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

.------------------------------------.---------------.----------.-------.
|   Type (X and Y are placeholders)  | default (def) |    max   |  min  |
|------------------------------------|---------------|----------|-------|
|       Character (C)                |      ' '      | \1114111 | \NUL  |
|       Numbers   (N)                |       0       |   Inf    | -Inf  |
|       List of X (LX)               |      []       |  ∞ max   |   []  | *
|       Function :: X -> Y           | const (def Y) |   n/a    |  n/a  |
'------------------------------------'---------------'----------'-------'

* Здесь ∞ должен представлять бесконечный список соответствующего максимума (см. Пример ниже)

Примечание. Для кортежей (X, Y) будут использоваться значения для каждого компонента отдельно.


Когда они используются

В то время как максимумы и минимумы используются только для ▲▼пустых списков (например, husk -u "▼" "[]:LLN"будет возвращать бесконечный список Inf), значения по умолчанию используются в нескольких местах:

  • сворачивание пустых списков без указания значения самостоятельно ( Fи )
  • предварительное значение по умолчанию (с Θ)
  • когда чтение ( r) не удается
  • получение первого / последнего элемента ( ←→) или индексация в один ( !)
  • сопоставление с образцом ( Γ) в пустых списках
  • используя или в пустых списках
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.