Suggerimenti per giocare a golf in Pyth


46

Pyth è un linguaggio di programmazione procedurale ispirato a Python, creato dall'utente isaacg di PPCG .

Quali consigli generali hai per giocare a golf in Pyth? Sto cercando idee che possano essere applicate ai problemi del codice golf in generale che siano almeno in qualche modo specifiche per Pyth.

Un consiglio per risposta, per favore.

Risposte:


25

Scrivi prima il codice in Python

Pyth è così simile a Python che è abbastanza facile tradurre i programmi Python in Pyth. Tuttavia, poiché Pyth è un linguaggio a lettera singola per comando, a volte è difficile scrivere direttamente Pyth. Scrivendo prima in Python, c'è meno da pensare alla volta (dal momento che Python è un linguaggio abbastanza facile da codificare).


1
Puoi anche menzionare che puoi ancora usare la sintassi di Python in Pyth, quindi puoi convertire parti del programma individualmente o semplicemente usare Python se necessario. (Come hai fatto qui )
FryAmTheEggman,

@ mbomb007 Scarica l'interprete Pyth e leggi i documenti. Questo è l'unico modo affidabile che conosco per scrivere un programma Pyth.
Giustino,

@ mbomb007 Siamo spiacenti; è così che ho imparato a scrivere Pyth (guardando attraverso il codice sorgente). Fondamentalmente non esiste documentazione su Pyth; fondamentalmente devi imparare la sintassi per tentativi ed errori.
Giustino,

22

Conosci le tue variabili

Pyth ha 3 categorie di variabili: variabili preinizializzate generiche, variabili preinizializzate in base all'input dell'utente e variabili che implicitamente generano un'assegnazione al primo utilizzo.

Variabili generiche:

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

Variabili di input inizializzate:

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

Si noti che queste inizializzazioni verranno eseguite in un determinato programma solo se la variabile associata viene utilizzata al di fuori di una stringa nel codice. Inoltre, l'ordine è Q, quindi z, se entrambi vengono utilizzati.

Assegnazione su variabili di primo utilizzo:

Je K. Se si desidera inizializzarli entrambi allo stesso valore, è possibile farlo con un'espressione come KJ0, che è equivalente al più lungo J0K0.


18

Usa l' interprete online ancora più recente per testare le tue risposte.

Si noti che questo è un nuovo software, quindi potrebbe essere difettoso. Si prega di segnalare eventuali problemi a me.


2
Eccezionale! Non sono riuscito a trovarlo con Google, proprio quello di cui avevo bisogno!
theonlygusti,

12

Le stringhe alla fine della riga non richiedono virgolette. Per esempio:

"Hello, world!

è un programma Hello World completamente valido.


Abbastanza ovvio davvero, è il primo risultato google per "Linguaggio di programmazione Pyth". Hai creato la tua pagina su esolangs?
theonlygusti,

3
@theonlygusti Sì, l'ho fatto. Inoltre, non è stato il primo risultato lo scorso ottobre.
isaacg,

9

Utilizzare Cper la compressione di base

Questo è in realtà documentato, C su una stringa è in realtà non chr diretta -> int ma invece di base 256 -> base 10 (che è la stessa su corde una char). Questo è estremamente utile nel comprimere un int, possiamo usare questo script per comprimere:

sCMjQ256

Prendi 12345678910, il risultato è ßÜ>(alcuni non stampabili lì dentro).

Inoltre con una matrice di ints, puoi concatenarli e con stringhe di grandi dimensioni convertendoli in punti di codice e trattandoli come numero 128 di base.

Un altro uso di C, grazie a @xnor per avermelo mostrato, sta facendo un numero arbitrario di grandi dimensioni. Il modo ingenuo è:

^TT

Ma possiamo fare un byte meglio con:

CG

questa base 256 deconvertisce l'intero alfabeto. Risultati 156490583352162063278528710879425690470022892627113539022649722= ~ 1.56e62.


Aggiunto a doc ora.
Isaacg,


8

Utilizzare le brevi funzioni funzionali ... err ...

Quando l'argomento lambda applica mapo reduceapplica solo un'operazione agli argomenti, è possibile utilizzare le forme brevi Me F. fMxè equivalente a mfdxed fFxè la stessa cosa di .UfbZx. Ad esempio, supponiamo di prendere un elenco di numeri come input e output ciascuno incrementato. Un primo approccio potrebbe essere:

mhdQ

Tuttavia, ciò può essere riscritto come:

hMQ

Una cosa simile si applica a reducecon F. Ad esempio, supponiamo che ci sia una sfida per calcolare il prodotto di un elenco di numeri interi. Ancora una volta, un primo tentativo potrebbe essere:

.U*bZQ

Tuttavia, con F, ciò può essere abbreviato in:

*FQ

Elimina tre byte ... non male!


E non è necessario Q, in quanto viene integrato quando alla funzione manca un input, rendendolo*F
Stan Strum

7

Mantieni aggiornata l'implementazione di Pyth.

Sto migliorando abbastanza regolarmente Pyth, rimuovendo le funzioni meno utili e aggiungendo altre più utili, quindi tieni d'occhio le novità e aggiorna regolarmente la tua copia dell'implementazione.

Alcune funzionalità aggiunte di recente: (dal 19/10/14)

y: Agisce come *2sui numeri e come elenco di tutti i sottoinsiemi su stringhe ed elenchi. Per esempio:

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

f: fè normalmente il comando filtro. Ora, quando viene chiamato con un numero come secondo argomento, filtrerà sulla sequenza infinita iniziando con quel numero e contando per uno, quindi restituirà il primo elemento della sequenza risultante.

Ad esempio, ecco il codice per trovare il primo più piccolo oltre un miliardo:

pyth -c 'f!tPT^T9'
1000000007

Sembrano utili aggiunte, ma cosa puoi usare al posto del vecchio yz? mvdczdnon può essere il modo più breve ...
Dennis,

1
@Dennis Ho buttato via il vecchio yperché non credo che Pyth debba avere più formati di input analizzati in modo super facile, solo uno, ad esempio il formato Python. Quindi sì, penso che mvdczddovremo purtroppo farlo.
isaacg,

@Dennis Problema risolto, l'ho appena aggiunto alla rsuite di elaborazione delle stringhe.
isaacg,

rsembra abbastanza utile.
Dennis,

@isaacg Mi dispiace se questo è off-topic, ma mi chiedo come utilizzare l'operazione di root @in Fdr1 + 1 @ Q2Iq% Qd0d per creare un calcolatore di fattori. Quando provo ad usarlo, il suo valore predefinito è indexinvece. Esiste un modo per aggirare questo comportamento?
StardustGogeta

5

Argomenti nominati nelle funzioni (non più supportati)

A volte, i valori predefiniti nelle funzioni possono essere utili per giocare a golf. Pyth in realtà supporta questo (con mia grande sorpresa). Per esempio:

DC=Z1RZ;C;C5

Stampa:

1
5

Puoi anche usare J e K per salvare i personaggi mentre lo fai:

DgJ1K1R+JKg;g2;g2 3

stampe:

2
3
5

Questo è di solito utile per algoritmi ricorsivi.

Questo non funziona più, ma l'ho lasciato qui nel caso qualcuno volesse giocare a golf usando una vecchia versione di Pyth.


16
Wow - Anche se non mi rendevo conto che Pyth lo supportava, e ho scritto la lingua!
Isaacg,

Sfortunatamente, questo non funziona più nelle versioni più recenti di Pyth.
isaacg,

Questo suggerimento deve essere eliminato come uno degli altri suggerimenti non aggiornati? In caso contrario, forse dovrebbe essere contrassegnato con le versioni a cui questo suggerimento si applica.
mbomb007,

@ mbomb007 Volevo trovare la versione, ma sono stato troppo pigro. Lo eliminerò se pensi che sia meglio così finché non lo trovo.
FryAmTheEggman,

@FryAmTheEggman Penso che dipenda da te, dal momento che nel titolo si dice che non è supportato.
mbomb007,

5

Disimballare 2 tuple di elementi con F

Supponiamo che tu abbia una tupla a 2 elementi J = (a, b)e che tu voglia r(a,b), per qualche funzione di 2 arity r.

Il modo ingenuo per farlo è rhJeJ.

Il modo elegante per farlo è r.*Jusare l'operatore di decompressione.

Il modo davvero fantastico per farlo è rFJusare l'operatore di piegatura.


è ancora possibile usarlo .u? .usembra essere cumulativo ridurre ora.
Ven

.u ->. * questa è stata una modifica apportata qualche tempo fa, ma non è mai stata aggiornata.
isaacg,

4

Usa le brevi funzioni aritmetiche

h: Oltre a restituire il primo elemento di un elenco, incrementa un numero, ad esempio hTvaluta 11. Più corto di +1T.

t: Questo riduce un numero (diverso da quello di restituire la coda di un elenco), ad esempio tTvaluta 9. Più corto di -T1.

y: Questo raddoppia un numero, ad esempio yTvaluta 20, più breve di *T2o +TT.


4

Utilizzare mapper generare elenchi

Fondamentalmente è un equivalente delle fantasiose comprensioni di Python. Utilizzare un elenco esistente o un intervallo per scorrere e mappare ciascun valore, anche se il valore non ha importanza.

Due esempi:

  • Genera un elenco di 8 zeri.

    mZ8 invece di *8]Z

  • Genera un elenco di 5 numeri casuali tra 0 e 9:

    mOT5 invece di V5~Y]OT)

    Il secondo assegna automaticamente la lista a Y(bene in realtà si aggiunge a Y), ma =YmOTU5è anche più breve.


4

Q implicita a EOF

Questo è un nuovo cambiamento, ad oggi.

Qè la variabile che viene inizializzata automaticamente sull'input valutato. Viene implicitamente aggiunto alla fine del programma Pyth, tutte le volte che è necessario per far funzionare l'arity. Per vedere un esempio di come utilizzarlo per giocare a golf, supponiamo di voler calcolare la funzione Collatz dell'input.

Un modo più breve per scriverlo è così:

@,/Q2h*3QQ

Tuttavia, poiché le Qs sono implicite alla fine del file, possiamo semplicemente scrivere:

@,/Q2h*3

Salvataggio di 2 byte.

Si noti che le funzioni con argomenti non richiesti non includeranno tali argomenti. Ad esempio, c"12 12"non avrà un implicito Q, poiché crichiede solo 1 argomento.


3

Utilizzare riduci per applicare ripetutamente una funzione.

Supponiamo di dover impostare una variabile su qualche funzione di se stesso e ripetere un certo numero di volte. Prendi, ad esempio, il problema di trovare il numero 100 più tardi nella sequenza di Collatz dall'input. Il modo più breve per trovare il numero successivo nella sequenza, se il numero iniziale è Q, è

@,/Q2h*Q3Q

Il modo più ovvio per applicarlo 100 volte e stampare il risultato sarebbe

V100=Q@,/Q2h*Q3Q;Q

Ripeti 100 volte, aggiornando il valore di Q ogni volta, quindi termina il ciclo e stampa Q.

Invece, possiamo usare una funzione di riduzione che ignora la variabile di sequenza ( H).

u@,/G2h*G3GU100Q

Questo è più corto di 2 caratteri. È più breve di 3 caratteri se si tenta di eseguire il ciclo tante volte quante sono gli elementi di una sequenza.


3

Di solito ci sono alternative più brevi a Any

Quando vuoi scoprire se una qualsiasi di una sequenza soddisfa una condizione, di solito la usi .Em. Ad esempio, se vuoi scoprire se qualcuno in un elenco è maggiore o uguale a 5:

.Emgd5Q

Ma, se ha solo bisogno di essere un vero / falso, non vero / falso, smfunzionerebbe dal momento che la somma funziona sui bool.

smgd5Q

Possiamo anche fare uno più corto, con filter:

fgT5Q

L'ultimo sembra davvero brutto però.

Per prima .Acosa, l'unica cosa a cui riesco a pensare è usare la condizione opposta e negarla per un salvataggio di un carattere su .Am:

!f<T5Q

3

Guarda tutte le opzioni del flusso di controllo

Loops:

F: Per loop. Proprio come Python.

V: Per loop su un intervallo. Non devono essere indicati né variabili né intervalli, quindi 2 caratteri più corti.

W: Ciclo continuo. Proprio come Python.

#: Ciclo infinito while. Fuga con errore o interruzione esplicita. Solo try ... exceptcaratterizzato da ora in Pyth.

funzioni:

D: Definizione generale. Proprio come Python.

L: 1 argomento, nessuna funzione di assegnazione, come lambda di Python, ma denominato. RNon è necessario fornire il nome della funzione, il nome della variabile e return ( ), quindi 3 caratteri più brevi.

Programmazione funzionale:

f: Filtro: seleziona gli elementi della sequenza di input che restituiscono la verità sull'input lambda.

f: Primo numero intero maggiore o uguale all'input che fornisce un risultato di filtro veritiero.

m: Mappa: trasforma gli elementi della sequenza di input usando input lambda.

u: Riduci - piega la sequenza di input sull'input lambda, inizializzando l'accumulatore sul terzo argomento.

o: Ordine: elementi più vecchi della sequenza di input che utilizzano input lambda come chiave.

Di solito, ci saranno più possibilità per ogni dato problema e solo scrivendo soluzioni di test con ognuna di esse puoi capire qual è la più breve.


.xpuò essere usato più recentemente per blocchi try-tranne.
mbomb007,

@ mbomb007 c'è modo di trascurare tranne il blocco, voglio dire che può essere lasciato vuoto? Per esempio: .x{some_statments}{except_block - can this be empty}.
Gurupad Mamadapur,

@GurupadMamadapur # ... Bpuò essere usato in questo modo se non sei dentro un'espressione
isaacg

3

Commutazione di due elementi in un elenco

Il passaggio tra due elementi può essere un'attività piuttosto costosa. Quindi qui ci sono due approcci che vuoi usare.

Approccio a variabile tmp

In preparazione definiamo un elenco Ye lo riempiamo con alcuni numeri. L'obiettivo è cambiare il secondo e il terzo elemento.

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

Assegniamo semplicemente la variabile tmp J = Q[G], facciamo la prima assegnazione della lista Y[G] = Y[H]e poi la seconda ultima assegnazione Y[H] = J. Il trucco qui è annidare le due assegnazioni dell'elenco, quindi non è necessario sopprimere la stampa e non è necessario utilizzare fare riferimento due volte Y.

J@YGXXYG@YHHJ

invece di

J@YG XYG@YHXYHJ

Approccio alla traduzione

Se gli elementi, che si desidera cambiare, sono univoci nell'elenco, utilizzare questo approccio. È davvero breve. Quindi questa volta cambiamo il primo e il terzo elemento (i valori 1e 5sono unici).

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

Questo utilizza la funzionalità di traduzione dell'elenco:

XYm@YdK)

Questa traduzione sostituisce ogni elemento Y[0]con Y[1]e ogni Y[1]con Y[0]. Quindi se i valori non sono unici, le cose brutte accadono. Ad esempio K,1 2risultati in [1, 5, 3, 5, 6, 7].

Si noti che le parentesi di chiusura sono facoltative, se l'istruzione è l'ultima nel codice.


3

Debug con <newline>

Se il tuo codice è scritto in uno stile di programmazione imperativo, è abbastanza facile eseguire il debug, poiché puoi facilmente stampare risultati intermedi. ( permalink )

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

Ma una grande quantità di programmi Pyth utilizza elementi di programmazione funzionale, come mappa, filtro e riduzione, che non consentono una stampa così semplice. Ma è ancora possibile, usando il \ncomando.

Lo stesso codice che utilizza u(riduci) sarebbe: ( permalink )

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

Se vuoi stampare i valori intermedi, inserisci semplicemente \n: ( permalink )

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

\nastampa asu una nuova riga e ritorna a. Quindi puoi inserirlo ovunque senza preoccuparti di cambiare la funzionalità del programma.


Oggi puoi usare la nuova riga per questo, che stampa anche una nuova riga.
PurkkaKoodari,

@ Pietu1998 Sì, lo uso sempre. È ora di aggiornare il post.
Jakube,

3

Trovare il massimo di due numeri interi

g#

Ad esempio, supponiamo di avere J=5e K=12. Quindi g#JK= 12 e anche g#KJ= 12.

Questo è stato scoperto da @ Pietu1998, che lo ha messo così:

Non sono sicuro che qualcuno l'abbia già trovato, ma esiste un modo fantastico per eseguire max (A, B) in 2 byte, non è necessario utilizzare 3 per eS,AB. g#ABfa la stessa cosa. (È molto inefficiente, tuttavia, poiché esegue un numero massimo di volte (1, A-B + 1). Un'ottimizzazione consiste nel mettere il numero probabilmente maggiore in B.


@Jakube Questo è vero. Apparentemente ho pensato a qualcosa mentre scrivevo questo in chat.
PurkkaKoodari,

2

Il joinmetodo di Pyth

Il joinmetodo in Python può essere spesso un po 'fastidioso, poiché unisce solo le stringhe. Pyth's joinè più generoso. Trasforma tutti gli oggetti in stringhe per impostazione predefinita.

Ad esempio jkUT0123456789o jb["abc"4,5\f]7

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

Di recente, è stata aggiunta una funzionalità di trasformazione in stringa ancora maggiore - anche il primo argomento è forzato in una stringa, ad es. j2\a\b->"a2b"
isaacg

1

Dire se un numero è un numero intero

Un trucco pulito sta usando Invariant per dire se un numero è un numero intero in quanto tale:

sI

Questo controlla se il numero non cambia quando lo tronchi, che non lo sarà se è un numero intero.

Ad esempio, puoi usarlo come un perfetto controllo quadrato:

sI@Q2

1

Usa Packed Pyth

Packed Pyth è un nuovo "linguaggio di programmazione" che è esattamente lo stesso di Pyth, tranne per il fatto che utilizza 7 bit per carattere anziché 8 bit per carattere.

Per usarlo, clonare il repository pyth . Il file packed-pyth.pyè l'interprete.

Di 'che il tuo codice è "Hello, world!.

Innanzitutto, inseriscilo in un file: echo -n '"Hello, world!' > code.pyth

Quindi, comprimi il codice Pyth nel file Pyth compresso: python3 packed-pyth.py -p code.pyth code.ppyth

Infine, esegui il codice Packed Pyth: python3 packed-pyth.py code.ppyth

Quando si esegue il codice, è possibile fornire il -dflag per vedere qual è il codice Pyth attualmente in esecuzione e è possibile fornire input come secondo argomento della riga di comando dopo il file contenente il codice.

upside:

  • Il codice è più corto di 1/8.

Svantaggio:

  • Solo ASCII.

  • Nessun input interattivo.

  • Non sono disponibili opzioni di debug complete.

  • Segnalazione errori peggiore.


1
come abbiamo fatto per la modalità provvisoria, possiamo spostarlo in una bandiera?
Maltysen,

Questo è fantastico btw: D
Maltysen

@Maltysen Penso che aumenterebbe il punteggio in byte di uno.
isaacg,

Pyth non può essere impacchettato ulteriormente poiché utilizza solo ASCII stampabile?
Lirtosiast

1

Test di divisibilità utilizzando Ie GCD

Disclaimer: Questo solo funziona per numeri interi non negativi.

Per verificare se due numeri interi non negativi sono divisibili, è possibile effettuare le seguenti operazioni:

iI<divisor><dividend>

Se a è divisibile per b e a ≥ b ≥ 0 , gcd (a, b) = b .

Non necessariamente salva i byte !%<dividend><divisor>, ma potrebbe portarti un salvataggio, perché:

  • Potresti essere in grado di modificare le cose implicite alla fine di un programma Pyth (come far cadere Q), quando lavori con il dividendo.
  • Puoi usarlo come a <pfn>, poiché è una funzione a sé stante.
  • Gestisce modulo di 0.

Provalo!


Un altro vantaggio: iIè una funzione a sé stante, mentre !%non lo è, quindi puoi usarla come funzione prefisso.
Erik the Outgolfer,

@EriktheOutgolfer Grazie, aggiunto all'elenco dei vantaggi :)
Mr. Xcoder

0

Assegnare una variabile a una funzione applicata a se stessa

Se si dispone di una funzione di arity 1 e si desidera applicarla a una variabile e applicare a se stessa, è possibile utilizzare la sintassi seguente:

=<function><variable>

Invece di:

=<variable><function><variable>

Ad esempio, se vuoi incrementare la variabile Z, puoi fare:

=hZ

Il che consente di risparmiare un byte =ZhZ.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.