Comping Quipu: Base 10 dans le Nouveau Monde


41

Les quipus sont un ancien dispositif utilisé par les Incas à l’époque précolombienne pour enregistrer les nombres dans un système de positions à dix positions de base sur un cordon, qui fonctionne comme suit:

Chaque groupe de nœuds est un chiffre et il existe trois types principaux de nœuds: les nœuds simples et simples; "nœuds longs", consistant en un nœud plat avec un ou plusieurs tours supplémentaires; et huit nœuds.

  • Les puissances de dix sont indiquées par la position le long de la chaîne, et cette position est alignée entre les brins successifs.
  • Les chiffres dans les positions pour les puissances supérieures ou égales à 10 sont représentés par des grappes de nœuds simples (par exemple, 40 correspond à quatre nœuds simples dans une rangée dans la position «dizaines»).
  • Les chiffres dans la position "un" sont représentés par des nœuds longs (par exemple, 4 est un nœud à quatre tours). En raison de la manière dont les nœuds sont noués, le chiffre 1 ne peut pas être affiché de cette façon et est représenté dans cette position par un nœud en huit.
  • Le zéro est représenté par l'absence de noeud dans la position appropriée.

Détails

Pour ce défi, chaque branche d'un quipu représente un nombre unique (bien que, comme le dit l'article de Wikipedia, vous pouvez représenter plusieurs nombres sur un seul volet, nous ne le ferons pas pour ce défi).

Noeuds

Chaque nœud sera représenté par un seul caractère ASCII.

  • . représente un nœud simple
  • : représente un tour d'un noeud long
  • 8 représente un noeud en huit
  • | représente l’absence de noeud ainsi que de séparateur entre les chiffres.

Construire Quipus

Les Quipu sont construits en suivant ces règles.

  1. Les brins vont de haut en bas par ordre décroissant de position (comme dans, le chiffre des unités sera au bas d'un brin). Les chiffres le long d'un brin sont séparés par le caractère ( |).
  2. La puissance de 10 que représente un chiffre est déterminée par sa position le long du brin de la même manière qu'une puissance de 10 chiffres serait calculée à l'aide de son index dans un nombre avec notre système de numération. C'est-à-dire, 24avec un 2dans la position des dizaines et un 4dans la position des unités, sera représenté par deux nœuds, un délimiteur ( |), puis quatre nœuds.
  3. Les chiffres dans la même position sont alignés vers le bas du brin. Si un chiffre dans une position aura moins de nœuds que les autres chiffres des autres nombres dans la même position, l'absence de ces nœuds est représentée par ( |).
  4. Les nœuds simples consécutifs ( .) représentent une valeur dans leur position.
  5. Chaque chiffre est représenté par au moins 1 caractère. Lorsqu'une valeur numérique est 0 pour tous les nombres d'un quipu, elle est représentée par l'absence d'un nœud ( |).
  6. La place des unités est traitée spécialement. Un un dans la position des unités est représenté par un nœud en huit ( 8). Une valeur de deux ou plus à la place des unités est représentée par des nœuds longs consécutifs ( :).
  7. Lorsque le chiffre des unités est 0 pour tous les nombres d'un quipu, l'absence de nœud n'est pas imprimée, mais le séparateur final du chiffre des dizaines est conservé.
  8. Il n'y a pas de délimiteur après le chiffre des unités.

Règles

  • L'entrée consistera en une liste non vide d'entiers non négatifs pouvant être reçus via n'importe laquelle des méthodes d'entrée par défaut . Vous pouvez supposer que ces entiers sont tous inférieurs ou égaux à 2147483647ou 2^31-1. Bien que les scénarios de test soient séparés par des espaces, votre format d’entrée peut séparer les entrées de la manière qui vous convient le mieux pour votre langue, qu’il s’agisse de séparer les virgules, les sauts de ligne, d’un tableau, etc.
  • La sortie consiste en un seul Quipu construit selon les règles décrites ci-dessus. La sortie peut être donnée par n'importe laquelle des méthodes de sortie par défaut .
  • Votre code doit être un programme ou une fonction, bien qu'il ne soit pas nécessaire que ce soit une fonction nommée.
  • Les nœuds prennent un certain temps à nouer, donc pour gagner du temps, votre code le plus court possible.

Comme toujours, si le problème n'est pas clair, merci de me le faire savoir. Bonne chance et bon golf!

Exemples

Contribution:

5 3 1 0

Sortie:

:|||
:|||
::||
::||
::8|

Contribution:

50 30 10 0

Sortie:

.|||
.|||
..||
..||
...|
||||

Contribution:

330

Sortie:

.
.
.
|
.
.
.
|

Contribution:

204 1

Sortie:

.|
.|
||
||
||
:|
:|
:|
:8

Contribution:

201 0 100 222

Sortie:

.||.
.|..
||||
|||.
|||.
||||
|||:
8||:

Contribution:

1073741823 2147483647

Sortie:

|.
..
||
|.
||
.|
.|
.|
..
..
..
..
||
|.
|.
|.
|.
..
..
..
||
.|
.|
.|
..
..
..
..
||
|.
|.
|.
|.
..
..
..
..
||
|.
|.
..
||
.|
.|
..
..
..
..
..
..
||
|.
|.
..
..
||
|:
|:
|:
|:
::
::
::

Contribution:

0

Sortie:

|

Cas de test plus longs

Lectures complémentaires


Réponses:


3

Python, 64 octets

=QjRTQjCmj\|+:R"[8:]"\.PdedCmm+*\|-h.MZdk*?tk\:\8kdC.[L0h.MZlMQQ

Essayez-le en ligne!

Comment ça marche

=QjRTQ   Converts each number in input to decimal (as a list)
         123 becomes [1,2,3]

----

jCmj\|+:R"[8:]"\.PdedCmm+*\|-h.MZdk*?tk\:\8kdC.[L0h.MZlMQQ

                                              .[L0       Q  0-leftpad each #
                                                  h.MZlMQ   (max length) times

                                             C              transpose

                      mm                    d    for each digit:
                        +                        [convert to] sum of
                         *\|                     "|" repeated
                            -                    the difference of
                             h.MZd               maximum digit in same row
                                  k              and itself.. that many times
                                   *?tk\:\8      and (digit > 1 then ":" or "8") repeated
                                           k     itself many times


the list:
[11,23,52]
->[[1,1],[2,3],[5,2]]
->[[1,2,5],[1,3,2]]
->[["||||8","|||::",":::::"],["||8",":::","|::"]]

                     C      transpose

->[["||||8","||8"],["|||::",":::"],[":::::","|::"]]

  m                          for each number
      +                      [convert to] sum of
                 Pd          every element but the last
       :R"[8:]"\.            with "8" and ":" replaced by "."
                   ed        and the last element
   j\|                       joined with "|"

  C                          transpose
 j                           join (with newlines)

C'est une excellente réponse sauf pour un problème. Le nœud final n'est pas toujours un nœud en huit 8. En fait, il ne s'agit que d'un 8nœud lorsque le dernier chiffre est un 1 (voir règle 6). Vous convertissez tous les noeuds finaux et cela ne correspond pas à la spécification. De plus, essayez-le en ligne! le lien a apparemment un code différent de celui qui est affiché ici
Sherlock9

22

Illisible , 3183 3001 octets

Ce fut un défi amusant de travailler, de temps en temps, entre les fêtes de Noël. Merci d'avoir posté! La pratique du golf était intéressante car le cahier des charges est rempli d'exceptions et de cas particuliers, ce qui nécessitait de nombreuses conditions. De plus, bien que je n’aie pas eu besoin de convertir en décimales cette fois-ci, j’ai eu besoin d’une fonction de tri «max» pour déterminer le plus grand nombre de chiffres dans chaque nombre et la plus grande valeur des chiffres dans chaque emplacement.

La première version de ceci était 4844 octets, histoire de vous donner une idée de combien j'avais joué au golf.

Le programme attend l’entrée sous forme de liste d’entiers séparés par des virgules . Pas d'espaces ou de nouvelles lignes. Utiliser ceux-ci produira un comportement indéfini.

« " « » « » » « » « « » » « » « « » » « » « « » « « « » « » « » » » « » » « » « « » » « » « « » » « » « « » » « » « « » » « » « « » » « » « » « » « « » » « » « « » » « » « « » » « » " « »" « « » » « » « « » » « » « « » » « » « « » » « » « « » » « » « « » » « » « « » » « » « « » » « » « « » » « » '« » « « » » « » « « » » « » « « » » « » « « » » « » « « » » « » « « » » « » « « » » « » « » « » " » « » « » « » « « « » « « « » » » « « « » » » « « « » » » « » « » « « « » » » « » » » « « « » » » " » « » « « » » « » « « » » « » « « » « « « » « » « « « » « » « » » » « » » » « » « » « »" » « » « »« » « " « » « « « » « » « » » » « » « » « » » « « » « « « » » » " » « » « » « » "" « » « » « » « » "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" « » « » « » « « » » « » « « »" » « » « » « » « « « » » » « « « » » » « « « » » » « " « » » ""« » « » « » « » « « » « » « » » « » « » « » « « » » « » « « « » » » « » « » « » « « » » « » "" « » « " « » « « « » « » « » » » « « « » » » « » » « » « » « » « » « « » « » « » « « « » » » " » « » " « " « » « » » « » « « » » « » « « » « « « » « » « » « » » » « » « » « » » « » « « » » « »" »« » « « » « » « » » « » « » « » « « » « « « » « » « » « » » » « » « » « » » « » « " « » »" « » « » « » « « » « « « » « » « » « » » » « » » « » « » « » « « » » « » « « »" » « » « » « " « » « » « » » "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "« » « « « » « » « » » » « » « « » » « » « » « » « " « » « « « » « » » » « » « » « « « » » » »" « » « « » « « « » « » « » « » » » « » » « » « » « « « » « » « » « » » » « » « » « " « » « » « » »" « » « « " » » « » « » « » « « » « » « » " » « » « " « » « » « » « » » « « » « » « » « » " » « »« » « » « " « » « » « » »" « » « « « » « « « » « » « » « » « « « » » » « » « » « » » » « » » » « » "" "" "" "" "" "" "" "" "" "" "". "" "" "". "" "" "" "" ".. « » « « » » « » « « » » « » « " « » « » » « « » « » « » « « « » « » « » » » " » « » « « « » » »« » « » « » « « » » « » « « « » « » » » « » "" « » « » « « « » « » « » » » « « « » » » « « « » » » « « " » » « « « » « « « » « » « » » » « « « » » » « « « » » » « » » » « » « » « » « « » « » « » » « » « « » « « « » » » « » « » « » » « » « « »" » « » « " « » « » » « « » « » « »" » « » « »"« « " » » « » « « » « » « » « » » « » « » « » « « « » » » « » « « » « » « » « » " » « » « » « » " « " " « » « » « « « » « » « » » » « « « » » » « « « » » » « « « » » » » « « »" » « » « » « » « » « « » « » « » « « « » » » « « « » » » « « « » » » « « « » » » « » » « » « » « » « » "" « » « »« » « » « « » « » « » « » » « » « » « » « " « » « » « » » « « » " » « » « » « » « » "" « » « » « » « « " » » « « « » » » « » « « » « » « » » « » « « » » « » « « » » « » « " » « « » « » « » « »" » « » « « » « » « » « « « » « » « » « « « » » » « » » » « » « » « » « » » « » « « » » « » « » »« » « « » « » « » « « « » » » « » » « » « » « « » « » « » » « » « » « » « « « » » » « » " « » « » » « » « » « « » « » « » « » « « « » » » « » « » « » » « » « " « » » « « » « » « » « » « « « » » » " » « » « » « » « " « » « » « » » « « » " » « » « " « » « » « » « » « « « » » » « « « » » » « » »« » « « « » « » « » « « « » » » « » » » « » « « » « » « » « » » « » « « « » » » « » « » « » " « » » « » « » « « » » « » « « « » « » « » « » » » « » « » « » « " « » » « « » « » « » " » « » « » « » « » "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "« « » « » « »" » « » « " « » « » « » « « « » » » « « « » » » « « « » » » » « « » « « « » » »" »" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ". Différentes plusieurs différentes plusieurs-plusieurs différentes-plusieurs plusieurs plusieurs différentes-plusieurs plusieurs plusieurs plusieurs plusieurs-plusieurs plusieurs-plusieursions" "" "" "" "" "" "" "". Plusieurs plusieurs plusieurs plusieurs-plusieurs plusieurs plusieurs différentes différentes différentes différentes différentes différentes "" "" "" plusieurs plusieurs plusieurs plusieurs plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes plusieurs différentes différents différents différents différents différents différents différents divers différents divers différents divers plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieurs plusieursions} "" "" "" plusieurs plusieurs plusieurs plusieurs plusieurs plusieursions deuxions "" " « » « » « « » » « » « « » » « » « « » » « » « « « » « » » » « » « » « » « » " « » « » « » « » »"" « » « » « « « » « » « » « « « » « » « » » » « « « » » » « » » » « » « » « » "" « » « » « » « « " » » « « « » « « « » « » « » » » « » « » « » » »" " « » « « « » « » « » « » » » « » « » « » « « » « » « » « « « » » » « » » « » « " « » « » « » « » »" « » « » « » « « « » » » « « « » » »« « " » » « » « » « » « « » » « » « « » " » « » « « « » « » « » « » « « « » » » « » « » « » » » " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "".. « » « » « » « « « » « » « » « « « » » » « » » » « » « « » « »" » « » « » « »" " « » « » « »"" « » « « » « « « » » » « » « » « » » « » « « » » « » « " « » « « « » « » » » « » »" « » « » « « " « » « » » » « » « » « » « « » » « » « « « » « » « » « » » » « » « » « » « « » « » « » " » " « ' « » « « « » « » « » » » « » « » « « « » » » « « « » « « « » « » « » « » » » « » « » « » » »« « " » » « » « « » " » « » « » « « « » « » « » « « « » « » « » » » « « « » » » « » » » « " « » » « » « » « « » » « » « « » « « « » « » « » » » « » « » « » » « » « « » « « « » » » « » « » « » » « » « » « » « « « » » » « » « « » « » « » « » « « « » » » « » « » « » » « » « « « » « » « » » » « »« » « » « « « » « » « » « » » » « » « » « » « « « » « » « » « » » » « » « » « » « « » » « » " « » » « « »" » « » « " « » » « « » « » « » « »" » « » « » « " « » « » « » « « « » « » « » » » » " « »" "" « » « » « » « « « » » » « » « « » « » « » « « « » » » « « « » » »" » « » « " « » » ""« » « » « » « » « « » « » « » « « « » » » « « « » » » « » » "" « » « » « » « « « » « » « » « » » » « » « « »" » « » « » « » « » « « « » « » « » « » » » « » « » « » « « « » « » « » « » » » « » « »" « " " « » « » » " « »" « « » « » « » « » « « « » « » « » « « « » » » « « « » » » « » » » »"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "." "" "" "" "" "" "" "" "" "" "" "" "" "" "" "." "" "" "" "" "" "" "" "" "" "" "" "" "." "" "" "" "" "" "" "" "" ".." "" "" ".." "" "" "" "" "" "" "" "" "" "" "" "" ".. « » « « « » « » « » « » » » « » « » « « « » » » « « « » » » « » « « » « »" » « » « » « » « " « » » « » « « « » » » « « « » « « « » « » « » « » » » « » « » « » » » « « « » » » « » « « » « » « » »« » « » « » « « « » « « « » « » « » « » » » « » « » « » » » « » « » « » « « »" » « »"

Explication

Je vais vous expliquer le fonctionnement du programme en vous expliquant comment il traite les entrées spécifiques 202,100,1.

Au début, nous construisons quelques valeurs dont nous aurons besoin plus tard - principalement les codes ASCII des caractères que nous allons afficher.

entrez la description de l'image ici

Comme vous pouvez le voir '8'et '.'sont déjà disponibles.'|'Cependant, c’est vraiment 124, pas 14. Nous utilisons une boucle while pour ajouter le double de la valeur temporaire de l’emplacement n ° 1 afin d’obtenir 124 (ce qui correspond à 14 + 55 × 2, car la boucle while s’exécute pendant 56−1 = 55 itérations). Cela économise quelques octets, car les littéraux de grand entier comme 124 sont très longs. Dans le diagramme suivant, je montre l'emplacement de chaque variable utilisée par le programme.

entrez la description de l'image ici

Ensuite, nous voulons saisir tous les caractères et les stocker sur la bande à partir de la cellule 12 ( p est le pointeur courant pour cela). En même temps, nous voulons savoir quelle est la longueur du nombre le plus long (combien de chiffres). Pour ce faire, nous conservons un total cumulé en allant unaire à gauche à partir de la cellule # −1 (nous utilisons q comme pointeur en cours d'exécution). Après le premier numéro saisi (202 ), la bande ressemble maintenant à ceci:

entrez la description de l'image ici

Vous aurez sûrement remarqué que les nombres sont décalés de 4. Bien, lorsque nous les avons saisis pour la première fois, ce sont leurs valeurs ASCII. Ils sont donc «désactivés» par 48 et la virgule est 44. Pour chaque caractère, nous copions les 46 de '.'dans r puis soustrayez-le avec une boucle while (qui soustrait 45) et ensuite nous ajoutons 1. Nous faisons cela pour que la virgule (notre séparateur) vaut 0, afin que nous puissions utiliser une condition pour le reconnaître.

En outre, vous aurez remarqué que nous laissons la cellule 11 à 0. Nous en avons besoin pour reconnaître la limite du premier nombre.

Le prochain caractère sera une virgule, donc nous stockons un 0 dans # 15, mais bien sûr cette fois, nous n'avançons pas q . Au lieu de cela, nous avons mis q à 0 et commençons à «écraser» les 1 que nous avons déjà placés.

Une fois que tous les caractères restants ont été traités, nous obtenons ceci:

entrez la description de l'image ici

Comme vous pouvez le voir, les 1 écrits par q indiquent maintenant (en unaire) la longueur du nombre le plus long.

Nous utilisons maintenant une boucle while pour déplacer q à l'extrême gauche, puis plaçons un autre pointeur là-bas que j'appellerai r2 . Le but de R2 deviendra clair plus tard.

entrez la description de l'image ici

À ce stade, permettez-moi de clarifier la terminologie que je vais utiliser tout au long de cette étape.

  • Par nombre , j'entends un des nombres entrants séparés par des virgules. Dans notre exemple, ils sont 202, 100 et 1.
  • Par chiffre , j'entends un seul chiffre dans un nombre spécifique. Le premier numéro a 3 chiffres.
  • Par lieu , j'entends les lieux, les dizaines, les centaines, etc. Ainsi, si je dis «les chiffres du lieu actuel» et que le lieu actuel est celui des lieux, ces chiffres sont 2, 0 et 1. ordre.

Revenons maintenant à notre programmation régulière. Le reste du programme est une grande boucle qui avance q jusqu'à atteindre la cellule 0. Chacune des cellules situées le long du chemin représente un endroit, avec celles situées à l'extrême droite, et q commencera au plus significatif. Dans notre exemple, c’est la place des centaines.

Nous procédons en incrémentant la cellule q points à (c'est-à-dire, * q ).

entrez la description de l'image ici

Nous sommes maintenant à la «phase 2» pour la place des centaines. Dans cette étape, nous allons découvrir quel est le plus grand chiffre parmi tous les chiffres des centaines. Nous utilisons le même truc unaire, sauf que cette fois le pointeur s'appelle r et le pointeur r2 marque sa position de départ sur laquelle nous devons le réinitialiser à chaque fois que nous passons au nombre suivant.

Commençons par le premier numéro. Nous commençons par régler p sur 11 (la position de départ codée de manière irréversible de tous les nombres). Nous utilisons ensuite une boucle while pour trouver la fin du nombre et définissons p2 pour marquer la position. Dans le même temps, nous avons également mis q2 à 0:

entrez la description de l'image ici

Ne soyez pas distrait par le fait que q2 pointe dans les vars. Nous n'avons pas de remplissage d'une cellule vierge car nous pouvons détecter la cellule # 0 simplement parce que c'est le numéro zéro.

Ensuite, nous parcourons le nombre actuel en décrémentant ensemble p et q2 jusqu'à ce que * p soit égal à zéro. À chaque endroit, la valeur de * q2 nous indique ce que nous devons faire. 1 signifie «ne fait rien», alors nous continuons. Finalement, nous rencontrons le 2 dans la cellule n ° −3. Chaque fois que * q2 n'est pas égal à 1, q2 est toujours égal à q .

entrez la description de l'image ici

Comme je l'ai déjà indiqué, l'étape 2 consiste à «déterminer le chiffre le plus élevé à cet endroit». Nous définissons donc r sur r2 , utilisons une boucle while pour décrémenter * p , déplacez r vers la gauche et remplissez la bande avec des 1, puis utilisez une autre boucle while pour déplacer r vers la droite et incrémentez à nouveau * p pour restaurer la valeur. N'oubliez pas que chaque boucle while s'exécute pour une itération de moins que la valeur sur laquelle nous l'utilisons; pour cette raison, le nombre de 1 écrits sera 3 de plus (plutôt que 4 de plus) que la valeur du chiffre, et la valeur finale stockée dans * p sera de 2 de plus. Ainsi, cela a effectivement décrémenté * p par 2.

Après cela, nous définissons p à la valeur de p2 et nous recommençons tout cela. Pour la deuxième fois, définissez q2 sur 0, recherchez la fin du nombre en déplaçant p vers la droite, puis parcourez les chiffres de ce nombre en décrémentant ensemble p et q2 . Une fois encore, nous allons rencontrer le 2 dans la cellule # −3 et écrire qu'il reste beaucoup de 1 dans * r .

Dans le cas du troisième nombre, on finit par ne rien faire car il n'a pas une place de centaines (donc q2 n'atteint jamais q ), mais c'est correct car cela n'affecte pas le calcul de la valeur maximale du chiffre.

entrez la description de l'image ici

Nous définissons également la cellule * (r - 4) , que j'ai marquée d'une flèche sans étiquette ici, sur 1 (même si elle est déjà à 1). Je ne vais pas vous dire pourquoi encore, mais peut-être que vous avez déjà deviné?

L'incrément suivant de * q nous amène à l'étape 3, qui est «soustrayez le chiffre maximum de tous les chiffres du lieu actuel». Comme précédemment, nous réinitialisons p sur 11 et q2 sur 0, puis examinons tous les nombres comme nous l’avions fait à l’étape précédente; sauf que cette fois, * q = 3 au lieu de 2. À chaque fois que q2 rencontre q et que p est à des centaines, nous utilisons une boucle while pour décrémenter * p autant de fois qu'il y a 1 dans le bloc restant de * r2 (5 dans notre exemple) en utilisant rcomme un pointeur en cours d'exécution. Nous le décrémentons encore une fois pour que le chiffre le plus grand finisse à -2, pour une raison qui deviendra claire plus tard:

entrez la description de l'image ici

Après avoir traité tous les chiffres, nous en sommes maintenant à la fin de la troisième étape. Nous effectuons ici deux choses singulières.

  • Premièrement, nous soustrayons également la taille du bloc- r (plus 1) de * q , mais en utilisant le pointeur r2 , qui le laisse à gauche. * q devient négatif de cette façon. Dans notre cas, le bloc- r a cinq 1, donc * q devient −3.
  • Deuxièmement, nous définissons une variable sur une valeur non nulle pour indiquer que nous entrons maintenant dans l’étape de sortie. (Techniquement, le fait que * q soit négatif indique déjà l'étage de sortie, mais c'est trop difficile à vérifier, d'où la variable supplémentaire.)

Vous comprenez maintenant que nous continuons à parcourir les nombres, à trouver le lieu actuel (indiqué par la valeur non-1 de * q ) dans chaque nombre et à faire quelque chose en fonction de la valeur de * q . Nous voyons que * q est d'abord incrémenté à 2 (= calcule la valeur maximale du chiffre), puis 3 (soustrayez la valeur maximale de chaque chiffre à cet endroit), puis nous le soustrayons pour le rendre négatif. À partir de là, il continuera à monter jusqu'à atteindre 1, rétablissant ainsi la valeur qui signifie «ne rien faire». À ce stade, nous passons à l’endroit suivant.

Maintenant, quand * q est négatif, nous produisons. * q est exactement à la bonne valeur pour que nous puissions sortir le bon nombre de lignes de caractères avant qu'il atteigne 1; si le chiffre le plus grand est 2, nous devons générer 3 lignes. Voyons ce qui se passe à chaque valeur de * q :

  • * q = −2:
    • Pour le premier nombre, * p est égal à -2, ce qui indique qu'il faut générer un '.'(point) ou un ':'(deux points). Nous décidons lequel en regardant q : si c'est -1, nous sommes à la place de uns, donc ':'nous produisons a (que nous calculons comme '8'+2), sinon a '.'.
    • Pour le second nombre, * p est −3. Tout ce qui n'est pas -2 signifie que nous produisons un '|'(tuyau) puis incrémentons la valeur. De cette façon, il atteindra −2 au bon endroit, puis nous produirons '.'s / ':'s pour le reste de ce chiffre.
    • Dans chaque cas, nous définissons également une variable pd sur 0 avant de traiter le nombre, et définissons pd (= "imprimé") sur une valeur non nulle pour indiquer que nous avons imprimé un caractère.
    • Pour le troisième numéro, aucun traitement n'a lieu car le troisième numéro n'a pas une place de centaines. Dans ce cas, pd sera toujours à 0 après le traitement du nombre, ce qui indique que nous devons toujours sortir un '|'(uniquement si out est différent de zéro, car sinon nous en sommes toujours aux étapes 2 ou 3).
    • Après avoir traité tous les nombres, si out est différent de zéro, créez une nouvelle ligne. Notez que nous avons besoin de la variable out pour ne pas sortir la nouvelle ligne à l’étape 2 ou 3.
  • * q = −1: comme avant, sauf que * p est égal à −2 pour les deux premiers nombres, donc les deux sorties a'.'(et la troisième sortie a'|'comme précédemment).
  • * q = 0: lorsque * q est 0, cela signifie «ne fait rien si nous sommes à la place de 1, sinon affiche une ligne de'|'s indépendamment de * p ». De cette façon, nous obtenons le remplissage entre les chiffres.

Maintenant, on incrémente q pour passer à l’endroit suivant, l’emplacement des dizaines, et on incrémente * q ici. Au début de l'étape 2, la bande ressemble à ceci:

entrez la description de l'image ici

Ensuite, nous effectuons la phase 2 comme avant. Rappelez-vous que ceci soustrait effectivement 2 de chaque chiffre de cet endroit et laisse également un nombre unaire de * r2 indiquant le chiffre maximum. Nous laissons le numéro unaire précédent et continuons d'étendre la bande vers la gauche; «nettoyer» ne coûterait que du code supplémentaire inutile. Lorsque nous avons terminé et que nous incrémentons * q , au début de l'étape 3, la bande est maintenant:

entrez la description de l'image ici

En fait, c'est un mensonge. Rappelez-vous plus tôt où j'ai dit que nous avons mis * (r - 4) à 1 et que je ne vous ai pas dit pourquoi? Maintenant je vais vous dire pourquoi. C’est le cas dans ce cas, où le chiffre le plus grand est en fait 0, ce qui signifie que tous les chiffres de cet endroit sont 0. Le réglage * (r - 4) , indiqué par la flèche non étiquetée ci-dessus, passe à 1 et prolonge le nombre unaire de 1, mais seulement dans ce cas particulier. De cette façon, nous prétendons que le chiffre le plus grand est 1, ce qui signifie que nous allons afficher une ligne supplémentaire.

Après l'étape 3 (soustrayez le nombre maximal de tous les chiffres de l'emplacement actuel), y compris l'étape supplémentaire qui rend * q négatif, la bande ressemble à ceci. La dernière fois, le plus gros chiffre était représenté par −2 dans le bloc * p , mais cette fois, ils sont tous −3 car ils sont tous en fait des zéros, mais nous prétendons que le chiffre maximum est un 1.

entrez la description de l'image ici

Voyons maintenant ce qui se passe lorsque * q progresse vers 1:

  • Lorsque * q = −1, les * valeurs sont égales à −3, ce qui signifie que nous produisons '|'s et les incrémentons.
  • Lorsque * q = 0, nous produisons '|'parce que c'est ce que nous faisons toujours lorsque * q = 0, indépendamment de * p .

Ainsi, nous obtenons deux rangées de tuyaux.

Enfin, nous nous déplaçons * q à sa place. Celui-ci devient intéressant car nous devons indiquer ':'s si le chiffre réel est différent de 1, mais '8'si c'est 1. Voyons comment se déroule le programme. Tout d'abord, nous incrémentons * q pour lancer l'étape 2:

entrez la description de l'image ici

Après l'étape 2 («calculer la valeur maximale du chiffre»), il ne nous reste plus que:

entrez la description de l'image ici

Après l'étape 3 («soustraire la valeur numérique maximale de tous les chiffres de l'emplacement actuel»), la bande se présente comme suit:

entrez la description de l'image ici

Examinons maintenant chaque itération de * q :

  • * q = −2:
    • Premier nombre: déjà à -2, sortez donc a ':'(plutôt que '.'car q = −1).
    • Deuxième nombre: à -4, affiche donc a '|'et incrémente.
    • Troisième nombre: à -3, donc sortie a '|'. Toutefois, cette fois, au lieu d’incrémenter, un cas particulier se déclenche. Seulement si nous sortons la dernière place ( q = −1), et que nous sommes dans l'avant dernière ligne pour cela ( * q = −2), et que le chiffre est en fait un 1 ( * p = −3) , alors au lieu de l’incrémenter à -2, nous le fixons à -1. En d'autres termes, nous utilisons -1 comme valeur spéciale pour indiquer que lors de la prochaine itération, nous aurons besoin de produire '8'au lieu de ':'.
  • * q = −1:
    • Premier nombre: déjà à -2, donc sortie a ':'.
    • Deuxième nombre: à -3, donc sortie a '|'. La condition spéciale ne se déclenche pas car * q n'est plus −2. Par conséquent, incrémentez.
    • Troisième nombre: à -1, donc sortie '8'.
  • * q = 0: Normalement, nous afficherions la ligne de remplissage de'|'s ici, mais dans le cas particulier où nous sommes à la place de uns ( q = −1), nous ignorons cela.

Après cela, q est incrémenté à 0 et la boucle big while se termine.

Maintenant, vous savez comment une entrée 202,100,1fonctionne. Cependant, il y a un autre cas spécial que nous n'avons toujours pas couvert. Vous vous souviendrez peut-être que lors du traitement de la dernière position, lorsque * p était −3, nous le fixons à −1 pour le 1(au lieu de l'incrémenter à −2) afin que l'itération suivante produise un à la '8'place. Cela ne fonctionne que parce que nous avons une itération dans laquelle * p est égal à −3 et que nous décidons de l'incrémenter ou de le définir sur −1. Nous n'avons pas une telle itération si tous les chiffres de la position des unités sont 0 ou 1. Dans un tel cas, toutes les * p valeurs pour les 1 commenceraient à −2; il n'y a aucune possibilité de décider de le mettre à −1plutôt que de l'incrémenter de -3 . De ce fait, il existe une autre condition de casse spéciale à l’étape 3 («soustrayez le chiffre maximum de chaque chiffre de l’emplacement actuel»). J'ai prétendu qu'après avoir soustrait la valeur de chiffre maximum de chaque chiffre (à quel point le chiffre maximum est à -1), nous le décrémentons encore une fois, mais en réalité, il existe une condition qui se présente comme suit:

Si le chiffre que nous regardons est égal au chiffre maximum à cet endroit ( * p = −1), et que cet endroit est celui des unités ( q = −1), et que le chiffre maximum est 1 ( * (r + 5) = 0, c'est-à-dire que le bloc unaire à l'extrême gauche ne contient que 5 cellules), alors seulement , nous laisserons * p en -1 pour indiquer que la seule itération de la sortie doit générer un '8'. Dans tous les autres cas, nous le décrémentons une fois de plus.

Terminé. Bonne année!

  • Edit 1 (3183 → 3001): De bonnes fêtes de golf! J'ai réussi à me débarrasser entièrement des variables p2 et r2 ! p se bouscule maintenant pour trouver le début et la fin des nombres, mais il semble que le code soit plus court. J'ai aussi essayé de me débarrasser de q2 , mais je ne pouvais pas raccourcir le code de cette façon.

    J'ai également trouvé quelques endroits supplémentaires où je pourrais appliquer des astuces de golf non lisibles typiques, comme réutiliser la dernière valeur d'une boucle while. Pour vous donner un exemple, au lieu de

    while *(++p) { 1 }         // just increment p until *p is 0; the 1 is a noop
    if (pd) { x } else { y }   // where pd is a variable
    

    Je peux sauver le '""""(faites le premier, puis le second) et le '"""(constant 1) en l'écrivant de la même manière

    if (while *(++p) { pd }) { x } else { y }
    

    Bien sûr, cela ne fonctionne que si je sais que la boucle while sera exécutée pendant au moins une itération, mais si c'est le cas, sa valeur de retour est pd , je peux donc l'utiliser comme condition pour le if.


"Illisible" est certainement un nom qui convient ...
Alex A.

9
-1 pas assez d'explications
Le gars avec le chapeau

7

Javascript (ES6) 750 744 690 604 498 346 245 234 octets

Je suis nouveau à PPCG et j'ai pensé que je pourrais essayer celui-ci en pensant que c'était plutôt simple. Boy était je me suis trompé !! Cela fait un moment que je travaille dessus et j'ai beaucoup de golf à faire ... Les
suggestions sont encouragées! - Bien que donner un sens à cela ne soit pas chose facile.

Sort des cordes quand l'entrée est un tableau de nombres (par exemple:) [204, 1].

a=>(o=m=s="",l=a.map(n=>(s+="|",l=(n+"").length)>m?m=l:l),h=[],a=a.map((n,i)=>[..."0".repeat(m-l[i])+n].map((d,j)=>d<h[j]?d:h[j]=d)),h.map((n,i)=>{i?o+=s+`
`:0;for(j=n;j--;o+=`
`)a.map(d=>o+="|.:8"[d[i]-j<1?0:i<m-1?1:d[i]-1?2:3])}),o)

Explication

a=>(

  o=m=s="",                      // m = max number of digits in a number, s = separator string         
  l=a.map(n=>(                   // l = lengths of each number
      s+="|",                    // set the separator string
      l=(n+"").length                 // convert each number to a string
    )>m?m=l:l                    // get max length
  ),
  h=[],
  a=a.map((n,i)=>
    [..."0".repeat(m-l[i])+n]    // add leading 0s to make all same length
    .map((d,j)=>d<h[j]?d:h[j]=d) // set each digit of h to max
  ),

  h.map((n,i)=>{
    i?o+=s+`
`:0;
    for(j=n;j--;o+=`
`)
      a.map(d=>
        o+=
          "|.:8"[
            d[i]-j<1?0
            :i<m-1?1
            :d[i]-1?2:
            3
          ]
      )
  }),
  o
)

Exemple

Entrée: tableau de nombres: [4,8,15,16,23,42]
sortie:

|||||.
|||||.
||||..
||....
||||||
|:||||
|:||||
|:|:||
|:::||
::::||
:::::|
::::::
::::::

+1 golf impressionnant. Voulez-vous inclure un exemple avec entrée et sortie?
DavidC

@ David C Merci! Et l'exemple est inclus. Appelez-le depuis la console et il retourne une chaîne. :)
Aᴄʜᴇʀᴏɴғᴀɪʟ

7

Python 3, 624 598 595 574 561 535 532 527 525 426 345 328 324 294 288 286 283 280 267 265 255 251 245 238 235 234 230 228 octets

z=input().split();v=max(map(len,z));d=''.join(i.zfill(v)for i in z);x=['']*len(z)
for k,c in enumerate(d):j=k%v;m=int(max(d[j::v]));c=int(c);x[k//v]+="|"*(m-c+0**m+(j>0))+":8."[(c<2)|-(j<v-1)]*c
for r in zip(*x):print(*r,sep='')

Comme cette question nécessitait une réponse, j’en ai fourni une ici, où l’entrée devrait être une chaîne de nombres séparés par des espaces, tels que "204 1". Boy, est-ce long? Toutes les suggestions de golf (ou de meilleures réponses) sont les bienvenues.

Edit: Octets enregistrés en mélangeant des tabulations et des espaces.

Edit: J'ai sauvegardé beaucoup d'octets en changeant la façon dont j'ai obtenu les chiffres d'un nombre (faire une liste à partir de la chaîne de chiffres complétée de zéros, puis dans le corps du code, transposer pour obtenir des centaines de chiffres, dix chiffres, etc. .)

Edit: Et j'ai économisé un peu plus en incorporant cette dernière :8boucle dans la boucle quipu principale. Maintenant, si seulement je pouvais comprendre pourquoi b=d[j*v+i]==m(d[i::v])ne fonctionne pas. Compris et la solution prend trop d'octets. (Le nombre d'octets a également été supprimé car les onglets ont été redéfinis en quatre espaces. Il s'agissait probablement du format de bloc de code sur ce site)

Edit: j'ai réorganisé comment fait le quipus. Maintenant, il crée un brin à la fois, puis transpose pour l’impression.

Edit: a transformé ma réponse en un programme Python 3 pour enregistrer davantage d’octets.

Edit: j'ai trouvé un bogue dans mon code qui l'a fait de sorte qu'il n'imprimait pas correctement les zéros au milieu des nombres (voir le cas de test 204 1ci-dessus). En corrigeant cela, j'ai réussi à jouer au golf :)

Edit: J'ai changé l'impression pour économiser 10 octets. Et je remets tous les vieux comptes d'octets en arrière, juste parce que.

Edit: Golfé l'attribution d' vutiliser mappour quatre octets. Crédit à CarpetPython , comme l’a leur réponse ici .

Edit: Tourne le milieu "boucle pour dans une boucle", en une boucle pour six octets.

Edit: maintenant en utilisant enumerate. Ne plus utiliserl=len(z) . A transformé le ternaire if-elseen une liste ternaire. Voir ci-dessous pour plus de détails.

Modifier: Sp3000 a suggéré d’éditer printet d’éditer la condition ternaire qui enregistrait un octet.

Ungolfed:

s = input()
z = s.split()
v = max(map(len, z))                # the amount of digits of the largest number
d = ''.join(i.zfill(v) for i in z)  # pad zeroes until every number is the same length
                                     # then join the numbers into one string
x = ['']*len(z)                     # a list of strings for the output, one for each number

for k,c in enumerate(d):          # for every digit in every number
    i,j = divmod(k, v)            # i is the index of the number we're on
                                   # j is the index of the digit of the number we're on
    m = int(max(d[j::v]))         # the largest of all the digits in the j-th place
    c = int(c)                    # the digit in j-th place of the i-th number
    x[i] += "|"*(m-c+0**m+(j>0))  # pad | to size m-c, until the knots are correctly spaced
                                  # add a | if m<1, all j-th place digits are 0
                                  # add a | if j>0, if it's not at the start, as delimiters
    x[i] += ":8."[(c<2)|-(j<v-1)] * c
    # this is essentially the following code
    # if j<v-1:
    #     x[i] += "."*c      # . knots if not in the units place
    # else:
    #     if c == 1:
    #         x[i] += "8"*c  # 8 knots for ones in the units place
    #     else:
    #         x[i] += ":"*c  # : knots for something else is in the units place

for r in zip(*x):       # transpose so all the rows (the quipu strings) now hang down
    print(*r, sep='')    # join the strings together at each knot
                         # and print each on a separate line

Y at-il quelque chose de spécifique à Python 3 ici? Sinon, le convertir en Python 2 pourrait vous épargner quelques octets
Cyoce

@ Cyoce Rien de trop spécifique à Python 3. Je viens de commencer avec Python 3 car c'est la version que j'ai. Je vais tester une version Python 2 sur ideone ou quelque chose du genre.
Sherlock9

@ Maltysen Cela ne fonctionne pas avec les entrées qui commencent par 0, comme 0 12 4.
Sherlock9

Vous pouvez économiser des octets en alternant des tabulations et des espaces pour l'indentation dans Python 2. Je crois qu'un caractère de tabulation == 8 espaces selon l'analyseur d'indentation de Python
Cyoce

for r in zip(*x):print(''.join(r))->print(''.join(r)for r in zip(*x))
Leaky Nun

4

C, 238 235 octets

S'appuyant fortement sur le préprocesseur C pour rendre le code aussi court que possible. En tant qu'effet secondaire, le rend également à peu près illisible.

#define l strlen(a[i])
#define d l<k||a[i][l-k]-48
#define m(e) for(i=1;a[i];e<=r?i++:r++);
#define p(e) {m(!putchar(e?'|':k>1?46:d<2?56:58))puts("");}
k,r;main(int i,char**a){m(l)for(k=r,r=1;k;r=k>1){m(d)for(;r;r--)p(d<r)if(--k)p(1)}}

Sur Ubuntu 14.04, vous pouvez compiler le code simplement gcc quipu.c(ignorez les avertissements). Un exemple d'exécution de l'exécutable:

$ ./a.out 1 2 3 2 1
||:||
|:::|
8:::8

Testé contre tous les cas de test de l'OP.

Code source non-golfé:

// Standard library; leaving out the includes still gives executable code despite the warnings.
#include <stdio.h>
#include <string.h>

// 4 preprocessor macros.
// Note: some of these actually make use of the fact that parentheses have been left out

// l: length of argument i
#define l     strlen(a[i])

// d: shorthand for a digit
#define d     l<k || a[i][l-k]-'0'

// m: loop across all arguments; calculates r as the maximum of expression e
#define m(e)  for (i=1; a[i]; e<=r ? i++ : r++);

// p: prints one line of output
// note: intentionally does not use the r++ code branch of m;
//       putchar always returns a non-zero number here, so !putchar is zero,
//       which is always <=r (because r is never negative)
// note: the semicolon after m(...) is redundant;
//       the definition of m already contains a semicolon
// note: puts("") outputs a newline
#define p(e)  { m(!putchar(e ? '|' : k > 1 ? '.' : d < 2 ? '8' : ':')); puts(""); }

// k: knot position; 1 for units, 2 for tens, 3 for hundreds...
int k;

// r: input and output value for m
// note: the first time we call m, we need r to be zero;
//       by defining it outside main, it is automatically initialized as such
int r;

// function main
// note: parameter i (normally named argc by convention) is not needed
//       (the last element of argv is known; it is followed by a NULL pointer)
//       but we cannot leave it out (otherwise we cannot access argv)
//       so it serves as a local variable (to loop through arguments; see m)
// note: parameter a (normally named argv by convention)
//       is the array of arguments (starting from index 1)
int main(int i, char **a)
{
    // Determine the longest argument; store its length in r.
    // This is the number of knot positions to consider.
    m(l)

    // Iterate k through the knot positions from top to bottom.
    // Note: k > 0 has been abbreviated to k.
    // Note: for each iteration, we also initialize r with either 0 or 1.
    //       0 = suppress printing when all knots are zero
    //       1 = always print, even when all knots are zero
    for (k = r, r = 1; k > 0; r = k > 1)
    {
        // Determine the highest digit at this knot position.
        // Note: due to the absence of parentheses, d mixes up with <=r into:
        // (l < k) || (a[i][l-k]-'0' <= r)
        m(d)

        // Count the digits down.
        for (; r; r--)
        {
            // Print a single line of output.
            // When d (the digit in the current strand) is less than the counter,
            // then print a '|', otherwise print a knot.
            p(d < r)
        }

        // Decrement k (go to next knot position).
        // If this was not the last iteration...
        if (--k > 0)
        {
            // Print separator line.
            p(1)
        }
    }

    // Return exit code zero; redundant.
    return 0;
}

Toutes nos félicitations! En tant que réponse la plus courte publiée au cours de la période de prime, vous avez reçu ma prime de +50 rep. Bonne réponse! :)
Alex A.

4

Mathematica 436 453 357 352 347 octets

t=Transpose;y=ConstantArray;a=Table;
g@j_:=(s=t[PadLeft[#,Max[Length/@i]]&/@(i=IntegerDigits@#)]&;p_~u~o_:=(m=Max@p;c=If[o==-2,":","."];w=If[o==-2,"8","."];p//.{0->a["|",Max@{1,m}],1->Join[a["|",{m-1}],{w}],n_/;MemberQ[2~Range~9,n]:>Join[y["|",m-n ],c~y~n]});t[Join@@@t@Join[u[#,0]&/@Most@#,u[#,-2]&/@{#[[-1]]}]]&[Riffle[(s@j),{a[0,Length@j]}]]//Grid)

Ce qui précède

  • Divise chaque entier en une liste de chiffres, en utilisant IntegerDigits ; touche chaque chiffre avec des zéros à gauche (pour assurer un espacement égal); chaque numéro d'entrée, maintenant décomposé en chiffres, correspond à une ligne d'un tableau; chaque colonne représente une valeur de position. Le tableau est transposé.
  • Remplace les chiffres par une liste de nœuds avec un rembourrage. Une routine de correspondance de motif légèrement différente est utilisée pour les unités.

Exemple

g[Range[0, 50]]

cinquante


Transpose@Join? Cela devrait être à, non?
CalculatriceFeline

Oui. Merci d'avoir attrapé ça.
DavidC

Espace juste avant ça.
CalculatorFeline

1

R - 446 444

Je vois qu'il n'y a pas encore de solution R, alors en voici une. La fonction prend un vecteur avec des entiers.

function(x){r=nchar(max(x));c=length(x);m=matrix(0,r,c);for(i in 1:c){t=as.numeric(strsplit(as.character(x[i]),"")[[1]]);m[(r+1-length(t)):r,i]=t};Q=c();for(i in 1:r){d=m[i,];z=ifelse(max(d)>0,max(d),1);q=matrix("|",z,c);for(j in 1:c){v=m[i,j];if(i==r){if(v==1)q[z,j]=8;if(v>1)q[(z-v+1):z,j]=rep(":",v)};if(i<r){if(v>0)q[(z-v+1):z,j]=rep(".",v)}};if(i!=1&sum(d)>0)q=rbind(rep("|",c),q);Q=rbind(Q,q)};for(i in 1:nrow(Q))cat(Q[i,],sep="",fill=T)}

Ungolfed

# Some test data
test <- c(201, 0, 100, 222, 53)

# Define function
quipu <- function (x) {

    # Create matrix with a row for each digit and a column for each number
    r=nchar(max(x));c=length(x);m <- matrix(0,r,c)
    for(i in 1:c) {
        t=as.numeric(strsplit(as.character(x[i]),"")[[1]])
        m[(r+1-length(t)):r,i]=t
    }

    # Loop through each row (digit) starting at the top of the quipu
    Q=c() # Empty matrix to store quipu 
    for(i in 1:r){

        d=m[i,]
        z=ifelse(max(d)>0,max(d),1)
        q=matrix("|",z,c)

        # Loop through each column (number in the vector) starting at the leftmost quipu
        for(j in 1:c){

            # The digit
            v=m[i,j]

            # If it is the last segment of the quipu
            if(i==r){
                if(v==1){q[z,j]=8} # If unit digit =1
                if(v>1){q[(z-v+1):z,j]=rep(":",v)} # If unit digit >1               
            }

            # If it is not the last segment of the quipu
            if(i<r){
                if(v>0){q[(z-v+1):z,j]=rep(".",v)} # If non-unit digit >0   
            }
        }

        # Add segment to Q
        if(i!=1 & sum(d)>0){q=rbind(rep("|",c),q)}
        Q=rbind(Q,q)    
    }

    # Print quipu
    for(i in 1:nrow(Q)) {cat(Q[i,], sep="", fill=T)}
}

# Test
quipu(test)

Avez-vous besoin if(v>0)de votre if(i<r)clause? Est-ce que R accepte une plage comme z+1:zquand v==0? Si cela q[z+1:z,j]ne devait pas du tout être affecté, je penserais. Aussi, R a-t-il un elsemot clé et une sorte de else ifmot clé? Si tel est le cas, vous pourrez jouer au golf avec certaines de ces conditions.
Sherlock9

if(v>0)est nécessaire car, si v=0, l’indice sera hors limites (c’est-à-dire qu’il essaiera d’obtenir la ligne suivante + 1). R l’a fait else, et j’ai en fait essayé votre suggestion et utilisé elseautant que possible, mais il s’est avéré qu’il s’agissait du même nombre d’octets.
Loris lente
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.