GolfScript слишком часто делает свой собственный путь, и я чувствую, что хранилище полезных советов для игры в гольф в J может помочь в борьбе против империи зла. Какие у вас есть советы по сокращению этого и без того краткого языка?
Для тех , кто хочет узнать J, очевидное место , чтобы начать это jsoftware сайт и особенно словарный запас , то обучение J руководство и J для C программистов руководство.
GolfScript gets its own way far too often
в 2019 году.Ответы:
Есть несколько тонкостей, чтобы выжать последние несколько символов в J. Для следующего предположим, что каждая заглавная буква является примитивным глаголом (то есть я удаляю пробелы, которые в противном случае потребовались бы для разделения имен).
Когда у вас идет поезд, и вам нужно применить функцию поверх другого на полпути,
([:FLGR)
и(LF@:GR)
иметь такое же количество символов, но(LF@GR)
сохраняет один. Если кадр G больше или равен рангу монады F, это допустимое преобразование. Примечательно, что все поезда имеют бесконечный ранг, как, ,. ,: ~. /: \: [ ]
и большинство случаев использования#
и|.
.Если вам нужно выбрать строки из списка, и у этих строк нет пробелов, используйте
>i{ab`cd`ef
. Это грязно, но сохраняет символы для каждой новой строки, с которой вам приходится иметь дело, если только вы не вытягиваете отдельные символы, и даже в этом случае charlist должен быть длиной 4, чтобы быть короче. Происходит то, что неопределенные имена обрабатываются как ссылки на глаголы, и когда вы берете герунды этих глаголов, вы получаете строку имени в штучной упаковке. Любые имена, которые уже определены как имеющие тип существительное, наречие или соединение, не могут быть использованы таким образом, потому что эти имена разрешаются до того, как`
могут иметь их.Если вам повезло иметь выражение для работы, а не просто молчаливый глагол, почти всегда стоит присвоить переменные, которые вы используете, переменным, будь то существительные, глаголы или наречия. Парены иногда окупаются, вписываясь в то место, где у вас были пробелы раньше, и большинство таких определений того стоят, если их снова использовать еще раз.
Соединения вроде
(FGH)^:(u`v`w)
можно переписатьu`v`w(FGH^:)
. Это работает для любой длины поезда, даже 1, хотя вы сохраняете что-либо, только если этот трюк удаляет паренсы из правильного аргумента. Этот прием работает только при предварительной загрузке левого операнда. (Понятия не имеете, что только что произошло? Найдите «молчаливые наречия» и изучите раздел « Анализ и выполнение » в Словаре J).Не используйте
a.&i.
, используйтеu:
!{&a.
и3&u:
эквивалентны по длине, хотя, и первый может быть более полезным в соединении (в зависимости от соединения).Такие вещи, как
(2%~F)
и(F%2:)
эквивалентны по длине. Это полезно, потому что иногда, в зависимости от того, как выглядит остальная часть вашего поезда, вы можете перестроить его с помощью@
трюков, как написано в первом пункте, чтобы сохранить некоторых отчаянных персонажей. (И, конечно, еслиF
есть,]
а поезд - это монада, то есть%&2
спасает чарса, да.)Крюкообразные поезда с
]
или[
как самый левый глагол, например(]FGH)
.]
позволяет разбить двоичное приложение и использовать только правильный аргумент. (Поменяйте местами слева со(]FGH)~
штрафом не менее 1 символа, а может и больше.) Сохраняет символ(FGH)@]
и очень удобен в герундиях![
в монтируемом хуке позволяет вам что-то сделать для побочных эффектов на правой стороне, а затем вернуть аргумент снова. Чаще всего используется с1!:2
, возможно, с форматированием мусора.I / O отстой. Ускорьте процесс, создавая петли из всего, что вы можете.
1!:1
имеет ранг0
, и оба1!:2 3
имеют ранг_ 0
, например, поэтому используйте это, создавая массивы из 1 и бегите1!:1
прямо над ними. Обратите внимание, что он".
также имеет ранг 1, так что обычно вы можете просто поставить его сразу после1!:1
, и не нужно прикреплять его через@
или ранг махинаций.Это не легко найти места, чтобы поставить это, но
::
может быть полезно.::]^:_
например, это особенно мощная комбинация, которая позволяет вам делать что-то опасное, пока вы больше не можете это делать. (С учетом обычных^:_
предостережений типа «как петля».)Это также позволяет вам использовать
{
списки, которые не имеют желаемого индекса, потому что при этом возникает ошибка домена. Например, полезно взять заголовок списка только в том случае, если он существует (попробуйте использовать,::]
чтобы вернуть пустой список или::_1:
вернуть код ошибки и т. Д.).]`($:@u)@.v
обычно можно сделать корочеu^:v^:_
, особенно на определенияхu
и сv
которыми можно поиграться. Аналогичный случай имеет место для условно-подобныхu^:(1-v)
против]`u@.v
. Рассмотрите ваши варианты, особенно когда у вас много плавающих именных глаголов. Это также немного более гибко, но помните, что при использовании$:
, есть глубина рекурсии, с которой легко столкнуться. (Обычно что-то вроде 1800 итераций?)источник
%&2
спасает полукокса" И-:
спасает другого!Самое важное при игре в гольф в J - это не только понять проблему, но и свести проблему к серии преобразований массива. Вы должны понимать этот способ мышления, чтобы иметь успех с J-кодом.
Например, недавняя задача попросила решить самую большую проблему подмассива . Стандартный алгоритм для решения этой проблемы - это алгоритм Кадане, имеющий следующее неофициальное описание:
Перевод в императивный код прост:
Этот алгоритм кажется сложным для J с первого взгляда, поскольку существует явный цикл, который на первый взгляд не выглядит как сокращение. Если вы понимаете, что делает алгоритм, вы можете распутать отдельные шаги и увидеть, что он фактически выполняет две простые операции с массивами:
Теперь эти два шага очень легко реализовать в J. Вот перевод:
(0 >. +)/\. y , 0
- Этот шаг работает с другого конца массива, чтобы лучше соответствовать парадигме J.0 >. +
молчит для0 >. x + y
.>./ y
Вместе мы получаем очень краткую реализацию алгоритма:
Если вы научитесь подходу к реализации алгоритмов, ваши решения будут такими же краткими, как и этот код.
Вот некоторые уловки, которые я накопил со временем. Этот список будет расширяться по мере того, как я получу больше знаний в области гольфа.
=
поначалу странный, но очень полезен в художественных задачах ASCII.&
в молчаливом контексте, когда вы хотите силовое соединение. Словарь предлагаетu@[&0
в качестве молчаливой замены4 : 'u^:x y
и я тоже.[:
или@:
в последовательности, напримерu@v
, выбрав вариантu
с левым аргументом. Например, чтобы удалить первый элемент результатаv
, используйте1}.v
вместо,[:}.v
если}.@v
по какой-то причине невозможно.] v
часто короче, чемv@]
если вы хотите использовать monadicv
в двоичном контексте. Это полезно, особенно когдаv
это длинный ряд глаголов.m (n v w) y
вместо(n v m&w) y
. Это может позволить избежать пробелов и скобок.#\
вместо>:@i.@#
.u &. v
полезно, когдаv
есть лицевая сторона. Когда нет, вы можете использовать[: vinv u & v
илиu & (v :. vinv)
вместо.^:_
чрезвычайно полезен для алгоритмов, в которых вы хотите достичь конвергенции, таких как заливка или моделирование.=.
и=:
может быть вставлен в любом месте фразы. Используйте это, чтобы сделать однострочники там, где молчаливого обозначения недостаточно.,
вместо нескольких сокращений при уменьшении многомерных массивов.источник
Будьте осторожны с использованием петель.
В то время как J имеет зацикливания структуры (
for. do. end.
,while. do. end.
и вариации), если вы оказываетесь их помощью есть возможность того, что ваш алгоритм не играет в гольф сильных J и что есть сбережения характера , которые будут сделаны.^:
силовое соединение - твой друг. Чтобы выполнить глаголx
раз:Если вам нужен результат каждой итерации в списке:
Вы также можете использовать,
^:
чтобы выполнить глагол условно:Удваивается,
+:
если^:
элемент больше 33<]
("0
меняет ранг глагола, чтобы он одновременно работал с элементом).источник
(i.x)
пример, тоf^:(<x)
есть эквивалентноf^:(i.x)
.вход
1!:1[1
займет одну строку ввода, завершенную нажатием клавиши ввода.1!:1[3
займет несколько строк ввода (завершается с помощью Ctrl-D на моем Mac, Ctrl-C в Windows).Если вы пытаетесь вводить числа, использование
".
оценит строку и вернет список чисел, готовых для манипуляции. Если вы набираете одно число, но вам нужно работать с цифрами индивидуально".,.
(благодаря комментарию Яна Дворжака за это) или"."0
разделите строку на отдельные цифры:Если вы читаете в строках, самый короткий способ получить список отдельных строк в штучной упаковке - это использовать
;:
. Это лучше всего подходит для строк, разделенных пробелами:источник
1!:1[2
получилось бы (если вообще что-нибудь)?1!:
странице (я не эксперт J), 2 - это экран, поэтому ввод с экрана не имеет особого смысла.2
не действует? У меня нет моего компьютера J, чтобы попробовать его в данный момент. Где я вижу2
, чуть ниже заметки о1!:1
, это для1!:2
.".
имеет ранг 1-xx и,.
всегда создает двумерный массив,".,' ',.
(стежок с пробелом, разбить и оценить; 8 символов) можно заменить на просто".,.
(разбить элементы и оценить; 4 символа).Использование итерации для вычисления последовательностей
Как правило, решение проблемы последовательности OEIS потребует использования одной из формул, приведенных на его странице. Некоторые из них хорошо адаптируются к J, а другие - не так. Рекурсивные формулы просты, однако итерация может быть непростой. Шаблон, который я начал использовать,
где
s
- первое значение в последовательности,f
это глагол, который будет вычислять следующий термин, заданный предыдущим термином, иn
основанный на нуле индекс термина, который вы хотите вычислить. Этот метод основан на том факте, что при вычислении мощности диады LHS связывается с диадой, чтобы сформировать новую монаду, и эта монада вкладывается в начальное значение. Диада, передаваемая наречению власти, - это ловушка, в которой(]f)
указывается индексn
на LHS и значение члена в последовательностиs
. Крюк будет применятьсяf
наs
как монады, а затем игнорировать ,n
чтобы вернуть результатf s
.Стандартная библиотека
Иногда вы можете обнаружить, что у J будет поддержка глагола в его стандартной библиотеке . Например, большинство побитовых целочисленных операций связаны с именами, которые короче, чем примитивный вызов.
Встроенные дата и время также доступны.
Изменяется
Если у вас есть набор значений,
[a, b, c]
и вы хотите сформировать диапазон на основе их продукта[0, 1, 2, ..., a*b*c-1]
, типичным подходом будет найти их продукт, а затем сформировать диапазон, который может[:i.*/
стоить 6 байтов. Более короткий путь -,@i.
4 байта, поскольку онi.
может образовывать многомерные массивы, продолжая отсчитывать, и его выравнивание приведет к эквивалентному диапазону.Непрерывная печать
Неявный способ напечатать значение и продолжать использовать его без явного цикла -
([echo)
для монадического случая.echo
это глагол в стандартной библиотеке, который печатает его содержимоеstdout
в том же формате, который используется в интерпретаторе. Затем ловушка передает то же входное значение, используя левый[
глагол.База 10 цифр целого числа
Стандартный способ получения базовых 10 цифр целого числа -
10#.inv]
это 8 байтов, слишком много! Альтернатива состоит в том, чтобы преобразовать ее в строку и проанализировать ее на уровне 0,"."0@":
что позволяет сэкономить байт, но еще лучше -,.&.":
сохранить еще один байт, получив окончательную стоимость 6 байт вместо 8.источник
Попробуйте использовать явное определение вместо написания молчаливого глагола; Конечно,
3 :'
и'
стоимость 5 байтов, но вы можете сэкономить много@
,@:
и[:
таким образом.источник
Некоторые (довольно) распространенные трюки, которые я видел
Я делюсь несколькими вещами, которые мне пригодились. В основном все это советы, которые я получил сам, но у меня больше нет кредитов.
Сумма ранга один массив
Вместо использования
+/@:(FGH)
использовать(1#.FGH)
. Это означает снижение до базы 1, что фактически означает суммирование массива. Хотя он длиннее+/
, он не требует кепки или композиции, что часто делает его намного короче, чем при использовании+/
.Считая последние истины
Если у вас есть логический список, и вы хотите посчитать количество конечных истин, используйте
#.~
. Смотрите здесь . APL ответ дает хорошее объяснение того , как это работает. Конечно, это было полезно только для меня дважды, но я решил, что поделюсь этим в любом случае.Под (&.)
Не конкретный трюк, а просто общее предположение: наречие
&.
часто приводит к изящным и (что более важно) кратким решениям. Имейте это в виду, когда вы играете в гольф.Часто это полезно для двоичных и других базовых задач преобразования, например, этот код, который удаляет самый старший бит из числа:
}.&.#:
(преобразовать в список двоичных цифр, удалить первую цифру, затем отменить преобразование в список двоичных цифр и преобразовать обратно в десятичную). Простое решение является еще два байта:#.@}.@#:
.Under также полезен для задач, где вам нужно работать с десятичными цифрами, так как вы можете использовать
u&.":
. Например, короткий путь миль дает колоть до десятичных цифр использования в:,.&.":
.Последний пример - определение величины вектора:
+/&.:*:
обратите внимание, что вам нужно собрать все результаты из*:
-square с -under,&.:
так как*:
-square имеет нулевой ранг.источник
Более короткие способы связываться со званиями
Иногда у вас будет такой код
<"0 i.3 3
, где вы хотите применить глаголv
по рангуr
. Однако, если вы используете существительное (например0
), вам часто придется включать пробел. Чтобы избежать этого, вы можете использовать другой глаголu
эквивалентного ранга и использоватьu"v
вместо него. Например, поскольку+
имеет ранг0 0 0
, мы можем использовать<"+
вместо<"0
.Вот таблица всех глаголов и их рангов (можно получить с помощью
v b. 0
):Чтобы использовать эту таблицу, найдите нужный ранг
r
с левой стороны, затем выберите подходящий глаголv
с правой стороны. Например, если мне нужно векторизовать глаголv
на глубине2 _ 2
, я нахожу этот ранг слева и выбираю%.
справа. Тогда я используюv"%.
вместоv"2 _ 2
.источник
strings
библиотека: советы по игре в гольфБиблиотека строк очень полезна для выполнения любых операций со строками. Конечно, это занимает
include'strings'
(что очень дорого, учитывая J), но иногда вы можете пожинать плоды.stringreplace
Найти себя, используя строку заменить? Обратите внимание, что
A stringreplace B
это так же, какB rplc A
.На самом деле, вот как
rplc
это реализовано:cuts
Глагол
cuts
обеспечивает таким образом:Так что это действительно нарезать строку.
источник
Получение чисел от 0 до 4
Если есть ограничения на использование чисел в вашем коде:
0
%_
: один делится на бесконечность.1
#_
: сколько бесконечностей?2
#_ _
: две бесконечности.3
verb
: есть встроенный.4
dyad
: еще один встроенный.Получение номеров от 10 до 35
База-inifinity литералов: 11 :
_bb
, 26 : и_bq
т.д.источник
Молчаливое программирование
основы
Диадический глагол
Монадический глагол
Разное
Трюки
(F x) G (H y)
Неявные решение:
(G~F)~H
; в зависимости от фактических глаголов рассмотрите возможность перестановки левого и правого аргументов для удаления~
.Монадно-диадические замены
источник
(G~F)~H
это чистая игристая доброта!&
твой друг, используй это с умомv
является глаголом,n
является существительным,x
иy
левый и правый аргументы, соответственно.Monad
&
: ввести~
внутри цепочки наречий / соединенияЦепочка наречий / соединения оценивается слева. Так что что-то вроде
_2&+/\&.>
не будет работать, потому что это анализирует, как(_2&+)/\&.>
мы хотим_2&(+/\)&.>
. В этом случае при переключении влево / вправо+/\
может быть сохранен байт,+/\~&_2&.>
потому что этот синтаксический анализ выполняется как((+/\)~)&_2&.>
. Чтобы понять, почему это работает:Диада
&
: Повторитеx
разЗнаете ли вы , что если вы даете левый аргумент
x
к&
, функция применяется этоx
разy
? Довольно много задач требуют от вас выполнения определенногоx
времени работы. В основном это достигается двумя способами:^:
без правильного операндаЕсли операция выполняется
v
, то онаv^:
становится цепочкой наречий, которая, когда ей дают левый операнд, становится монадическим глаголом. Такv
применяетсяy
,x
раз.&
как самое внешнее соединениеЧтобы использовать эту функцию , вам необходимо определить константу
n
и двоичный глаголu
, так что либоn u y
илиy u n
эквивалентноv
. Тогда вы можете написатьn&u
илиu&n
решить всю задачу. Эта форма наиболее эффективна, когда выбор константы очевиден, например, 3 в3 u:
(преобразование символов в значения ASCII).Кроме того,
u&n
немного предпочтительнее, чемn&u
когда самая внешняя структураu
является соединением или наречием (в этом случаеn&u
должно бытьn&(u)
; вы можете сделатьu~&n
вместо этого).Обратите внимание, что вы можете поместить диадику в
&
любом месте последовательности, чтобы добиться повторения произвольной функции для произвольного аргумента, в том же смысле, что и для динамического^:
.источник