Я недавно запустил один тестовый гольф, и кажется, что победителем стал GolfScript (сюрприз, сюрприз!). Интересно то, что был еще один очень сильный конкурент, у которого были все шансы победить GolfScript. Его зовут APL. Я вижу много ответов, написанных в APL здесь. Похоже, что этот язык достаточно эффективен для игры в гольф кода, поэтому я решаю попросить любые советы по игре в гольф кода, которые вы знаете для программ APL. Не стесняйтесь размещать некоторые примеры кода. Обычно очень интересно видеть язык в действии.
Поезда
источник
Трюки для работы с поездами
/
и⌿
в поездахПри использовании поездов вы можете использовать сокращения,
f/
такие как сумма+/
или даже дублирование сокращения//
. Однако, если ваш поезд имеет больше частей слева от сокращения, вам нужно заключить в скобки верхнюю часть. Вот несколько приемов для сохранения байтов.Используйте
1∊
вместо монадических∨/
или∨⌿
логических массивовЗадача: Если заданы две строки A и B одинаковой длины, вернуть 2, если любые соответствующие символы A и B равны, иначе 0. Например ,
A←'abc'
иB←'def'
дает0
иA←'abc'
иB←'dec'
дает2
.Решение dfn может быть,
A{2×∨/⍺=⍵}B
но вы хотите сократить его, перейдя в молчание.A(2×∨/=)B
не собирается работать, потому что правила формирования поезда разбирают это так, как2 (× ∨/ =)
вы хотите2 × (∨/=)
.Заметим, что
∨/
или∨⌿
на булевом векторе (∨/,
или∨⌿,
для массивов более высокого ранга) спрашивается, есть ли 1, то есть1∊
мы можем записать наш поезд как2×1∊=
.Обратите внимание, что
∊
это правильный аргумент, поэтому вы не можете использовать его для уменьшения каждой строки или столбца в отдельности.Используйте
1⊥
вместо монадического+/
или+⌿
Задача: учитывая список списков L и индекс N, вернуть трижды сумму N-го списка. Например
L←(3 1 4)(2 7)
иN←1
дает24
.Решение dfn может быть,
N{3×+/⍺⊃⍵}L
но вы хотите сократить его, перейдя в молчание.N(3×+/⊃)L
не собирается работать, потому что правила формирования поезда разбирают это так, как3(× +/ ⊃)
вы хотите3 × (+/⊃)
.Заметьте, что вычисление списка чисел в унарном (base-1) эквивалентно суммированию списка, потому что ∑ { a , b , c , d } = a + b + c + d = ( a × 1³) + ( b × 1² ) + ( c × 1¹) + ( d × 1⁰). Поэтому так
+/a b c d
же, как1⊥a b c d
и мы можем написать наш поезд, как3×1⊥⊃
.Обратите внимание, что для аргументов более высокого ранга
1⊥
эквивалентно+⌿
.Использовать
f.g
вместоf/g
скалярных и / или векторных аргументовЗадача: учитывая список L и число N, верните диапазон 1 до числа минимального остатка деления, когда элементы L делятся на NEg
L←31 41 59
иN←7
дают1 2 3
.Решение dfn может быть,
N{⍳⌊/⍺|⍵}L
но вы хотите сократить его, перейдя в молчание.N(⍳⌊/|)L
не собирается работать, потому что правила формирования поезда разбирают это так, как⍳ (⌊/) |
вы хотите⍳ (⌊/|)
.Внутреннее произведение
A f.g B
скалярных двух функций, когда аргументы являются скалярами и / или векторами, совпадает с тем,f/ A g B
что оба они(A[1] g B[1]) f (A[2] g B[2]) f (A[3] g B[3])
и т. Д., Поэтому мы можем записать наш поезд как⍳⌊.|
.Обратите внимание, что это не работает для массивов более высокого ранга.
Используйте
∊⊆
вместо/
логических аргументов левый и простой векторный правыйЗадача: учитывая список L и число N, отфильтруйте список так, чтобы остались только числа больше N. Например
L←3 1 4
иN←1
дает3 4
.Решение dfn может быть,
N{(⍺<⍵)/⍵}L
но вы хотите сократить его, перейдя в молчание.N(</⊢)L
не будет работать, потому что правила привязки будут анализировать это как,(</) ⊢
но вы хотите,/
чтобы функция копировалась, а не уменьшала оператор .Dyadic
⊆
с логическим левым аргументом разбивает правый аргумент в соответствии с сериями 1 в левом аргументе, отбрасывая элементы, обозначенные 0. Это почти то, что мы хотим, за исключением нежелательных разделов. Тем не менее, мы можем избавиться от разбиения, применяя monadic∊
. Таким образом{(⍺<⍵)/⍵}
может стать{∊(⍺<⍵)⊆⍵}
и таким образом мы можем написать наш поезд как∊<⊆⊢
.Обратите внимание, что это не работает для массивов более высокого ранга.
Использовать
0⊥
вместо⊢/
или⊢⌿
с числовыми аргументамиЗадача: Учитывая список L и число N, Умножить N с правым элементом Ноги
L←3 1 4
иN←2
дает8
.Решение dfn может быть,
N{⍺×⊢/⍵}L
но вы хотите сократить его, перейдя в молчание.N(⊣×⊢/⊢)L
не собирается работать, потому что правила формирования поезда разбирают это так, как⊣ (× ⊢/ ⊢)
вы хотите⊣ × (⊢/⊢)
.Заметьте, что
0⊥
числовой массив такой же, как⊢⌿
, поэтому мы можем записать наш поезд как⊣×0⊥⊢
.Обратите внимание, что это выбирает последнюю главную ячейку массивов более высокого ранга.
источник
Используйте
⊥
для объединения умножения с сложениемПредположения:
a
иb
являются терминами, которые не требуют дополнительных скобок при использовании в качестве левого аргументаC
это выражение, которое может нуждаться в скобках при использовании в качестве левого аргументаa
b
C
оценивать по числовым скалярамисточник
Сложные числа
Часто упускаемые из виду, они предоставляют прекрасные возможности для сокращения выражений, связанных с сетками, лабиринтами, фракталами или геометрией.
источник
Индексирование по модулю длины вектора
⊃i⌽a
часто короче наивного⊃a[(≢a)|i]
илиa⊃⍨i|⍨≢a
(гдеa
вектор иi
целое число⎕io
0)полезный вариант этого (спасибо EriktheOutgolfer за указание):
I↑Y⌽⍨I×X
гдеY
- конкатенация некоторыхI
векторов длины иX
индекс того, который мы хотим выбрать, например:3↑'JanFeb...Dec'⌽⍨3×month
источник
Постоянные функции
=⍨
и≠⍨
благодаря нгн.Иногда вам просто нужно одно значение для каждого элемента списка. Хотя у вас может возникнуть соблазн использовать
{value}¨
его, он короче,value⊣¨
но для некоторых общих значений вы можете стать еще короче (используя⎕IO←0
):¯1
с⍬⍸list
0
с⍬⍳list
1
с⍬⍷list
Обратите внимание, что они работают только со списками (хотя они могут быть вложенными). Для массивов более высокого ранга вы можете использовать следующее, чтобы получить все 0 и все 1:
1
с=⍨
0
с≠⍨
Если вы установите
⎕ML←0
, все числа могут быть превращены в нули (как будто0×
) с помощью:∊
Если вам нужен только один номер, вы можете использовать monadic
≡
для получения 1 или 0 вместо использования1⊣
или0⊣
.источник
⊣\
⊣
и⊢
с/
и⌿
достоинством должности своих собственным.использование
⍨
Избегайте скобок
⍨
(Commute) может сохранить ваши байты, избегая скобок. Если у вас есть функция, в которой левый аргумент необходимо заключить в скобки, а правый - нет, вы можете сохранить байт, например(A<B)÷C
→C÷⍨A<B
.Двойные массивы
Чтобы добавить копию массива в его конец, используйте
,⍨A
или⍪⍨A
.Двойные числа
Вместо использования
2∘×
для удвоения, вы можете использовать,+⍨
так как он добавляет аргумент к себе:1+2∘×
→1++⍨
.Квадратные числа
Вместо использования
2*⍨Y
в квадрат вы можете использовать,×⍨Y
так как он умножает аргумент на себя:2*⍨A+B
→×⍨A+B
.Случайная перестановка
?⍨N
даст вам случайную перестановку длиныN
.Self-Классифицировать
Найти индексы первого появления каждой крупной ячейки с
⍳⍨A
Подсчитайте конечные единицы в булевом векторе
Вместо того,
+/∧\⌽B
чтобы посчитать, сколько трейлингов 1N
можно использовать⊥⍨
.Обратная композиция
A f∘g B
естьA f g B
, но если хочешь(g A) f B
, используйf⍨∘g⍨
.Обратное уменьшение
f/ a1 a2 a3
естьa1 f (a2 f a3)
. Если хочешь(a1 f a2) f a3
, используйf⍨/⌽
.Обратное сканирование
f\ A B C
естьA (A f B) (A f (B f C))
.f⍨/∘⌽¨,\ A B C
естьA (A f B) ((A f B) f C)
.f⍨\⌽ A B C
есть((A f B) f C) (B f C) C
.⌽f/∘⌽¨,\⌽ A B C
, есть(A f (B f C)) (B f C) C
.источник
Перечислять символы в строке без
⍳≢
Задача: Для двух строк, S и T, перечислить индексы их конкатенации. Например
S←'abcd'
иT←'xyz'
дает1 2 3 4 5 6 7
.Решение dfn может быть,
S{⍳≢⍺,⍵}T
но вы хотите сократить его, перейдя в молчание.⍳≢,
не будет работать, потому что правила парсинга поезда будут анализировать это так, как(⍳)≢(,)
вы хотите(⍳≢),
.Dyadic
⍋
с пустым левым аргументом классифицирует простые символьные массивы в соответствии с их текущим порядком, который совпадает с⍳≢
. Таким образом{⍳≢⍺,⍵}
может стать{⍬⍋⍺,⍵}
, поэтому мы можем написать наш поезд как⍬⍋,
.Обратите внимание, что это не работает для числовых или смешанных массивов.
источник