Поради щодо гольфу в Pyth


46

Pyth - натхненна Python мова процедурного програмування, створена користувачем PPCG isaacg .

Які загальні поради щодо гольфу в Pyth? Я шукаю ідеї, які можна застосувати для кодування проблем із гольфом взагалі, які принаймні дещо характерні для Pyth.

Будь ласка, одна порада на відповідь.

Відповіді:


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.


18

Скористайтеся ще новішим онлайн-перекладачем, щоб перевірити свої відповіді.

Зауважте, що це нове програмне забезпечення, тому воно може бути помилковим. Будь ласка, повідомте мені про будь-які проблеми.


2
Дивовижно! Я не міг цього знайти в Google, просто те, що мені потрібно!
theonlygusti

12

Рядки в кінці рядка не потребують кінцевих лапок. Наприклад:

"Hello, world!

є цілком дійсною програмою Hello World.


Насправді очевидно, що це перший результат Google для "мови програмування Pyth". Ви створили власну сторінку на esolangs?
theonlygusti

3
@theonlygusti Так, я. Крім того, це був не перший результат минулого жовтня.
isaacg

9

Використовувати Cдля стиснення основи

Це насправді недокументовано, C на рядку насправді не є прямим chr -> int, а натомість базою 256 -> базою 10 (що таке саме на одних рядках char). Це дуже корисно для стиснення int, ми можемо використовувати цей сценарій для стиснення:

sCMjQ256

Візьміть 12345678910, це призводить до ßÜ>(деякі недруковані матеріали там).

Також з масивом ints ви можете об'єднати їх і з великими рядками, перетворившись у кодові точки та розглядаючи як базове 128 число.

Ще одне використання C, дякую @xnor, що він мені це показав, - це довільна велика кількість. Наївний спосіб:

^TT

Але ми можемо зробити один байт краще за допомогою:

CG

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


Додано в doc зараз.
isaacg


8

Використовуйте короткі функціональні ... помилки ... функції

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

mhdQ

Однак це можна переписати як:

hMQ

Схожа річ стосується і reduceс F. Наприклад, скажіть, що існує завдання скласти обчислення добутку списку цілих чисел. Знову ж таки, перша спроба може бути:

.U*bZQ

Однак, Fце може бути скорочено до:

*FQ

Голить три байти ... непогано!


І вам це не потрібно Q, оскільки він доповнюється, коли функції відсутній вхід, що робить його*F
Stan Strum

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

Вони виглядають як корисні доповнення, але що можна використовувати замість старих yz? mvdczdне може бути найкоротшим шляхом ...
Денніс

1
@Dennis Я викинув старий, yтому що не думаю, що Pyth потребує декількох надлегко розібраних форматів введення, лише один, наприклад формат Python. Так, так, я думаю mvdczd, доведеться робити, на жаль.
isaacg

@Dennis Проблема вирішена, просто додав це до rнабору обробних рядків.
isaacg

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.


16
Нічого собі - навіть я не розумів, що Pyth це підтримує, і я написав мову!
isaacg

На жаль, це не працює більше в останніх версіях Pyth.
isaacg

Чи слід видалити цю пораду як один із інших застарілих підказок? Якщо ні, можливо, слід позначити, до якої версії (-ів) застосовується ця порада.
mbomb007

@ mbomb007 Я мав намір знайти версію, але я занадто лінивий. Буду видаляти його, якщо ви вважаєте, що краще так, поки я не знайду його.
FryAmTheEggman

@FryAmTheEggman Я думаю, це залежить від вас, оскільки в заголовку написано, що це не підтримується.
mbomb007

5

Розпакування 2 елемента кортежів за допомогою F

Скажіть, у вас є кортеж з двома елементами J = (a, b), і ви хочете r(a,b), щоб виконати деяку функцію 2 arity r.

Наївний спосіб це зробити rhJeJ.

Фантастичний спосіб зробити це - r.*Jвикористання оператора unpack.

Справді химерний спосіб зробити це - rFJза допомогою оператора складання.


це все-таки можна використовувати .uдля цього? .uздається, кумулятивне зменшення зараз.
Вен

.u ->. * ця зміна була внесена деякий час тому, але ніколи не оновлювалася.
isaacg

4

Використовуйте короткі арифметичні функції

h: Крім повернення першого елемента списку, він збільшує число, наприклад, hTоцінює до 11. Коротше +1T.

t: Це зменшення числа (крім повернення хвоста списку), наприклад, tTоцінюється до 9. Коротше -T1.

y: Це подвоює число, наприклад, yTоцінює на 20, менший від *T2або +TT.


4

Використовуйте mapдля створення списків

Це в основному еквівалент розуміння пітона піктограм. Використовуйте наявний список або діапазон, щоб повторити і відобразити кожне значення, навіть якщо значення не має значення.

Два приклади:

  • Створіть список з 8 нулів.

    mZ8 замість *8]Z

  • Створіть список з 5 випадкових чисел між 0 і 9:

    mOT5 замість V5~Y]OT)

    Другий автоматично призначає цей список Y(ну, власне, він додає Y), але навіть =YmOTU5коротший.


4

Неявний Q на EOF

Це нова зміна станом на сьогодні.

Q- це змінна, яка автоматично ініціалізується на оцінений вхід. Це неявно додається до кінця програми Pyth, стільки разів, скільки потрібно для того, щоб армія випрацювала. Щоб побачити приклад, як це використовувати для гольфу, скажімо, що ми хочемо обчислити функцію Collatz .

Найкоротший спосіб його написати:

@,/Q2h*3QQ

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

@,/Q2h*3

Збереження 2 байт.

Зауважте, що функції з необов’язковими аргументами не будуть заповнювати ці аргументи. Наприклад, c"12 12"не буде неявним Q, оскільки cпотрібен лише 1 аргумент.


3

Використовуйте зменшення, щоб застосувати функцію неодноразово.

Припустимо, вам потрібно встановити змінну на якусь функцію себе і повторити певну кількість разів. Візьмемо, наприклад, проблему пошуку числа 100 пізніше в послідовності Колалца з введення. Найкоротший спосіб знайти наступне число в послідовності, якщо це початкове число Q, є

@,/Q2h*Q3Q

Найбільш очевидний спосіб застосувати це 100 разів і надрукувати результат

V100=Q@,/Q2h*Q3Q;Q

Цикл 100 разів, оновлюючи значення Q кожен раз, потім закінчуйте цикл і друкуйте Q.

Натомість ми можемо використовувати функцію зменшення, яка ігнорує змінну послідовності ( H).

u@,/G2h*G3GU100Q

Це на 2 символи коротше. Це на 3 символи коротше, якщо ви намагаєтеся циклічно стільки разів, скільки є елементів у послідовності.


3

Зазвичай існують коротші альтернативи Any

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

.Emgd5Q

Але, якщо це потрібно лише бути truthy / falsey, а не true / false, він smби працював, оскільки сума працює на bools.

smgd5Q

Ми навіть можемо зробити один коротший, з filter:

fgT5Q

Останній виглядає по-справжньому потворно.

Щодо .All, єдине, про що я можу придумати, - це використовувати протилежну умову та заперечувати її для збереження одного знака .Am:

!f<T5Q

3

Подивіться на всі варіанти керуючого потоку

Петлі:

F: Для петлі. Так само, як і Python's.

V: Для циклу понад діапазон. Ні змінної, ні діапазону не повинні бути задані, тому на два символи коротше.

W: Поки петля. Так само, як і Python's.

#: Нескінченний цикл. Втеча з помилкою або явним розривом. Тільки try ... exceptособливість тепер Pyth.

Функції:

D: Загальне визначення. Так само, як і Python.

L: 1 аргумент, немає функції призначення, як лямбда Python, але з ім'ям. Ім'я функції, ім'я змінної та return ( R) не потрібно вказувати, тому 3 символи коротше.

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

f: Фільтр - виберіть елементи вхідної послідовності, які повертають правду на вхідну лямбда.

f: Перше ціле число більше або рівне вхідному, яке дає результат "фільтр".

m: Map - елементи перетворення послідовності введення за допомогою вхідної лямбда.

u: Зменшення послідовності введення в лямбда-введення, ініціалізація акумулятора до третього аргументу.

o: Порядок - старші елементи послідовності введення, використовуючи лямбда введення як ключ.

Зазвичай для будь-якої задачі буде кілька можливостей, і лише написавши тестові рішення з кожним із них, ви зможете зрозуміти, який найкоротший.


.xз недавніх пір можна використовувати для випробувань, крім блоків.
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].

Зауважте, що дужки, що закриваються, необов’язкові, якщо оператор є останнім у вашому коді.


3

Налагодження з <newline>

Якщо ваш код написаний в обов'язковому стилі програмування, його налагодити досить просто, оскільки ви можете легко надрукувати проміжні результати. ( постійна посилання )

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

Але велика кількість програм Pyth використовує елементи функціонального програмування, такі як карта, фільтр та зменшення, які не дозволяють настільки простого друку. Але це все-таки можливо, використовуючи \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. Таким чином, ви можете вставити його куди завгодно, не турбуючись про зміну функціональності програми.


Ви можете використовувати для цього новий рядок, який також друкує новий рядок.
PurkkaKoodari

@ Pietu1998 Так, я використовую його постійно. Час оновлення публікації.
Jakube

3

Знаходження максимум двох цілих чисел

g#

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

Це виявив @ Pietu1998, який висловив це так:

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


@Jakube Це правда. Я, мабуть, щось мішу, вводячи це в чат.
PurkkaKoodari

2

Pyth в joinметод

joinМетод в Python може бути часто трохи дратує, так як він включається тільки рядки. Піти join- щедріші. Він перетворює всі об'єкти в рядках за замовчуванням.

Напр. jkUTДає 0123456789або jb["abc"4,5\f]7дає

abc
4
(5, 'f')
[7]

Нещодавно було додано ще більше функцій перетворення на рядок - перший аргумент також примусовий до рядка, наприклад j2\a\b->"a2b"
isaacg

1

Скажіть, чи число є цілим числом

IОхайний трюк - це використовувати nvariant, щоб сказати, чи є число цілим числом як таким:

sI

Це перевіряє, чи не змінюється число, коли ви його усікаєте, чого не буде, якщо це ціле число.

Наприклад, ви можете використовувати це як ідеальну квадратну перевірку:

sI@Q2

1

Використовуйте Packed Pyth

Packed Pyth - це нова "мова програмування", яка точно така ж, як і Pyth, за винятком того, що вона використовує 7 біт на символ замість 8 біт на символ.

Для його використання клонуйте сховище pyth . Файл packed-pyth.pyє перекладачем.

Скажіть, ваш код є "Hello, world!.

Спочатку покладіть його у файл: echo -n '"Hello, world!' > code.pyth

Далі запакуйте код Pyth у файл Packed Pyth: python3 packed-pyth.py -p code.pyth code.ppyth

Нарешті, запустіть код Packed Pyth: python3 packed-pyth.py code.ppyth

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

Наверх:

  • Код коротший на 1/8.

Нижня сторона:

  • Тільки ASCII.

  • Немає інтерактивного введення.

  • Повні варіанти налагодження недоступні.

  • Гірше повідомлення про помилки.


1
як ми це зробили для безпечного режиму, чи можемо ми перенести його у прапор?
Мальтісен

Це дивовижне btw: D
Мальтісен

@Maltysen Я думаю, що це збільшить байт на одиницю.
isaacg

Неможливо Pyth упакувати далі, оскільки він використовує лише друкований ASCII?
lirtosiast

1

Тестування на роздільність за допомогою Iта GCD

Відмова від відповідальності: Це працює лише для невід’ємних цілих чисел.

Щоб перевірити, чи розділені два невід’ємні цілі числа, можна зробити наступне:

iI<divisor><dividend>

Якщо a ділиться на b і a ≥ b ≥ 0 , то gcd (a, b) = b .

Це не обов'язково зберігати байти !%<dividend><divisor>, але це може принести вам економію, оскільки:

  • Можливо, вам вдасться підправити неявні речі наприкінці програми Pyth (наприклад, випадання Q) під час роботи з дивідендом.
  • Ви можете використовувати його як a <pfn>, оскільки це функція сама по собі.
  • Він обробляє модуль 0.

Спробуй це!


Ще одна перевага: iIфункція сама по собі, тоді !%як ні, тому ви можете використовувати її як функцію префікса.
Ерік Аутгольфер

@EriktheOutgolfer Дякую, додано до переліку переваг :)
Містер Xcoder

0

Призначення змінної функції, застосованої до себе

Якщо у вас є функція arity 1, і ви хочете застосувати це до змінної та застосувати до себе, ви можете використовувати такий синтаксис:

=<function><variable>

Замість:

=<variable><function><variable>

Наприклад, якщо ви хочете збільшити змінну Z, ви можете зробити:

=hZ

Що економить один байт =ZhZ.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.