Wskazówki dotyczące gry w golfa w Pyth

46

Pyth to proceduralny język programowania zainspirowany Pythonem, stworzony przez użytkownika PPCG isaacg .

Jakie masz ogólne wskazówki na temat gry w golfa w Pyth? Szukam pomysłów, które można by zastosować do ogólnych problemów z golfem, które są przynajmniej nieco specyficzne dla Pytha.

Poproszę jedną wskazówkę na odpowiedź.

isaacg
źródło

Odpowiedzi:

25

Najpierw napisz kod w Pythonie

Pyth jest tak podobny do Pythona, że ​​tłumaczenie Pythona na język Pyth jest dość łatwe. Ponieważ jednak Pyth jest językiem zawierającym jedną literę na polecenie, czasami trudno jest napisać prosty Pyth. Pisząc najpierw w Pythonie, nie trzeba się nad tym zastanawiać (ponieważ Python jest dość łatwym językiem do kodowania).

Justin
źródło
1
Możesz także wspomnieć, że nadal możesz używać składni Pythona w Pyth, więc możesz konwertować poszczególne części programu lub po prostu używać Pythona, jeśli to konieczne. (Tak jak tutaj zrobiłeś )
FryAmTheEggman
@ mbomb007 Pobierz interpreter Pyth i przeczytaj dokumenty. To jedyny znany mi sposób pisania programu w języku Pyth.
Justin
@ mbomb007 Przepraszamy; w ten sposób nauczyłem się pisać Pyth (przeglądając kod źródłowy). Zasadniczo nie ma dokumentacji dotyczącej Pytha; w zasadzie musisz nauczyć się składni metodą prób i błędów.
Justin
22

Poznaj swoje zmienne

Pyth ma 3 kategorie zmiennych: zmienne ogólne wstępnie zainicjowane, zmienne wstępnie zainicjowane na podstawie danych wprowadzonych przez użytkownika oraz zmienne, które domyślnie generują przypisanie przy pierwszym użyciu.

Zmienne ogólne:

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

Zmienne inicjowane przez dane wejściowe:

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

Zauważ, że te inicjalizacje będą uruchamiane w danym programie tylko wtedy, gdy powiązana zmienna zostanie użyta poza ciągiem w kodzie. Ponadto kolejność jest Qwtedy z, gdy oba są używane.

Przypisanie zmiennych pierwszego użycia:

Ja K. Jeśli chcesz zainicjować je obie na tę samą wartość, możesz to zrobić za pomocą wyrażenia takiego jak KJ0, które jest równoważne dłuższemu J0K0.

isaacg
źródło
18

Skorzystaj z jeszcze nowszego tłumacza internetowego, aby sprawdzić swoje odpowiedzi.

Pamiętaj, że jest to nowe oprogramowanie, więc może być wadliwe. Proszę zgłaszać mi wszelkie problemy.

isaacg
źródło
2
Niesamowite! Nie mogłem tego znaleźć w Google, tylko tego potrzebowałem!
theonlygusti
12

Ciągi na końcu wiersza nie wymagają cudzysłowów końcowych. Na przykład:

"Hello, world!

jest całkowicie poprawnym programem Hello World.

isaacg
źródło
Całkiem oczywiste, to pierwszy wynik Google dla „języka programowania Pyth”. Czy stworzyłeś własną stronę w esolangach?
theonlygusti
3
@ thehelylygusti Tak, zrobiłem. Ponadto nie był to pierwszy wynik z października ubiegłego roku.
isaacg,
9

Użyj Cdo kompresji bazy

Jest to w rzeczywistości nieudokumentowane, C na łańcuchu tak naprawdę nie jest bezpośrednim chr -> int, ale zamiast tego base 256 -> base 10 (to samo na łańcuchach znaków). Jest to bardzo pomocne w kompresji int, możemy użyć tego skryptu do kompresji:

sCMjQ256

Weźmy 12345678910, to powoduje ßÜ>(niektóre tam niedrukowalne).

Również z tablicą liczb całkowitych można łączyć je i dużymi łańcuchami, konwertując do punktów kodowych i traktując jako podstawową liczbę 128.

Innym zastosowaniem C, dzięki @xnor za pokazanie mi tego, jest tworzenie dowolnej liczby. Naiwny sposób to:

^TT

Ale możemy zrobić jeden bajt lepiej z:

CG

ta baza 256 dekonwertuje cały alfabet. Wyniki 156490583352162063278528710879425690470022892627113539022649722= ~ 1.56e62.

Maltysen
źródło
Dodano do dokumentu teraz.
isaacg,
8

Istnieje teraz samouczek online dla Pyth.

Pełna dokumentacja zostanie dodana później.

Maltysen
źródło
8

Użyj krótkich funkcji funkcjonalnych ... err ...

Gdy argument lambda do maplub reducepo prostu zastosuje jedną operację do argumentów, możesz użyć krótkich formularzy Mi F. fMxjest równoważne mfdxi fFxjest tym samym, co .UfbZx. Załóżmy na przykład, że bierzemy listę liczb jako dane wejściowe i wyjściowe, z których każda jest zwiększana. Pierwszym podejściem może być:

mhdQ

Można to jednak przepisać jako:

hMQ

Podobnie jest reducez F. Na przykład powiedzmy, że istnieje wyzwanie obliczenia iloczynu listy liczb całkowitych. Ponownie, pierwszą próbą może być:

.U*bZQ

Jednakże, z F, które mogą być skrócone do:

*FQ

Goli trzy bajty ... nieźle!

kirbyfan64sos
źródło
I nie potrzebujesz Q, ponieważ jest on uzupełniany, gdy funkcja nie zawiera danych wejściowych, co czyni ją*F
Stan Strum
7

Aktualizuj swoją implementację języka Pyth.

Dość regularnie poprawiam Pyth, usuwając mniej przydatne funkcje i dodając bardziej przydatne, więc miej oko na nowości i regularnie aktualizuj swoją kopię implementacji.

Niektóre ostatnio dodane funkcje: (stan na 19.10.14)

y: Działa jak *2na liczbach i jako lista wszystkich podzbiorów na ciągach i listach. Na przykład:

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

f: fzwykle jest poleceniem filter. Teraz, gdy zostanie wywołany z liczbą jako drugim argumentem, przefiltruje nieskończoną sekwencję, zaczynając od tej liczby i zliczając je, a następnie zwróci pierwszy element wynikowej sekwencji.

Na przykład, oto kod, aby znaleźć najmniejszą liczbę pierwszą ponad miliard:

pyth -c 'f!tPT^T9'
1000000007
isaacg
źródło
Wyglądają jak przydatne dodatki, ale czego możesz użyć zamiast starego yz? mvdczdnie może być najkrótszą drogą ...
Dennis,
1
@Dennis Wyrzuciłem stary, yponieważ nie sądzę, że Pyth musi mieć wiele bardzo łatwych do przeanalizowania formatów wejściowych, tylko jeden, np. Format Python. Tak, tak, myślę mvdczd, że niestety trzeba będzie to zrobić.
isaacg,
@Dennis Problem rozwiązany, właśnie dodałem to do rpakietu przetwarzania ciągów.
isaacg
rwygląda całkiem użytecznie.
Dennis
@isaacg Przepraszam, jeśli jest to nie na temat, ale zastanawiam się, jak użyć operacji @rootowania w Fdr1 + 1 @ Q2Iq% Qd0d, aby zrobić kalkulator czynnikowy. Kiedy próbuję go użyć, domyślnie ma indexznaczenie. Czy jest jakiś sposób obejścia tego zachowania?
StardustGogeta
5

Nazwane argumenty w funkcjach (nie są już obsługiwane)

Czasami wartości domyślne w funkcjach mogą być przydatne do gry w golfa. Pyth faktycznie to obsługuje (ku mojemu zaskoczeniu). Na przykład:

DC=Z1RZ;C;C5

Wydrukuje:

1
5

Możesz także użyć J i K, aby zapisać postacie, wykonując następujące czynności:

DgJ1K1R+JKg;g2;g2 3

drukuje:

2
3
5

Jest to zwykle przydatne w przypadku algorytmów rekurencyjnych.

To już nie działa, ale zostawiłem to tutaj na wypadek, gdyby ktoś chciał grać w golfa przy użyciu starej wersji Pytha.

FryAmTheEggman
źródło
16
Wow - nawet nie zdawałem sobie sprawy, że Pyth to obsługuje i napisałem język!
isaacg
Niestety nie działa to już w nowszych wersjach Pyth.
isaacg
Czy tę wskazówkę należy usunąć jak jedną z nieaktualnych porad? Jeśli nie, być może należy zaznaczyć wersje, których dotyczy ta wskazówka.
mbomb007,
@ mbomb007 Chciałem znaleźć wersję, ale byłem zbyt leniwy. Usunę go, jeśli uważasz, że tak będzie lepiej, dopóki go nie znajdę.
FryAmTheEggman
@FryAmTheEggman Myślę, że to zależy od ciebie, ponieważ w tytule napisano, że nie jest obsługiwany.
mbomb007,
5

Rozpakowanie krotek 2-elementowych za pomocą F

Powiedzmy, że masz krotkę 2-elementową J = (a, b)i chcesz r(a,b), dla jakichś 2 funkcji arity r.

Naiwnym sposobem na to jest rhJeJ.

Fantazyjnym sposobem na to jest r.*Jużycie operatora rozpakowywania.

Naprawdę wymyślnym sposobem na to jest rFJużycie operatora składania.

isaacg
źródło
czy nadal można z tego korzystać .u? .uwydaje się teraz kumulować się teraz.
Ven
.u ->. * była to zmiana, która została wprowadzona jakiś czas temu, ale nigdy nie została zaktualizowana.
isaacg
4

Użyj krótkich funkcji arytmetycznych

h: Oprócz zwracania pierwszego elementu listy, zwiększa liczbę, np. hTOcenia na 11. Krótszy niż +1T.

t: Zmniejsza liczbę (inną niż zwrócenie ogona listy), np. tTOcenia na 9. Krótszy niż -T1.

y: Podwaja liczbę, np. yTOcenia na 20, krótszy niż *T2lub +TT.

Jakube
źródło
4

Służy mapdo generowania list

Jest to w zasadzie odpowiednik fantazyjnej listy python. Użyj istniejącej listy lub zakresu, aby iterować i mapować każdą wartość, nawet jeśli wartość nie ma znaczenia.

Dwa przykłady:

  • Wygeneruj listę 8 zer.

    mZ8 zamiast *8]Z

  • Wygeneruj listę 5 liczb losowych od 0 do 9:

    mOT5 zamiast V5~Y]OT)

    Drugi automatycznie przypisuje listę do Y(no cóż, faktycznie dołącza do Y), ale nawet =YmOTU5jest krótszy.

Jakube
źródło
4

Implikowane Q w EOF

To nowa zmiana na dzień dzisiejszy.

Qjest zmienną, która jest inicjalizowana automatycznie dla analizowanego wejścia. Jest on domyślnie dołączany na końcu programu Pyth, tyle razy, ile jest to konieczne, aby arity działało. Aby zobaczyć przykład wykorzystania tego do gry w golfa, powiedzmy, że chcemy obliczyć funkcję Collatz wejścia.

Najkrótszy sposób na napisanie tego jest następujący:

@,/Q2h*3QQ

Ponieważ jednak Qs są niejawne na końcu pliku, możemy po prostu napisać:

@,/Q2h*3

Zapisywanie 2 bajtów.

Zauważ, że funkcje z niepotrzebnymi argumentami nie będą wypełnione tymi argumentami. Na przykład c"12 12"nie będą miały niejawnego charakteru Q, ponieważ cwymaga tylko 1 argumentu.

isaacg
źródło
3

Użyj zmniejszania, aby wielokrotnie stosować funkcję.

Załóżmy, że musisz ustawić zmienną na jakąś funkcję samą w sobie i powtórzyć określoną liczbę razy. Weźmy na przykład problem ze znalezieniem liczby 100 później w sekwencji Collatza na podstawie danych wejściowych. Najkrótszym sposobem znalezienia następnego numeru w sekwencji, jeśli jest numerem początkowym Q, jest

@,/Q2h*Q3Q

Najbardziej oczywistym sposobem na zastosowanie tego 100 razy i wydrukowanie wyniku byłby

V100=Q@,/Q2h*Q3Q;Q

Zapętl 100 razy, za każdym razem aktualizując wartość Q, a następnie zakończ pętlę i wypisz Q.

Zamiast tego możemy użyć funkcji redukcji, która ignoruje zmienną sekwencji ( H).

u@,/G2h*G3GU100Q

To jest 2 znaki krótsze. Jest o 3 znaki krótszy, jeśli próbujesz zapętlić tyle razy, ile jest elementów w sekwencji.

isaacg
źródło
3

Zwykle istnieją krótsze alternatywy dla Any

Gdy chcesz sprawdzić, czy jakakolwiek sekwencja spełnia warunek, zwykle byś użył .Em. Na przykład, jeśli chcesz dowiedzieć się, czy któryś z listy jest większy lub równy 5:

.Emgd5Q

Ale jeśli to musi być tylko prawda / falsey, a nie prawda / fałsz, smdziałałoby, ponieważ suma działa na boolach.

smgd5Q

Możemy zrobić nawet jeden krótszy, z filter:

fgT5Q

Ten ostatni wygląda jednak naprawdę brzydko.

Dla mnie .Ajedyne, co mogę wymyślić, to zastosować przeciwny warunek i zanegować go dla jednego znaku oprócz .Am:

!f<T5Q
Maltysen
źródło
3

Spójrz na wszystkie opcje przepływu sterowania

Pętle:

F: Dla pętli. Podobnie jak Python.

V: Dla pętli w zakresie. Nie należy podawać ani zmiennej, ani zakresu, więc 2 znaki krótsze.

W: Podczas pętli. Podobnie jak Python.

#: Nieskończona pętla while. Escape z błędem lub wyraźną przerwą. Teraz dostępna tylko try ... exceptw Pyth.

Funkcje:

D: Ogólne określenie. Tak jak Python.

L: 1 argument, brak funkcji przypisania, jak lambda Pythona, ale o nazwie. Nazwa funkcji, nazwa zmiennej i zwrot (R ) nie muszą być podawane, więc 3 znaki krótsze.

Programowanie funkcjonalne:

f: Filtruj - wybierz elementy sekwencji wejściowej, które zwracają wartość true na wejściowej lambda.

f: Pierwsza liczba całkowita większa lub równa wartości wejściowej, która daje prawdziwy wynik filtru.

m: Mapa - transformuj elementy sekwencji wejściowej za pomocą wejściowej lambda.

u: Zmniejsz - złóż sekwencję wejściową na wejściowej lambda, inicjując akumulator do trzeciego argumentu.

o: Order - starsze elementy sekwencji wejściowej, w których kluczem jest wejściowa lambda.

Zazwyczaj istnieje wiele możliwości dla danego problemu i tylko pisząc rozwiązania testowe dla każdego z nich, możesz dowiedzieć się, który jest najkrótszy.

isaacg
źródło
.xmoże być później używany do bloków try-oprócz.
mbomb007,
@ mbomb007 czy istnieje sposób na zaniedbanie oprócz bloku, to znaczy, czy można to pozostawić puste? Dla ex: .x{some_statments}{except_block - can this be empty}.
Gurupad Mamadapur
@GurupadMamadapur # ... Bmoże być używany w ten sposób, jeśli nie jesteś w wyrażeniu
isaacg
3

Przełączanie dwóch elementów na liście

Przełączanie dwóch elementów może być dość kosztownym zadaniem. Oto dwa podejścia, których chcesz użyć.

Podejście zmienne Tmp

W przygotowaniu definiujemy listę Yi wypełniamy ją liczbami. Celem jest zmiana drugiego i trzeciego elementu.

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

Po prostu przypisujemy zmienną tmp J = Q[G], wykonujemy pierwsze przypisanie listy, Y[G] = Y[H]a następnie drugie ostatnie przypisanie Y[H] = J. Sztuczka polega na zagnieżdżeniu dwóch przypisań do listy, dzięki czemu nie trzeba pomijać drukowania i nie trzeba używać polecenia refer to dwa razy Y.

J@YGXXYG@YHHJ

zamiast

J@YG XYG@YHXYHJ

Podejście do tłumaczenia

Jeśli elementy, które chcesz przełączyć, są unikalne na liście, użyj tego podejścia. To jest naprawdę krótkie. Tym razem przełączamy pierwszy i trzeci element (wartości 1i 5są unikalne).

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

Korzysta z funkcji tłumaczenia listy:

XYm@YdK)

Ten tłumaczenia zastępuje każdy element Y[0]z Y[1]I każdy Y[1]z Y[0]. Jeśli więc wartości nie są unikalne, zdarzają się złe rzeczy. Na przykład K,1 2wyniki w[1, 5, 3, 5, 6, 7] .

Zauważ, że nawiasy zamykające są opcjonalne, jeśli instrukcja jest ostatnią w kodzie.

Jakube
źródło
3

Debugowanie za pomocą <newline>

Jeśli kod jest napisany w trybie programowania imperatywnego, debugowanie jest dość łatwe, ponieważ można łatwo wydrukować wyniki pośrednie. (bezpośredni link )

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

Ale duża liczba programów Pyth wykorzystuje elementy programowania funkcjonalnego, takie jak mapowanie, filtrowanie i redukcja, które nie pozwalają na tak prosty wydruk. Ale nadal jest to możliwe przy użyciu\n polecenia.

Ten sam kod używający u(zmniejsz) to: (bezpośredni link )

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

Jeśli chcesz wydrukować wartości pośrednie, po prostu wstaw \n: (bezpośredni link )

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

\nadrukuje ana nowej linii i zwraca a. Możesz więc wstawić go w dowolne miejsce, nie martwiąc się o zmianę funkcjonalności programu.

Jakube
źródło
Możesz teraz użyć do tego nowej linii, która również drukuje nową linię.
PurkkaKoodari
@ Pietu1998 Tak, używam go cały czas. Czas zaktualizować post.
Jakube,
3

Znajdowanie maksymalnie dwóch liczb całkowitych

g#

Załóżmy na przykład, że masz J=5i K=12. Następnie g#JK= 12, a także g#KJ= 12.

Zostało to odkryte przez @ Pietu1998, który ujął to w następujący sposób:

Nie jestem pewien, czy ktoś go już znalazł, ale istnieje fajny sposób na zrobienie maksimum (A, B) w 2 bajtach, nie trzeba używać 3 dla eS,AB. g#ABrobi to samo. (Jest to jednak bardzo nieefektywne, ponieważ zapętla maksymalnie (1, A-B + 1) razy. Optymalizacja polega na umieszczeniu liczby, która prawdopodobnie będzie większa jako B.)

isaacg
źródło
@Jakube To prawda. Najwyraźniej coś myliłem podczas pisania tego na czacie.
PurkkaKoodari
2

joinMetoda Pytha

joinMetoda w Pythonie często może być trochę irytujące, ponieważ tylko dołącza ciągi. Pyth's joinjest bardziej hojny. Domyślnie przekształca wszystkie obiekty w ciągi.

Np. jkUTDaje 0123456789lub jb["abc"4,5\f]7daje

abc
4
(5, 'f')
[7]
Jakube
źródło
Ostatnio dodano jeszcze więcej funkcji przekształcania w ciąg - pierwszy argument jest również wymuszany na łańcuch, np. j2\a\b->"a2b"
isaacg
1

Mówienie, jeśli liczba jest liczbą całkowitą

IDobrą sztuczką jest użycie nvariant, aby stwierdzić, czy liczba jest liczbą całkowitą jako taką:

sI

To sprawdza, czy liczba nie zmienia się po obcięciu, co nie zmieni się, jeśli będzie to liczba całkowita.

Na przykład możesz użyć tego jako idealnego kwadratu:

sI@Q2
Maltysen
źródło
1

Użyj spakowanego Pytha

Spakowany Pyth to nowy „język programowania”, który jest dokładnie taki sam jak Pyth, z tym wyjątkiem, że używa 7 bitów na znak zamiast 8 bitów na znak.

Aby go użyć, sklonuj repozytorium pyth . Plik packed-pyth.pyjest tłumaczem.

Powiedz, że masz kod "Hello, world!.

Najpierw umieść go w pliku: echo -n '"Hello, world!' > code.pyth

Następnie spakuj kod Pyth do spakowanego pliku Pyth: python3 packed-pyth.py -p code.pyth code.ppyth

Na koniec uruchom spakowany kod Pyth: python3 packed-pyth.py code.ppyth

Podczas uruchamiania kodu możesz podać -dflagę, aby zobaczyć, jaki jest faktycznie uruchamiany kod Pyth, a także podać dane jako drugi argument wiersza poleceń po pliku zawierającym kod.

Do góry nogami:

  • Kod jest krótszy o 1/8.

Minusem:

  • Tylko ASCII.

  • Brak interaktywnego wejścia.

  • Opcje pełnego debugowania nie są dostępne.

  • Gorsze raportowanie błędów.

isaacg
źródło
1
tak jak w przypadku trybu bezpiecznego, czy możemy przenieść go do flagi?
Maltysen
To jest niesamowite btw: D
Maltysen
@Maltysen Myślę, że to zwiększy wynik bajtu o jeden.
isaacg
Czy Pyth nie może być zapakowany dalej, ponieważ używa tylko ASCII do wydruku?
lirtosiast
1

Testy podzielności za pomocą Ii GCD

Zrzeczenie się: Działa to tylko w przypadku liczb całkowitych nieujemnych.

Aby sprawdzić, czy dwie nieujemne liczby całkowite są podzielne, możesz wykonać następujące czynności:

iI<divisor><dividend>

Jeśli a jest podzielne przez b oraz a ≥ b ≥ 0 , to gcd (a, b) = b .

Niekoniecznie oszczędza bajtów !%<dividend><divisor> , ale może przynieść oszczędności, ponieważ:

  • Być może będziesz w stanie poprawić ukryte rzeczy na końcu programu Pyth (np. Upuszczanie Q) podczas pracy z dywidendą.
  • Możesz użyć go jako <pfn>, ponieważ jest to funkcja sama w sobie.
  • Obsługuje modulo przez 0.

Spróbuj!

Pan Xcoder
źródło
Jeszcze jedna zaleta: iIjest funkcją samą w sobie, podczas gdy !%nie jest, więc możesz użyć jej jako funkcji prefiksu.
Erik the Outgolfer,
@EriktheOutgolfer Dzięki, dodano do listy zalet :)
Mr. Xcoder
0

Przypisywanie zmiennej do funkcji zastosowanej do niej samej

Jeśli masz funkcję arity 1 i chcesz zastosować ją do zmiennej i zastosować do siebie, możesz użyć następującej składni:

=<function><variable>

Zamiast:

=<variable><function><variable>

Na przykład, jeśli chcesz zwiększyć zmienną Z, możesz:

=hZ

Co oszczędza jeden bajt =ZhZ.

Pan Xcoder
źródło