Conseils pour jouer au golf à Pyth


46

Pyth est un langage de programmation procédural inspiré de Python, créé par isaacg, un utilisateur de PPCG .

Quels conseils généraux avez-vous pour jouer au golf à Pyth? Je cherche des idées pouvant être appliquées aux problèmes de code de golf en général, qui sont au moins quelque peu spécifiques à Pyth.

Un pourboire par réponse, s'il vous plaît.

Réponses:


25

Commencez par écrire le code en Python

Pyth est tellement similaire à Python qu'il est assez facile de traduire des programmes Python en Pyth. Cependant, comme Pyth est un langage à lettre unique par commande, il est parfois difficile d’écrire directement en Pyth. En écrivant d'abord en Python, il y a moins de choses à penser à la fois (car Python est un langage assez facile à coder).


1
Vous pouvez également mentionner que vous pouvez toujours utiliser la syntaxe Python dans Pyth. Vous pouvez donc convertir des parties du programme individuellement ou simplement utiliser python si nécessaire. (Comme vous l'avez fait ici )
FryAmTheEggman

@ mbomb007 Téléchargez l'interpréteur Pyth et parcourez les documents. C'est le seul moyen fiable que je connaisse pour écrire un programme Pyth.
Justin

@ mbomb007 Désolé; c'est comme ça que j'ai appris à écrire Pyth (en regardant à travers le code source). Il n'y a pas de documentation sur Pyth; vous devez fondamentalement apprendre la syntaxe par essais et erreurs.
Justin

22

Connaissez vos variables

Pyth a trois catégories de variables: les variables génériques pré-initialisées, les variables pré-initialisées en fonction des entrées de l'utilisateur et les variables générant implicitement une affectation lors de la première utilisation.

Variables génériques:

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

Variables initialisées en entrée:

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

Notez que ces initialisations ne seront exécutées dans un programme donné que si la variable associée est utilisée en dehors d'une chaîne dans le code. De plus, la commande est Qalors zsi les deux sont utilisés.

Affectation sur les variables de première utilisation:

Jet K. Si vous souhaitez initialiser les deux à la même valeur, vous pouvez le faire avec une expression telle que KJ0, qui équivaut à la plus longue J0K0.


18

Utilisez le plus récent interprète en ligne pour tester vos réponses.

Notez qu'il s'agit d'un nouveau logiciel, il est donc peut-être buggé. S'il vous plaît signaler tout problème à moi.


2
Impressionnant! Je ne pouvais pas trouver cela avec Google, juste ce dont j'avais besoin!
theonlygusti

12

Les chaînes en fin de ligne n'ont pas besoin de guillemets. Par exemple:

"Hello, world!

est un programme Hello World complètement valide.


C’est une évidence, c’est le premier résultat de Google pour le "langage de programmation Pyth". Avez-vous créé votre propre page sur esolangs?
theonlygusti

3
@theonlygusti Oui, je l'ai fait. De plus, ce n'était pas le premier résultat en octobre dernier.
isaacg

9

Utiliser Cpour la compression de base

Ceci est en réalité non documenté, C sur une chaîne n'est pas direct chr -> int mais à la base 256 -> base 10 (ce qui est identique pour une chaîne de caractères ). Ceci est extrêmement utile pour compresser un int, nous pouvons utiliser ce script pour compresser:

sCMjQ256

Prenez 12345678910, il en résulte ßÜ>(certains non imprimables là-bas).

De même, avec un tableau d'ints, vous pouvez les concaténer, ainsi qu'avec des chaînes de grande taille, en les convertissant en points de code et en les traitant comme un nombre de base 128.

Un autre usage de C, merci @xnor de me l'avoir montré, est de faire un grand nombre arbitraire. La manière naïve est:

^TT

Mais nous pouvons mieux faire un octet avec:

CG

cette base 256 déconvertit l'alphabet entier. Résultats 156490583352162063278528710879425690470022892627113539022649722= ~ 1.56e62.


Ajouté à la doc maintenant.
isaacg


8

Utilisez les fonctions fonctionnelles courtes ... err ...

Lorsque l'argument lambda à mapou reduceapplique simplement une opération aux arguments, vous pouvez utiliser les formes abrégées, Met F. fMxest équivalent à mfdx, et fFxest la même chose que .UfbZx. Par exemple, supposons que nous prenions une liste de nombres en entrée et en sortie, chacun incrémenté. Une première approche pourrait être:

mhdQ

Cependant, cela peut être réécrit comme:

hMQ

Une chose similaire s'applique à reduceavec F. Par exemple, supposons qu'il soit difficile de calculer le produit d'une liste d'entiers. Encore une fois, un premier essai peut être:

.U*bZQ

Cependant, avec F, cela peut être réduit à:

*FQ

Rase trois octets ... pas mal!


Et vous n'avez pas besoin Q, car elle est complétée lorsque la fonction manque une entrée, ce qui la rend*F
Stan Strum

7

Gardez votre implémentation Pyth à jour.

J'améliore assez régulièrement Pyth, supprime des fonctionnalités moins utiles et en ajoute d'autres, donc gardez un œil sur les nouveautés et mettez à jour régulièrement votre copie de la mise en œuvre.

Quelques fonctionnalités récemment ajoutées: (au 19/10/14)

y: Agit comme un *2nombre et comme une liste de tous les sous-ensembles de chaînes et de listes. Par exemple:

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

f: fest normalement la commande de filtre. Maintenant, lorsqu'il est appelé avec un nombre en tant que deuxième argument, il filtre sur la séquence infinie en commençant par ce nombre et en comptant par 1, puis renvoie le premier élément de la séquence résultante.

Par exemple, voici le code pour trouver le plus petit nombre premier sur un milliard:

pyth -c 'f!tPT^T9'
1000000007

Ceux-ci ressemblent à des ajouts utiles, mais que pouvez-vous utiliser à la place de l'ancien yz? mvdczdça ne peut pas être le chemin le plus court ...
Dennis

1
@Dennis J'ai jeté l'ancien yparce que je ne pense pas que Pyth doit disposer de plusieurs formats d'entrée très facilement analysables, un seul, par exemple le format Python. Donc, oui, je pense que je devrai mvdczdle faire, malheureusement.
isaacg

@Dennis Problème résolu, nous venons d'ajouter ceci à rla suite de traitement de chaînes.
isaacg

rsemble très utile.
Dennis

@isaacg Désolé si cela est hors sujet, mais je me demande comment utiliser l'opération racine @dans Fdr1 + 1 @ Q2Iq% Qd0d pour créer un calculateur de facteurs. Lorsque j'essaie de l'utiliser, le indexsens par défaut est utilisé . Y a-t-il un moyen de contourner ce comportement?
StardustGogeta

5

Arguments nommés dans les fonctions (non pris en charge)

Parfois, les valeurs par défaut dans les fonctions peuvent être utiles pour le golf. Pyth le supporte réellement (à ma grande surprise). Par exemple:

DC=Z1RZ;C;C5

Imprimera:

1
5

Vous pouvez également utiliser J et K pour sauvegarder des caractères en procédant comme suit:

DgJ1K1R+JKg;g2;g2 3

impressions:

2
3
5

Ceci est généralement utile pour les algorithmes récursifs.

Cela ne fonctionne plus, mais je l'ai laissé ici au cas où quelqu'un voudrait jouer au golf avec une ancienne version de Pyth.


16
Wow - Même si je n'avais pas réalisé que Pyth le supportait, j'ai écrit le langage!
isaacg

Malheureusement, cela ne fonctionne plus dans les versions les plus récentes de Pyth.
isaacg

Ce conseil devrait-il être supprimé comme l'un des autres conseils obsolètes? Si non, peut-être devrait-il être marqué avec la ou les versions auxquelles cette astuce s'applique.
mbomb007

@ mbomb007 Je voulais trouver la version, mais j'ai été trop paresseux. Je vais le supprimer si vous pensez que c'est mieux ainsi jusqu'à ce que je le trouve.
FryAmTheEggman

@FryAmTheEggman Je pense que c'est à vous de décider, car cela indique dans le titre qu'il n'est pas pris en charge.
mbomb007

5

Déballage de tuples 2 éléments avec F

Supposons que vous avez un tuple à 2 éléments J = (a, b), et que vous voulez r(a,b), pour une fonction à 2 arités r.

La façon naïve de le faire est rhJeJ.

Pour ce faire r.*J, utilisez l’opérateur de décompression.

La façon la plus simple de procéder consiste à rFJutiliser l’opérateur de pliage.


est-il encore possible d'utiliser .upour cela? .usemble être cumulatif réduire maintenant.
Ven

.u ->. * il s’agit d’un changement qui a été fait il ya un moment, mais qui n’a jamais été mis à jour.
isaacg

4

Utiliser les fonctions arithmétiques courtes

h: En plus de renvoyer le premier élément d'une liste, il incrémente un nombre, par exemple, hTévalue 11. Plus court que +1T.

t: Ceci décrémente un nombre (autre que renvoyer la queue d'une liste), par exemple, tTévalue 9. Plus court que -T1.

y: Ce double un certain nombre, par exemple yTévalue à 20plus court que *T2ou +TT.


4

Utiliser mappour générer des listes

C'est fondamentalement un équivalent de la compréhension de liste fantaisie de python. Utilisez une liste existante ou une plage sur laquelle itérer et mapper chaque valeur, même si la valeur n'a pas d'importance.

Deux exemples:

  • Générez une liste de 8 zéros.

    mZ8 au lieu de *8]Z

  • Générez une liste de 5 nombres aléatoires compris entre 0 et 9:

    mOT5 au lieu de V5~Y]OT)

    Le second attribue automatiquement la liste à Y(eh bien en fait il s’ajoute à Y), mais =YmOTU5est même plus court.


4

Q implicite à EOF

C'est un nouveau changement, à compter d'aujourd'hui.

Qest la variable qui est auto-initialisée à l'entrée évaluée. Il est implicitement ajouté à la fin du programme Pyth, autant de fois que nécessaire pour résoudre le problème d'arité. Pour voir un exemple d'utilisation de cette méthode pour le golf, supposons que nous voulions calculer la fonction Collatz de l'entrée.

Une façon la plus rapide de l’écrire est la suivante:

@,/Q2h*3QQ

Cependant, les Qs étant implicites à la fin du fichier, on peut simplement écrire:

@,/Q2h*3

Enregistrement de 2 octets.

Notez que ces arguments ne seront pas renseignés dans les fonctions avec des arguments non requis. Par exemple, ils c"12 12"n'auront pas d'implicite Q, car ils cne nécessitent qu'un seul argument.


3

Utilisez réduire pour appliquer une fonction à plusieurs reprises.

Supposons que vous deviez définir une variable sur une fonction d'elle-même et la répéter un certain nombre de fois. Prenons, par exemple, le problème de trouver le nombre 100 plus tard dans la séquence de Collatz à partir de l'entrée. Le moyen le plus rapide de rechercher le prochain numéro de la séquence, si le numéro initial est Q, est

@,/Q2h*Q3Q

La manière la plus évidente d’appliquer ces 100 fois et d’imprimer le résultat serait

V100=Q@,/Q2h*Q3Q;Q

Boucle 100 fois, en mettant à jour la valeur de Q à chaque fois, puis terminez la boucle et imprimez Q.

Au lieu de cela, nous pouvons utiliser une fonction de réduction qui ignore la variable de séquence ( H).

u@,/G2h*G3GU100Q

C'est 2 caractères plus court. Il est plus court de 3 caractères si vous essayez de boucler autant de fois qu'il y a d'éléments dans une séquence.


3

Il existe généralement des alternatives plus courtes à

Lorsque vous voulez rechercher si une séquence satisfait à une condition, vous utiliserez généralement .Em. Par exemple, si vous voulez savoir si certains éléments d'une liste sont supérieurs ou égaux à 5:

.Emgd5Q

Mais, si cela doit seulement être une vérité / falsey, pas vrai / faux, smcela fonctionnerait puisque sum travaille sur bools.

smgd5Q

On peut même en faire un plus court, avec filter:

fgT5Q

Le dernier a l'air vraiment moche cependant.

Pour .All, la seule chose à laquelle je peux penser est d'utiliser la condition opposée et de la nier pour une sauvegarde d'un caractère .Am:

!f<T5Q

3

Regardez toutes les options de flux de contrôle

Boucles:

F: Pour la boucle. Tout comme Python.

V: Pour une boucle sur une plage. Aucune variable ni plage ne doit être donnée, donc 2 caractères plus courts.

W: En boucle. Tout comme Python.

#: Infini en boucle. Échapper avec une erreur ou une pause explicite. Seule try ... exceptfonctionnalité maintenant en Pyth.

Les fonctions:

D: Définir général. Tout comme Python.

L: 1 argument, pas de fonction d’assignation, comme le lambda de Python, mais nommé. Le nom de la fonction, le nom de la variable et return ( R) n'ont pas besoin d'être indiqués, donc 3 caractères plus courts.

Programmation fonctionnelle:

f: Filter - sélectionne les éléments de la séquence d’entrée qui retournent la vérité sur l’entrée lambda.

f: Premier entier supérieur ou égal à l'entrée qui donne le résultat du filtre de vérité.

m: Map - transforme les éléments de la séquence d'entrée en utilisant l'entrée lambda.

u: Réduit - plie la séquence d'entrée sur l'entrée lambda, initialisant l'accumulateur sur le troisième argument.

o: Order - les éléments les plus anciens de la séquence d'entrée utilisant l'entrée lambda comme clé.

Habituellement, il y a de multiples possibilités pour un problème donné, et ce n'est qu'en écrivant des solutions de test avec chacun d'eux que vous pouvez déterminer laquelle est la plus courte.


.xpeut plus récemment être utilisé pour les blocs try-except.
mbomb007

@ mbomb007 y at-il moyen de négliger sauf bloc, je veux dire que peut être laissé vide? Ex: .x{some_statments}{except_block - can this be empty}.
Gurupad Mamadapur

@GurupadMamadapur # ... Bpeut être utilisé de cette façon si vous n'êtes pas dans une expression
isaacg

3

Changer deux éléments dans une liste

Changer deux éléments peut être une tâche assez coûteuse. Donc, voici deux approches que vous voulez utiliser.

Approche tmp-variable

En préparation, nous définissons une liste Yet la remplissons de chiffres. L'objectif est de passer du deuxième au troisième élément.

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

Nous affectons simplement la variable tmp J = Q[G], faisons la première affectation de liste Y[G] = Y[H]puis l’avant-dernière affectation Y[H] = J. Le truc ici consiste à imbriquer les deux assignations de liste, de sorte que vous n’ayez pas à supprimer l’impression ni à utiliser le renvoi à deux fois Y.

J@YGXXYG@YHHJ

au lieu de

J@YG XYG@YHXYHJ

Approche traductive

Si les éléments que vous souhaitez activer sont uniques dans la liste, utilisez cette approche. C'est vraiment court. Donc, cette fois, nous commutons les premier et troisième éléments (les valeurs 1et 5sont uniques).

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

Ceci utilise la fonctionnalité de traduction de la liste:

XYm@YdK)

Cette traduction remplace chaque élément Y[0]avec Y[1]et Y[1]avec Y[0]. Donc, si les valeurs ne sont pas uniques, de mauvaises choses se produisent. Par exemple, K,1 2résulte en [1, 5, 3, 5, 6, 7].

Notez que les parenthèses fermantes sont facultatives, si l’instruction est la dernière de votre code.


3

Débogage avec <newline>

Si votre code est écrit dans un style de programmation impératif, il est assez facile de déboguer, car vous pouvez facilement imprimer des résultats intermédiaires. ( permalien )

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

Cependant, un grand nombre de programmes Pyth utilisent des éléments de programmation fonctionnelle, tels que mappage, filtrage et réduction, qui ne permettent pas une impression aussi simple. Mais c'est toujours possible, en utilisant la \ncommande.

Le même code utilisant u(réduire) serait: ( permalien )

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

Si vous souhaitez imprimer les valeurs intermédiaires, il vous suffit d'insérer \n: ( permalien )

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

\naimprime asur une nouvelle ligne et retourne a. Ainsi, vous pouvez l'insérer n'importe où sans vous soucier de modifier les fonctionnalités du programme.


Vous pouvez maintenant utiliser la nouvelle ligne pour cette opération, qui imprime également une nouvelle ligne.
PurkkaKoodari

@ Pietu1998 Oui, je l'utilise tout le temps. Il est temps de mettre à jour le message.
Jakube

3

Trouver le maximum de deux entiers

g#

Par exemple, supposons que vous avez J=5et K=12. Alors g#JK= 12, et g#KJ= 12 aussi.

Ceci a été découvert par @ Pietu1998, qui l'a exprimé ainsi:

Je ne suis pas sûr que quelqu'un l'ait déjà trouvé, mais il existe un moyen pratique de faire max (A, B) sur 2 octets, inutile d'utiliser 3 pour eS,AB. g#ABfait la même chose. (C'est très inefficace, cependant, car il boucle max (1, A-B + 1) fois. Une optimisation consiste à mettre le nombre susceptible d'être plus grand que B.)


@ Jakube C'est vrai. J'ai apparemment mal compris quelque chose en tapant ceci dans le chat.
PurkkaKoodari

2

La joinméthode de Pyth

La joinméthode en Python peut être souvent un peu gênante, car elle ne fait que joindre des chaînes. Pyth's joinest plus généreux. Il transforme tous les objets en chaînes par défaut.

Par exemple, jkUTdonne 0123456789ou jb["abc"4,5\f]7donne

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

Récemment, une fonctionnalité encore plus importante de transformation de chaîne a été ajoutée - le premier argument est également contraint en chaîne, par exemple j2\a\b->"a2b"
isaacg

1

Dire si un nombre est un nombre entier

Une astuce consiste à utiliser Invariant pour savoir si un nombre est un nombre entier en tant que tel:

sI

Ceci vérifie si le nombre ne change pas lorsque vous le tronquez, ce qui ne sera pas le cas s'il s'agit d'un nombre entier.

Par exemple, vous pouvez utiliser ceci comme vérification carrée parfaite:

sI@Q2

1

Utilisez Packed Pyth

Packed Pyth est un nouveau "langage de programmation" qui est identique à Pyth, à la différence qu’il utilise 7 bits par caractère au lieu de 8 bits par caractère.

Pour l'utiliser, clonez le référentiel pyth . Le fichier packed-pyth.pyest l'interprète.

Dites que votre code est "Hello, world!.

Tout d'abord, mettez-le dans un fichier: echo -n '"Hello, world!' > code.pyth

Ensuite, compressez le code Pyth dans un fichier Packed Pyth: python3 packed-pyth.py -p code.pyth code.ppyth

Enfin, lancez le code Packed Pyth: python3 packed-pyth.py code.ppyth

Lorsque vous exécutez du code, vous pouvez indiquer à l' -dindicateur quel est le code Pyth en cours d'exécution, ainsi que le deuxième argument de ligne de commande après le fichier contenant le code.

Upside:

  • Le code est plus court de 1 / 8ème.

Inconvénient:

  • ASCII seulement.

  • Aucune entrée interactive.

  • Les options de débogage complètes ne sont pas disponibles.

  • Pire rapport d'erreurs.


1
comme nous l'avons fait pour le mode sans échec, pouvons-nous le placer dans un drapeau?
Maltysen

C'est génial d'ailleurs: D
Maltysen

@Maltysen Je pense que cela augmenterait le score d'octet d'un.
isaacg

Pyth ne peut-il pas être emballé plus loin puisqu'il n'utilise que de l'ASCII imprimable?
lirtosiast

1

Test de divisibilité avec Iet GCD

Avertissement: Cela ne fonctionne que pour les entiers non négatifs.

Pour vérifier si deux entiers non négatifs sont divisibles, vous pouvez procéder comme suit:

iI<divisor><dividend>

Si a est divisible par b et a ≥ b ≥ 0 , alors gcd (a, b) = b .

Cela ne économise pas nécessairement plus d'octets !%<dividend><divisor>, mais cela peut vous apporter une économie, car:

  • Vous pourrez peut-être modifier les éléments implicites à la fin d'un programme Pyth (comme un abandon Q) lorsque vous travaillerez avec le dividende.
  • Vous pouvez l'utiliser comme un <pfn>, puisqu'il s'agit d'une fonction à part entière.
  • Il gère modulo par 0.

Essayez le!


Un autre avantage: iIest une fonction en elle-même, alors qu’elle !%ne l’est pas, vous pouvez donc l’utiliser comme fonction de préfixe.
Erik l'Outgolfer

@EriktheOutgolfer Merci, ajout à la liste des avantages :)
M. Xcoder

0

Assigner une variable à une fonction appliquée à elle-même

Si vous avez une fonction d'arité 1 et que vous souhaitez l'appliquer à une variable et l'appliquer à elle-même, vous pouvez utiliser la syntaxe suivante:

=<function><variable>

Au lieu de:

=<variable><function><variable>

Par exemple, si vous voulez incrémenter la variable Z, vous pouvez faire:

=hZ

Ce qui sauve un octet fini =ZhZ.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.