Советы по игре в гольф в Pyth

46

Pyth - это язык процедурного программирования, вдохновленный Python, созданный пользователем PPCG isaacg .

Какие общие советы у вас есть для игры в гольф в Pyth? Я ищу идеи, которые могут быть применены к кодовым проблемам гольфа в целом, которые, по крайней мере, несколько специфичны для Pyth.

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

isaacg
источник

Ответы:

25

Сначала напишите код на Python

Pyth настолько похож на Python, что переводить программы Python на Pyth довольно просто. Однако, поскольку Pyth является языком, состоящим из одной буквы для каждой команды, иногда трудно написать прямой Pyth. Когда вы пишете сначала на Python, вы можете думать меньше (поскольку Python - довольно простой язык для написания кода).

Джастин
источник
1
Вы также можете упомянуть, что вы все еще можете использовать синтаксис Python в Pyth, так что вы можете конвертировать части программы по отдельности или просто использовать Python при необходимости. (Как вы сделали здесь )
FryAmTheEggman
@ mbomb007 Загрузите интерпретатор Pyth и прочитайте документы. Это единственный надежный способ написания программы на Pyth.
Джастин
@ mbomb007 Извините; так я научился писать Pyth (просматривая исходный код). На Pyth практически нет документации; Вы должны изучить синтаксис методом проб и ошибок.
Джастин
22

Знай свои переменные

Pyth имеет 3 категории переменных: общие предварительно инициализированные переменные, переменные, предварительно инициализированные на основе пользовательского ввода, и переменные, которые неявно генерируют назначение при первом использовании.

Общие переменные:

b = "\n"
d = " "
k = ""
G = "abcdefghijklmnopqrstuvwxyz"
H = {}                            # (empty dict)
N = '"'
T = 10
Y = []
Z = 0

Инициализированные вводом переменные:

Q = eval(input())
z = input()

Обратите внимание, что эти инициализации будут выполняться только в данной программе, если связанная переменная используется вне строки в коде. Кроме того, порядок Q, zесли оба используются.

Назначение на переменные первого использования:

Jи K. Если вы хотите инициализировать их оба одинаковыми значениями, вы можете сделать это с помощью выражения, такого как KJ0, что эквивалентно длиннее J0K0.

isaacg
источник
18

Используйте еще более новый онлайн-переводчик, чтобы проверить свои ответы.

Обратите внимание, что это новое программное обеспечение, поэтому оно может содержать ошибки. Пожалуйста, сообщите мне о любых проблемах.

isaacg
источник
2
Потрясающие! Я не мог найти это с Google, только то, что мне было нужно!
theonlygusti
12

Строки в конце строки не нуждаются в конечных кавычках. Например:

"Hello, world!

это полностью действующая программа Hello World.

isaacg
источник
Совершенно очевидно, что это первый результат Google для языка программирования Pyth. Вы создали свою собственную страницу на esolangs?
theonlygusti
3
@ theonlygusti Да, я сделал. Кроме того, это был не первый результат в октябре прошлого года.
Исаак
9

Использовать Cдля базового сжатия

Это на самом деле недокументировано, C в строке на самом деле не является прямым chr -> int, а вместо этого base 256 -> base 10 (то же самое для строк с одним символом). Это очень полезно при сжатии int, мы можем использовать этот скрипт для сжатия:

sCMjQ256

Возьми 12345678910, это приводит к ßÜ>(некоторые непечатные там).

Также с массивом целых чисел вы можете объединить их и с большими строками, преобразовав их в кодовые точки и рассматривая как базовое число 128.

Еще одно использование C, спасибо @xnor за то, что показали это, - создание произвольного большого числа. Наивный способ это:

^TT

Но мы можем сделать один байт лучше с:

CG

эта база 256 деконвертирует весь алфавит. Результаты 156490583352162063278528710879425690470022892627113539022649722= ~ 1.56e62.

Maltysen
источник
Добавлено в документ сейчас.
Исаак
8

Используйте короткие функциональные ... err ... функции

Когда лямбда-аргумент mapили reduceпросто применяет одну операцию к аргументам, вы можете использовать короткие формы, Mи F. fMxэквивалентно mfdx, и fFxто же самое, что и .UfbZx. Например, скажем, мы берем список чисел в качестве входных и выходных данных, каждое из которых увеличивается. Первый подход может быть:

mhdQ

Однако это можно переписать так:

hMQ

Аналогичная вещь относится к reduceс F. В качестве примера, скажем, есть задача вычислить произведение списка целых чисел. Опять же, первая попытка может быть:

.U*bZQ

Тем не менее, с F, что может быть сокращено до:

*FQ

Сбривает три байта ... неплохо!

kirbyfan64sos
источник
И вам это не нужно Q, так как оно дополняется, когда функция пропускает вход, делая это*F
Стэн Струм
7

Держите вашу реализацию Pyth в актуальном состоянии.

Я довольно регулярно совершенствую Pyth, удаляя менее полезные функции и добавляя более полезные, поэтому следите за новостями и регулярно обновляйте вашу копию реализации.

Некоторые недавно добавленные функции: (по состоянию на 19.10.14)

y: Действует как *2для чисел, так и как список всех подмножеств в строках и списках. Например:

pyth -c 'y"abc'
['', 'a', 'b', 'c', 'ab', 'ac', 'bc', 'abc']

f: fобычно это команда фильтра. Теперь, когда вызывается с числом в качестве второго аргумента, он фильтрует бесконечную последовательность, начиная с этого числа и считая по единицам, а затем возвращает первый элемент полученной последовательности.

Например, вот код для поиска наименьшего простого числа из миллиарда:

pyth -c 'f!tPT^T9'
1000000007
isaacg
источник
Это похоже на полезные дополнения, но что вы можете использовать вместо старого yz? mvdczdне может быть кратчайшим путем ...
Деннис
1
@Dennis Я выбросил старое, yпотому что я не думаю, что Pyth должен иметь несколько супер-легко анализируемых форматов ввода, только один, например, формат Python. Так что, да, я думаю mvdczd, придется сделать, к сожалению.
Исаак
@Dennis Проблема решена, только что добавили это в rпакет обработки строк в России.
Исаак
rвыглядит довольно полезно.
Деннис
@isaacg Извините, если это не по теме, но мне интересно, как использовать корневую операцию @в Fdr1 + 1 @ Q2Iq% Qd0d для создания факторного калькулятора. Когда я пытаюсь использовать его, indexвместо этого по умолчанию используется значение. Есть ли способ обойти это поведение?
StardustGogeta
5

Именованные аргументы в функциях (больше не поддерживаются)

Иногда значения по умолчанию в функциях могут быть полезны для игры в гольф. Pyth фактически поддерживает это (к моему большому удивлению). Например:

DC=Z1RZ;C;C5

Распечатает:

1
5

Вы также можете использовать J и K для сохранения символов при этом:

DgJ1K1R+JKg;g2;g2 3

печатает:

2
3
5

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

Это больше не работает, но я оставил это здесь на случай, если кто-то захочет поиграть в гольф, используя старую версию Pyth.

FryAmTheEggman
источник
16
Ух ты! Даже я не осознавал, что Пиф поддержал это, и я написал язык!
Исаак
К сожалению, это больше не работает в более поздних версиях Pyth.
Исаак
Должен ли этот совет быть удален как один из других устаревших советов? Если нет, то, возможно, следует указать, к какой версии относится данный совет.
mbomb007
@ mbomb007 Я хотел найти версию, но мне было лень. Я удалю его, если вы думаете, что так будет лучше, пока я его не найду.
FryAmTheEggman
@FryAmTheEggman Я думаю, это зависит от вас, так как в заголовке написано, что это не поддерживается.
mbomb007
5

Распаковка двухэлементных кортежей с F

Скажем, у вас есть кортеж из 2 элементов J = (a, b), и вы хотите r(a,b), для некоторой функции 2 арности r.

Наивный способ сделать это rhJeJ.

Необычный способ сделать это r.*Jс помощью оператора распаковки.

Действительно причудливый способ сделать это rFJ, используя оператор сгиба.

isaacg
источник
это все еще можно использовать .uдля этого? .uкажется, кумулятивное снижение сейчас.
Ven
.u ->. * это было изменение, которое было сделано некоторое время назад, но никогда не обновлялось.
Исаак
4

Используйте короткие арифметические функции

h: Кроме возврата первого элемента списка, он увеличивает число, например, hTоценивает до 11. Короче чем +1T.

t: Это уменьшает число (кроме возврата конца списка), например, tTоценивает в 9. Короче чем -T1.

y: Это удваивает число, например, yTоценивает 20, короче *T2или +TT.

Jakube
источник
4

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

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

Два примера:

  • Создайте список из 8 нулей.

    mZ8 вместо *8]Z

  • Создайте список из 5 случайных чисел от 0 до 9:

    mOT5 вместо V5~Y]OT)

    Второй автоматически назначает список Y(ну, фактически он добавляет к Y), но даже =YmOTU5короче.

Jakube
источник
4

Неявный Q в EOF

Это новое изменение, на сегодняшний день.

Qпеременная, которая автоматически инициализируется для оцениваемого ввода. Он неявно добавляется в конец программы Pyth столько раз, сколько необходимо, чтобы заставить arity работать. Чтобы увидеть пример того, как использовать это для игры в гольф, скажем, мы хотим вычислить функцию Collatz для ввода.

Кратчайший способ написать это так:

@,/Q2h*3QQ

Однако, так как Qs неявны в конце файла, мы можем просто написать:

@,/Q2h*3

Экономия 2 байта.

Обратите внимание, что функции с необязательными аргументами не будут заполнены этими аргументами. Например, c"12 12"не будет иметь неявного Q, поскольку cтребуется только 1 аргумент.

isaacg
источник
3

Используйте уменьшение, чтобы применить функцию повторно.

Предположим, вам нужно установить переменную для какой-либо функции и повторить ее определенное количество раз. Возьмем, к примеру, проблему поиска числа 100 позже в последовательности Коллатца из входных данных. Самый короткий способ найти следующее число в последовательности, если это начальное число Q, это

@,/Q2h*Q3Q

Самый очевидный способ применить это 100 раз и напечатать результат будет

V100=Q@,/Q2h*Q3Q;Q

Выполните 100 циклов, обновляя значение Q каждый раз, затем завершите цикл и напечатайте Q.

Вместо этого мы можем использовать функцию Reduce, которая игнорирует переменную sequence ( H).

u@,/G2h*G3GU100Q

Это на 2 символа короче. Это на 3 символа короче, если вы пытаетесь выполнить цикл столько раз, сколько элементов в последовательности.

isaacg
источник
3

Есть обычно более короткие альтернативы любому

Когда вы хотите узнать, удовлетворяет ли какая-либо последовательность из условия, вы обычно используете .Em. Например, если вы хотите узнать, есть ли в списке больше или равно 5:

.Emgd5Q

Но, если это будет только правда / ложь, а не правда / ложь, smэто сработает, так как сумма работает на bools.

smgd5Q

Мы можем даже сделать один короче, с помощью filter:

fgT5Q

Последний выглядит действительно ужасно.

Для .All единственное, о чем я могу думать, это использовать противоположное условие и отменить его для сохранения одного символа .Am:

!f<T5Q
Maltysen
источник
3

Посмотрите на все параметры потока управления

петли:

F: Для цикла. Так же, как у Питона.

V: Для цикла в диапазоне. Ни переменная, ни диапазон не должны указываться, поэтому на 2 символа короче.

W: Пока цикл. Так же, как у Питона.

#: Бесконечный цикл while. Побег с ошибкой или явным разрывом. Только try ... exceptфункция теперь в Pyth.

Функции:

DОбщее определение. Так же, как Python.

L: 1 аргумент, без функции присваивания, как лямбда в Python, но с именем. RНе обязательно указывать имя функции, имя переменной и return ( ), поэтому на 3 символа короче.

Функциональное программирование:

f: Filter - выбрать элементы входной последовательности, которые возвращают truey на входную лямбду.

f: Первое целое число, большее или равное входному значению, которое дает истинный результат фильтра.

m: Карта - преобразовать элементы входной последовательности, используя входную лямбду.

u: Уменьшить - сложить входную последовательность на входной лямбде, инициализируя аккумулятор в третий аргумент.

o: Порядок - старые элементы входной последовательности, использующие в качестве ключа лямбда-ввод.

Как правило, для каждой конкретной проблемы будет несколько возможностей, и только написав тестовые решения с каждым из них, вы сможете определить, какая из них самая короткая.

isaacg
источник
.xв последнее время может использоваться для блоков try-кроме.
mbomb007
@ mbomb007 есть ли способ пренебречь, кроме блока, я имею в виду, это можно оставить пустым? Для экс: .x{some_statments}{except_block - can this be empty}.
Гурупад Мамадапур
@GurupadMamadapur # ... Bможно использовать таким образом, если вы не в выражении
isaacg
3

Переключение двух элементов в списке

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

TMP-переменный подход

При подготовке мы определяем список Yи заполняем его некоторыми числами. Цель состоит в том, чтобы переключить второй и третий элемент.

=Y[1 3 5 3 6 7)AGH,1 2

Мы просто присваиваем переменную tmp J = Q[G], делаем первое назначение списка, Y[G] = Y[H]а затем второе последнее назначение Y[H] = J. Хитрость заключается в том, чтобы вкладывать два списка назначений, поэтому вам не нужно подавлять печать и не использовать дважды ссылку на Y.

J@YGXXYG@YHHJ

вместо

J@YG XYG@YHXYHJ

Переводящий подход

Если элементы, которые вы хотите переключить, являются уникальными в списке, используйте этот подход. Это действительно коротко. Поэтому на этот раз мы переключаем первый и третий элемент (значения 1и 5являются уникальными).

=Y[1 3 5 3 6 7)K,Z2

Это использует функциональность перевода списка:

XYm@YdK)

Этот перевод заменяет каждый элемент Y[0]на Y[1]и каждый Y[1]на Y[0]. Так что, если значения не уникальны, случаются плохие вещи. Например, K,1 2приводит к [1, 5, 3, 5, 6, 7].

Обратите внимание, что закрывающие скобки являются необязательными, если оператор является последним в вашем коде.

Jakube
источник
3

Отладка с помощью <newline>

Если ваш код написан в стиле императивного программирования, его довольно легко отладить, так как вы можете легко напечатать промежуточные результаты. ( постоянная ссылка )

FN.:Q2                loop
      =Y+-Y-FNhN      some random command
                Y     print intermediate result
                 ;Y   end for loop and print result

Но большое количество программ Pyth использует элементы функционального программирования, такие как map, filter и Reduce, которые не позволяют такую ​​простую печать. Но это все еще возможно, используя \nкоманду.

Тот же код с использованием u(уменьшить) будет: ( постоянная ссылка )

u        .:Q2Y   reduce .:Q2, start with G = Y
 +-G-FHhH        random command

Если вы хотите напечатать промежуточные значения, просто вставьте \n: ( постоянная ссылка )

u         .:Q2Y   reduce
   \nG             print(G)
 +-\nG-FHhH        random command

\naпечатает aна новую строку и возвращает a. Таким образом, вы можете вставить его куда угодно, не беспокоясь об изменении функциональности программы.

Jakube
источник
В настоящее время вы можете использовать для этого новую строку, которая также печатает новую строку.
PurkkaKoodari
@ Pietu1998 Да, я использую это все время. Время обновить пост.
Якуб
3

Нахождение максимум двух целых

g#

Например, предположим, у вас есть J=5и K=12. Тогда g#JK= 12 и g#KJ= 12.

Это было обнаружено @ Pietu1998, который выразил это так:

Не уверен, что кто-то уже нашел его, но есть классный способ сделать max (A, B) за 2 байта, нет необходимости использовать 3 для eS,AB. g#ABделает то же самое. (Тем не менее, это очень неэффективно, так как он повторяет макс. (1, A-B + 1) раз. Оптимизация заключается в том, чтобы число, вероятно, было больше как B.)

isaacg
источник
@Jakube Это правда. Я явно что-то напутал, набирая это в чате.
PurkkaKoodari
2

joinМетод Пита

joinМетод в Python может быть часто немного раздражает, так как он включается только строки. Пифс joinболее щедрый. По умолчанию все объекты преобразуются в строки.

Например, jkUTдает 0123456789или jb["abc"4,5\f]7дает

abc
4
(5, 'f')
[7]
Jakube
источник
Недавно была добавлена ​​еще больше функций преобразования в строку - первый аргумент также приведен к строке, например j2\a\b->"a2b"
isaacg
1

Говорить, является ли номер целым числом

Аккуратный трюк использует Invariant, чтобы определить, является ли число целым числом как таковым:

sI

Это проверяет, не меняется ли число, когда вы его усекаете, что не будет, если это целое число.

Например, вы можете использовать это как идеальный квадратный чек:

sI@Q2
Maltysen
источник
1

Используйте упакованный Pyth

Packed Pyth - это новый «язык программирования», который точно такой же, как Pyth, за исключением того, что он использует 7 бит на символ вместо 8 бит на символ.

Чтобы использовать его, клонируйте хранилище pyth . Файл packed-pyth.pyпереводчик.

Скажи твой код "Hello, world!.

Сначала поместите это в файл: echo -n '"Hello, world!' > code.pyth

Затем упакуйте код Pyth в упакованный файл Pyth: python3 packed-pyth.py -p code.pyth code.ppyth

Наконец, запустите упакованный код Pyth: python3 packed-pyth.py code.ppyth

При запуске кода вы можете указать -dфлаг, чтобы увидеть, какой код Pyth на самом деле выполняется, и вы можете предоставить ввод в качестве второго аргумента командной строки после файла, содержащего код.

Потенциал роста:

  • Код короче на 1/8.

Даунсайд:

  • Только ASCII.

  • Нет интерактивного ввода.

  • Полные параметры отладки недоступны.

  • Хуже сообщения об ошибках.

isaacg
источник
1
как мы сделали для безопасного режима, можем ли мы переместить его во флаг?
Maltysen
Это потрясающе, кстати: D
Maltysen
@ Maltysen Я думаю, что это увеличило бы счет байтов на один.
Исаак
Разве Pyth не может быть упакован дальше, поскольку он использует только печатный ASCII?
lirtosiast
1

Тестирование делимости с использованием Iи GCD

Отказ от ответственности: это работает только для неотрицательных целых чисел.

Чтобы проверить, делятся ли два неотрицательных целых числа, вы можете сделать следующее:

iI<divisor><dividend>

Если a делится на b и a ≥ b ≥ 0 , то gcd (a, b) = b .

Это не обязательно экономит байты !%<dividend><divisor>, но может принести вам экономию, потому что:

  • Возможно, вы сможете настроить неявные вещи в конце программы Pyth (например, отбрасывание Q) при работе с дивидендом.
  • Вы можете использовать его как <pfn>, так как это отдельная функция.
  • Он обрабатывает по модулю 0.

Попробуй!

Мистер Xcoder
источник
Еще одно преимущество: iIэто функция сама по себе, а !%нет, так что вы можете использовать ее в качестве функции префикса.
Эрик Outgolfer
@EriktheOutgolfer Спасибо, добавил в список преимуществ :)
Mr. Xcoder
0

Присвоение переменной функции, применяемой к ней

Если у вас есть функция arity 1, и вы хотите применить ее к переменной и применить к себе, вы можете использовать следующий синтаксис:

=<function><variable>

Вместо:

=<variable><function><variable>

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

=hZ

Который сохраняет один байт =ZhZ.

Мистер Xcoder
источник