En tant que l'une des langues les moins populaires, il est difficile de trouver de la littérature sur l'avant-garde du piratage postscript. Alors, quelles découvertes les golfeurs ont-ils fait pour exploiter le modèle de pile (ou d'autres fonctionnalités) pour surmonter la verbosité inhérente à Postscript?
14
Réponses:
Décodeur intégré
Un programme Postscript a une capacité unique (?) De lire son propre texte de programme sous forme de données. Ceci est normalement utilisé par l'
image
opérateur qui reçoit un procédure d'acquisition des données en entrée, et cette procédure utilise souventcurrentfile
suiviereadline
,readstring
oureadhexstring
. Mais vu d'une autre manière, ceimage
n'est qu'un autre opérateur de bouclage, de sorte que n'importe quelle boucle peut être lue à l'avance . Un exemple est l'émulateur d'imprimante ligne du Livre vert.L'utilisation de l'
token
opérateur appelle le scanner sur un fichier ou une chaîne, en tirant un nombre ou un espace (ou autre): voir autre réponse) nom délimité.Un simple interprète PS dans PS:
Décodeur de chaîne d'opérateur binaire
Puisque je n'arrive pas à me faire cru les jetons binaires (voir autre réponse), j'ai utilisé l'idée de "décodage intégré" pour exploiter le mécanisme des jetons binaires pour emballer le code dans des chaînes de 8 bits, puis manipuler et analyser les commandes de la chaîne à la volée .
La
.
procédure prend un nombre dans la pile et l'insère comme deuxième octet dans une chaîne de deux octets, le premier octet étant le préfixe-octet d'un jeton binaire, spécifiant un nom de système exécutable. Nous enregistrons un octet dans la chaîne hexadécimale en utilisant une règle du scanner selon laquelle un nombre impair de quartets dans la chaîne hexagonale est complété par un quartet supplémentaire, donc 3 quartets hexagonaux produisent une chaîne de 2 octets. La chaîne est ensuite marquée comme exécutable et appelée avecexec
laquelle invoque le scanner, produit le nom du système exécutable souhaité, puis charge le nom et exécute l'opérateur. Le$
fait cela sur chaque octet d'une chaîne de la pile, en utilisant le.
procédure deux fois , une fois comme corps de boucle, puis pour exécuter l'opérateur de bouclageforall
par numéro.De façon plus compacte, ces procédures ressemblent à ceci:
Ainsi, 55 caractères achètent des chaînes de jetons binaires. Ou, pour 6 (peut-être 7, si vous le terminez par un espace), vous pouvez charger la bibliothèque G avec
(G)run
laquelle définit.
et$
comme ci-dessus (+ quelques autres pour étendre la gamme de codes accessibles par ascii).Encore illustré dans ma réponse de puzzle de mots croisés .
la source
Lorsque la génération d'une sortie graphique et d'une sortie console n'a pas d'importance, utilisez
=
plutôtpop
.la source
Remplacer les chaînes hexadécimales par ASCII85
Probablement de vieilles nouvelles, mais je viens de l'apprendre. :)
Vous pouvez le faire en utilisant l'interpréteur postscript de manière interactive avec un filtre d'encodage et un copier-coller. Mais je vais montrer comment utiliser
dc
pour le faire "à la main".Alors, voici une chaîne hexadécimale. Nous l'avons divisé en morceaux de 4 octets.
En activant le courant continu, nous les entrons sous forme de nombres d'ordre de gros octets de 32 bits (non signés). Ensuite mod base-85 -off chiffres (il devrait y avoir 5 jusqu'à ce que vous obtenez à 0).
Remplir le dernier morceau avec
00 00
, donne (décimal), en omettant le même nombre d'octets que nous avons rempli.Ajoutez 33 pour passer à la gamme imprimable d'ASCII et de pouf! ASCII85.
Enveloppez-le dans
<~
...~>
, et Postscript de niveau 2 peut accéder à des données 8 bits, moins cher que hexadécimal.la source
Voici un quickie: encapsulez plusieurs définitions
[...>>begin
pour éliminer le mot-clédef
(nb.[
Est le même que<<
).Alors souviens-toi: plus de
Troisdeux ... affluent ensemble ! ;)la source
/a 1 def/b 2 def/c 3 def
avec<</a 1/b 2/c 3>>begin
. Nous avons besoin de plus d'espace pour def.[/a 1/b 2/c 3>>begin
/a{pop 2 mul}def
ou\b[2 3]def
, ledef
seul coûte 3 caractères, pas 4.Alors que la plupart des opérateurs postscript sont des identificateurs syntaxiques (et doivent donc être délimités par des espaces (ou autrement)), les noms
[
,]
,<<
et>>
sont auto-délimitation et scanner les détecter sans espace intermédiaire. Pour la même raison, vous ne pouvez pas faire référence à ces noms avec la/literal
syntaxe habituelle (par exemple, il/[
s'agit de deux jetons: un nom littéral vide équivalent à()cvn cvlit
et le nom exécutable[
équivalent à([)cvn cvx exec
).Afin de redéfinir ces noms, qui ne peuvent pas être mentionnés par leur nom, nous pouvons utiliser des chaînes qui sont implicitement converties en noms lorsqu'elles sont utilisées comme clés dans un dictionnaire (pratique!).
Cet exemple illustre l'utilisation abusive de ces opérateurs pour effectuer l'arithmétique.
Aussi
<<
et[
(etmark
) signifient tous la même chose.Mon propre interprète postscript, xpost , rend également l'accolade droite bouclée disponible avec certaines restrictions. discussion
la source
/
termine le jeton précédent afin que vous n'ayez pas besoin d'espace avant.Factoriser les utilisations répétées des noms d'opérateurs longs
Si vous utilisez déjà un
<<>>begin
dictionnaire, il y a une surcharge constante de/?{}
4 caractères par redéfinition. Ainsi, un opérateur de longueur n répété N fois donnera un changement de nombre de caractères de(4 + n ) - ( N * ( n - 1)).
La définition de cette formule à 0 donne l'équation du seuil de rentabilité . De cela, nous pouvons résoudre pour chaque variable en termes de l'autre, donnant
n = - ( N - 4) / (1 - N ) et
N = (4 + n ) / ( n - 1).
Non, nous pouvons répondre à des questions telles que: "Pour combien d'utilisations de" l'impression "vaut-il la peine d'abréger?" n = 5, donc N = 9/4. Prenez le plafond, car vous ne pouvez pas appeler efficacement l'impression 1/4 fois. Donc, 3. 3 utilisations. Et en effet,
(en supposant que vous avez déjà payé les frais généraux de
<<>>begin
pour activer la définition, bien sûr).Bien sûr, les jetons binaires font ce genre de moot, vous donnant les 255 premiers noms de la table des noms de système en 2 octets: 0x92, 0x ??. Et les jetons binaires sont également auto-délimitants, ne nécessitant aucun espace avant ou après, car le bit haut du premier octet est en dehors de la plage ascii.
la source
Jetons binaires
Pour le zip ultime d'un programme PostScript, cette dernière frontière est les jetons binaires qui vous permettent de supprimer complètement les noms d'opérateurs longs, au prix de ne plus avoir de programme ASCII-clean.
Donc, en commençant par un bloc compact de code postscript
Nous recherchons tous les noms au dos du PLRM (Annexe F, pp. 795-797)
Et puis tapez-les en préfixe par un
146
octet (décimal).aide vim pour la saisie d'octets arbitrairesPuis dans vim, le fichier condensé peut être tapé directement, donc:
... vous devez entrer un espace ici pour terminer le
^V
-62 et démarrer le 1, mais vous pouvez le sauvegarder et le supprimer plus tard ...... devez entrer un espace ici pour terminer le
^V
-85 et démarrer le 1, mais vous pouvez le sauvegarder et le supprimer plus tard ...... Le 3e chiffre du code à 3 chiffres met fin à la saisie d'octets, ce qui suit
0
est normal, commodément ...Qui ressemblera à ceci à l'écran (en vim):
Celui-ci peut souvent être complètement omis si le but est simplement de montrer une image. Ghostscript peint la plupart des choses à l'écran sans avoir besoin
showpage
.[ Cela ne fonctionne pas vraiment. Ghostscript me donne
undefined
etsyntaxerror
pour ces jetons. Il y a peut-être un mode que je dois activer. ]la source
Changer les rouleaux négatifs en positifs
Les rouleaux négatifs peuvent toujours être remplacés par des rouleaux positifs .
la source
3 -1 roll
ou3 2 roll
? Dans mon modèle mental, le premier devrait être plus efficace car il suffit d'un mouvement. Mon modèle mental est-il correct?roll
opérateur.Utiliser ma bibliothèque G
https://github.com/luser-dr00g/G
C'est un fichier texte. Aucune extension, pour la syntaxe la plus courte possible pour le charger.
Il permet ce programme Sierpinksi Triangle de 203 caractères
à réécrire en 151 octets
fichier de travail avec commentaires
En utilisant la fonction de noms de système abrégés,
1(G)run
élimine complètement le fardeau des noms d'opérateurs longs. Un nom d'opérateur n'a besoin que d'être assez long pour le distinguer des autres.Donc
add
devientad
mul
devientmu
index
devienti
Utilisez le PLRM annexe F pour le tableau standard des noms d'opérateurs.
Et la fonction des chaînes d'opérateur est disponible même si les noms abrégés ne sont pas sélectionnés. La bibliothèque nue a un "niveau de base" sélectionné en ajoutant simplement
(G)run
sans autres décorations.Le niveau de base comprend une nouvelle fonction
.
qui accepte le code entier pour un opérateur (le même appendice F mentionné ci-dessus) et l'exécute.La nouvelle fonction
$
parcourt une chaîne et fait appel.
à chacun. Le code ascii sélectionne donc directement l'opérateur par numéro.Une nouvelle fonction
@
vous permet d'atteindre le bas du tableau de l'annexe F en traitant le caractère espace (Ascii 0x20) comme 0.Une nouvelle fonction
#
vous permet d'accéder plus loin dans le tableau en ajoutant d'abord 95 (0x5F) pour que le caractère d'espace 0x20 soit traité comme 127 (0x7F), le code suivant après le dernier caractère ascii imprimable~
126 (0x7E).Deux nouvelles fonctions
!
vous permettent d'accéder à une structure profondément imbriquée de tableaux et / ou de dict avec un tableau d'index d'indices / clés, plutôt que des expressions fastidieuses de nombreux opérateursget
(etput
).(G)run
7 caractères achète le niveau de base.1(G)run
8 caractères achètent les noms de système ET abrégés.3(G)run $
9 caractères commencent immédiatement un bloc de procédure implicite en balayant les lignes des sources jusqu'à la ligne vierge suivante, et en définissant la première ligne comme une procédure appeléeA
, la ligne suivante est définie comme une procédure appeléeB
, etc. Cela devrait supprimer la plupart desdef
s nécessaires pour définir beaucoup de choses, sans avoir besoin de les envelopper dans un dictionnaire, ni même de leur donner explicitement des noms.la source