Conteggio di Quipu: Base 10 nel Nuovo Mondo


41

Il quipus è un antico dispositivo usato dagli Inca nell'era precolombiana per registrare i numeri in un sistema di dieci posizioni posizionali di nodi su una corda, che funziona come segue:

Ogni gruppo di nodi è una cifra e ci sono tre tipi principali di nodi: semplici nodi passanti; "nodi lunghi", costituiti da un nodo sopraelevato con uno o più giri aggiuntivi; e figura otto nodi.

  • I poteri di dieci sono mostrati per posizione lungo la corda e questa posizione è allineata tra i fili successivi.
  • Le cifre in posizioni per 10 e potenze superiori sono rappresentate da gruppi di nodi semplici (ad esempio, 40 è quattro nodi semplici in fila nella posizione "decine").
  • Le cifre nella posizione "una" sono rappresentate da nodi lunghi (ad esempio, 4 è un nodo con quattro giri). A causa del modo in cui i nodi sono legati, la cifra 1 non può essere mostrata in questo modo ed è rappresentata in questa posizione da una figura di otto nodi.
  • Lo zero è rappresentato dall'assenza di un nodo nella posizione appropriata.

Dettagli

Per questa sfida, ogni componente di un quipu rappresenta un singolo numero (anche se, come afferma l'articolo di Wikipedia, puoi farlo rappresentare molti numeri su una parte, in questa sfida non lo faremo).

nodi

Ogni nodo sarà rappresentato da un singolo carattere ASCII.

  • . rappresenta un semplice nodo
  • : rappresenta un giro di un lungo nodo
  • 8 rappresenta un nodo a otto cifre
  • | rappresenta l'assenza di un nodo e un delimitatore tra le cifre.

Costruire Quipus

I quipu sono costruiti seguendo queste regole.

  1. I fili vanno dall'alto verso il basso in ordine decrescente di posizione (come in, la cifra delle unità sarà all'estremità inferiore di un filo). Le cifre lungo un filo sono separate dal carattere ( |).
  2. La potenza di 10 che rappresenta una cifra è determinata dalla sua posizione lungo il filo nello stesso modo in cui una potenza di 10 cifre di una cifra sarebbe calcolata usando il suo indice in un numero con il nostro sistema numerico. Cioè, 24con 2a al posto delle decine e 4a al posto delle unità, saranno rappresentati da due nodi, un delimitatore ( |), quindi quattro nodi.
  3. Le cifre nella stessa posizione sono allineate verso la parte inferiore del filo. Se una cifra in una posizione avrà meno nodi di altre cifre di altri numeri nella stessa posizione, l'assenza di quei nodi è rappresentata da ( |).
  4. Nodi consecutivi semplici ( .) rappresentano un valore nella loro posizione.
  5. Ogni cifra è rappresentata da almeno 1 carattere. Quando un valore di cifre è 0 per tutti i numeri in un quipu, è rappresentato dall'assenza di un nodo ( |).
  6. Il posto dell'unità è trattato in modo speciale. Uno nel posto delle unità è rappresentato da una figura-otto nodi ( 8). Un valore di due o più al posto delle unità è rappresentato da nodi lunghi consecutivi ( :).
  7. Quando la cifra delle unità è 0 per tutti i numeri in un quipu, l'assenza di un nodo non viene stampata, ma viene conservato il delimitatore finale per la cifra delle decine.
  8. Non c'è delimitatore che segue la cifra delle unità.

Regole

  • L'input consisterà in un elenco non vuoto di numeri interi non negativi che possono essere ricevuti tramite uno dei metodi di input predefiniti . Si può presumere che questi numeri interi siano tutti inferiori o uguali a 2147483647o 2^31-1. Mentre i casi di test sono delimitati da spazi, il formato di input può separare gli input in qualsiasi modo conveniente per la tua lingua, sia che sia separato da virgole, separato da nuova riga, in un array e così via.
  • L'output è costituito da un unico Quipu costruito secondo le regole sopra descritte. L'output può essere fornito tramite uno dei metodi di output predefiniti .
  • Il tuo codice dovrebbe essere un programma o una funzione, sebbene non debba essere una funzione con nome.
  • I nodi impiegano un po 'di tempo per legare in modo da risparmiare tempo, il tuo codice il più corto possibile.

Come sempre, se il problema non è chiaro, per favore fatemi sapere. Buona fortuna e buon golf!

Esempi

Ingresso:

5 3 1 0

Produzione:

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

Ingresso:

50 30 10 0

Produzione:

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

Ingresso:

330

Produzione:

.
.
.
|
.
.
.
|

Ingresso:

204 1

Produzione:

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

Ingresso:

201 0 100 222

Produzione:

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

Ingresso:

1073741823 2147483647

Produzione:

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

Ingresso:

0

Produzione:

|

Casi di prova più lunghi

Ulteriori letture


Risposte:


3

Pyth, 64 byte

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

Provalo online!

Come funziona

=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)

Questa è una risposta eccellente, tranne per un problema. Il nodo finale non è sempre un nodo a otto cifre 8. In effetti, è solo un 8nodo quando l'ultima cifra è un 1 (vedi regola 6). Stai convertendo tutti i nodi finali e questo non corrisponde alle specifiche. Inoltre, provalo online! il link ha un codice diverso da quello pubblicato qui, a quanto pare
Sherlock9

22

Illeggibile , 3183 3001 byte

Questa è stata una sfida divertente su cui lavorare, accendere e spegnere tra le celebrazioni natalizie. Grazie per la pubblicazione! Giocare a golf è stato interessante perché le specifiche sono piene di eccezioni e casi speciali, che hanno richiesto molte condizioni. Inoltre, mentre non ho bisogno di convertire da e verso decimali questa volta, ho avuto bisogno di una funzione “max” di sorta per determinare il maggior numero di cifre in ogni numero e il valore più grande delle cifre in ogni luogo.

La prima versione di questo era 4844 byte, solo per darti un'idea di quanto ho giocato a golf.

Il programma prevede l'input come un elenco di numeri interi separati da virgola . Nessuno spazio o newline. L'uso di questi produrrà un comportamento indefinito.

' '' '' ''' "" ' ''' "" ' ''' "" ' '' ' ' '' '' '''' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" "" "" ' ''' "" ' ''' "" ' ''' "" ' '' " ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" '"" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" "" "" '" "" "" "" " ' '' ' ' '''' ' ' '''' ' ' '''' '' '' ' ' '''' '''" " ' '''" "' "" ' ''' "" ' ''' "" ' '' ' ' '' '' ' ' '' '' '''' '''' '' '' '' "' '' ''"" "' '' ' ' '' '' '''' '' '' ''" ' '' ' ' '''' "' '' '' ''"' '' '' '' '' ' '' ' ' '' '' ' ' '''' '' '' ' ' '''' ' ' '''' '''' '' '' '' '' " ' '' ''' "" "" "" ' ''' "" ' '' "' '' '' '' ' ' '''' ' ' '''' ' ' '''' "' ''"'""" "" "" "" ' '' '' ''' "" "" "" ' ''' "" " ' '''" "" "" "" ' ''' "" " ' '' ' '' '' ' ' '' '' '''' ' ' '''' ''' "" "" "" "" ' '' '' '' ' ' '''' "' ''" ' '' '' ''' "" ' ''' "" ' '' ' ' '' '' '' '''' '' '' ''' "" ' ''' "" '""" ' '' '' ''' "" "" "" ' '' ' ' '' '' '' '''' '' '' ''' "" "' ''"' '' '' "" ' '' ' ' '' '' '' '''' ''' "" "" "" ' ''' "" ' '' "' '' '' "' '' '' ''" ' '' '' '' ' ' '' ' ' '' '' '''' '''' '' '' '' "' '' '' '' "' ''"' ''"" " ' '' '' '''" "" ' ''' "" "" "" "' '' ' ' '' '''' '' '' ' ' ''''"' '' ' '' ' ' '' '' '' '''' ''' "" "" " ' '' '' '' '''" "" "" "' '' '' ''"' '' " ' '''" "" "" "" ' '' '' '' "' '' "' '' '' '' ''" ' '' '' '' ''"' ''"" "" "' '' '' ''"' '' ' ' '' ' ' '' '' '' '' ' ' '''' '' '' '''' '''' '' ' '' '' '' ''' "" " ' '' '''" "" " ' '' '' '''" "' '' ' ' '''' ' ' ''''"' "" ' ''' "" ' ''' "" "' '' ''" ' '' '' '' ' ' '' '' '''' "' '' ' ' ''''"" "" "" ' ''' "" " ' '' '''" "" " ' '' '' ' ' '' '' '''' ' ' '''' ' ' '''' " ' '''" " ' '' ' ' '' '' '''' ' ' '''' ' ' '''' '''" "" "" "" ' '' '' ''' "" ' '' ' ' '''' '' '' ''' "" ' '' "' '' "' '' ''" ' '' '' ''"' '' '' "" ' '''" "" ' '' '' '' ''' "" "" "" " ' '''" "" ' '' '' '' '' "' '' '' ''" "' '' '' '' ' ' '' '' '''' ' ' '''' ' ' '''' ' ' ''''" ' '' "' '' '' '' '' ' '' '' '' ' ' '''' ' ' '''' ' ' '''' ' ' '''' ''' "" "" "" "" " ' '' ''"" "" ' '' '' '' ''' "" "" "" "' '' '' ''" ' '' "' '' '' '' ''"' '' '' '' " ' '''" " ' '''" "" ' '' '' ''' "" ' ''' "" ' ''' "" "'" ' '' '' '' '' "' "" ' '' '' '' ' ' '' '' '' ' ' '''' '''' '' '' '' ''' "" ' ''' "" """"" ' '' '' '' ' ' '''' ''' "" "" ' '' '' ''' "" "" "" " ' '''" "" ' '' ''" "" "" ' '' '' '' '' ' ' '''' '' '' ''' "" "' ''" ' '' '' '' '' ' ' '''' "' "" "" "" "' '' '' ''" ' '' "' '' "' '' '' '' '' ' ' '''' ' ' '''' ''""" " ' '' '' '' ' ' '''' '''" "" ' '' '' '' ''' "" " ' '''" "" "" "" ' ''" "" "" ' ''' "" " ' '' '' '' '''" "" "" "" "' ''" ' '' '' '' "' '' '' '' '' ' '' "' '' '' '' '' "' '' '' ''" ' '' '' ''"' '' "' '' '' '' ''" ' ''' '' '' '' "' '' "' '' '' '' ' ' '''' ' ' '''' ' ' ''''" ' '' ' ' ''''"' " "" "" "" ' ''' "" ' ''' "" ' ''' "" " ' '' '' '' ' ' '' '' '' '''' '''" "" "" "" ' ''' "" ' ''' "" ' ''' "" " ' '' '''" "" "" "" "" ' '' '' '' ''"' ''' "" "" " ' '' '' '' ' ' '' '' '''' ' ' '''' '''" "" "" "" " ' '' '' '' " ' '''" " ' '' ' ' '' '' '''' '' '' '''" " ' '' ' ' '' '' '' '''' '' '' '' ' '' '' '' ' ' '''' ''' "" "' '' '' '' ''"' '' '' '' ' ' '''' ' ' ''''" ' '''" "" "" "" ' ''' "" ' '' "' '' ' ' '' '' '' '' ' ' '''' '' '' ''''" " ' '' ' ' '' '' '' '''' '''" "" "" " ' '' '' '' ' ' '''' '''" "" "" "" "' "" "" "" " ' '' '' '' ' ' '''' '''" "" ' '' '' "' '' '' ''" ' '' '' ''' ''' "" ' '' ' ' '''' '' '' ''' "" ' ''' "" "' '' ' ' '' '''' ''"' '' '' " ' '' '' '''" "" "" "" ' ''' "" " ' '' '' '' '''" "" "" "" ' '' '' '' "'" "' '' ' ' '' '' '''' '' '' ' ' '''' ' ' '' ' ' '' '' '' '''' '' '' ''''" ' '''" "" ' '' "' '' '' ' ' '' '' '' ' ' '' '' '''' ' ' '''' '''' "' ''" "" "" ' ''' "" ' '' ' ' '' '' '''' '' '' ''' "" ' '' ' ' '''' '' '' ''' "" "" "" " ' '''" "" ' '' '' '' '' ' ' '''' '' '' ''' "" " ' '' '' '''" """" "" " ' '' '' '' '''" "" "" "" " ' '' '' '' '''" "" "" "" ' ''' "" ' ''" ' '' "' '' "' ''" ' '' '' '' ''"' '' '' "' '' '' '' ' ' '' '' ''''" ' '' " ' ''' "" "" "" " ' '''" "" ' '' '' '' ' ' '''' ' ' '''' "' '' "' ''"'""" "" "" "" ' '' '' '' ' ' '''' ' ' '''' ''' " ' '' '' '' ' ' '' '' '' '''' "" ' '' "' '' '' '' '' ' ' '' '' '' '''' '' '' '' ' ' '' '' '' '''' '' ''" "' '' '' ''"' '' " ' '' '' '' '' ' ' '' '' '' ' ' '''' ' ' '''' '''''"" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' '' " ' '' ' ' '' '' '''' '' '' ''' "" " ' '' '' '' '''" "" "" " ' '''" " ' '''" "" ' '' '' "' '' '' '' "' ''" "" " ' '''" " ' '' ' ' '' '' '' '''' '' '' '''" " ' '''" "" ' '' '' '''"" "" "" " ' '' ' ' '' '' '' '''' '' '' '''" "" "" "" ' '' "' ''"

Spiegazione

Ti guiderò attraverso il funzionamento del programma, mostrandoti come elabora l'input specifico 202,100,1.

All'inizio costruiamo alcuni valori di cui avremo bisogno in seguito, principalmente i codici ASCII dei caratteri che verranno emessi.

inserisci qui la descrizione dell'immagine

Come puoi vedere, '8'e '.'sono già disponibili. '|', tuttavia, è davvero 124, non 14. Usiamo un ciclo while per aggiungere il doppio del valore temporaneo nello slot # 1 su di esso per ottenere 124 (che è 14 + 55 × 2, perché il ciclo while funziona per 56-1 = 55 iterazioni). Ciò consente di risparmiare alcuni byte perché letterali interi di grandi dimensioni come 124 sono molto lunghi. Nel diagramma seguente, mostro la posizione di ogni variabile utilizzata dal programma.

inserisci qui la descrizione dell'immagine

Successivamente, vogliamo inserire tutti i caratteri e memorizzarli sul nastro a partire dalla cella # 12 ( p è il puntatore in esecuzione per questo). Allo stesso tempo, vogliamo sapere quanto è lungo il numero più lungo (quante cifre). Per raggiungere questo obiettivo, manteniamo un totale parziale in unario andando a sinistra a partire dalla cella # −1 (usiamo q come puntatore corrente). Dopo il primo numero di input ( 202), il nastro ora appare così:

inserisci qui la descrizione dell'immagine

Avrai notato che i numeri sono disattivati ​​di 4. Bene, quando li inseriamo per la prima volta, sono i loro valori ASCII, quindi sono "off" di 48 e la virgola è 44. Per ogni carattere, copiamo il 46 da '.'in r e quindi sottralo con un ciclo while (che sottrae 45) e quindi aggiungiamo 1. Lo facciamo in modo che la virgola (il nostro separatore) sia 0, quindi possiamo usare un condizionale per riconoscerlo.

Inoltre, avrai notato che lasciamo la cella n. 11 a 0. Abbiamo bisogno che riconosca il limite del primo numero.

Il prossimo carattere sarà una virgola, quindi memorizziamo uno 0 in # 15, ma ovviamente questa volta non avanziamo q . Invece, riportiamo q su 0 e iniziamo a "sovrascrivere" gli 1 che abbiamo già inserito.

Dopo che tutti i caratteri rimanenti sono stati elaborati, otteniamo questo:

inserisci qui la descrizione dell'immagine

Come puoi vedere, gli 1 scritti da q ora indicano (in unario) la lunghezza del numero più lungo.

Ora usiamo un ciclo while per spostare q all'estrema sinistra, quindi posizioniamo un altro puntatore lì che chiamerò r2 . Lo scopo di r2 diventerà chiaro in seguito.

inserisci qui la descrizione dell'immagine

A questo punto, vorrei chiarire la terminologia che userò in tutto questo.

  • Per numero , intendo uno dei numeri di input separati da virgole. Nel nostro esempio, sono 202, 100 e 1.
  • Per cifra , intendo una singola cifra in uno specifico dei numeri. Il primo numero ha 3 cifre.
  • Per luogo , intendo il posto di uno, il posto di decine, il posto di centinaia, ecc. Quindi, se dico "le cifre nel posto corrente", e il posto corrente è il posto di quelle, quelle cifre sono 2, 0 e 1 in quella ordine.

Ora torniamo alla nostra programmazione regolare. L'intero resto del programma è un grande loop che sposta q in avanti fino a raggiungere la cella # 0. Ciascuna delle celle lungo la strada rappresenta un luogo, con quelle posizionate all'estrema destra e q inizierà nel punto più significativo. Nel nostro esempio, questo è il posto delle centinaia.

Procediamo incrementando i punti q della cella in (ovvero, * q ).

inserisci qui la descrizione dell'immagine

Siamo ora allo "stadio 2" per le centinaia di posti. In questa fase, scopriremo qual è la cifra più grande tra tutte le cifre nelle centinaia. Usiamo lo stesso trucco di conteggio unario per questo, tranne che questa volta il puntatore si chiama r e il puntatore r2 segna la sua posizione iniziale alla quale dobbiamo reimpostarlo ogni volta che passiamo al numero successivo.

Cominciamo con il primo numero. Iniziamo impostando p su 11 (la posizione iniziale codificata di tutti i numeri). Quindi usiamo un ciclo while per trovare la fine del numero e impostiamo p2 lì per contrassegnare la posizione. Allo stesso tempo, impostiamo anche q2 su 0:

inserisci qui la descrizione dell'immagine

Non lasciarti distrarre dal fatto che q2 punta nei var. Non abbiamo un riempimento di una cella vuota perché possiamo rilevare la cella # 0 semplicemente perché è il numero zero.

Quindi, passiamo attraverso il numero corrente diminuendo p e q2 insieme fino a quando * p è zero. In ogni luogo, il valore di * q2 ci dice cosa dobbiamo fare. 1 significa "non fare nulla", quindi continuiamo. Alla fine incontriamo il 2 nella cella # −3. Ogni volta che * q2 non è uguale a 1, q2 è sempre uguale a q .

inserisci qui la descrizione dell'immagine

Come ho già affermato, la fase 2 è "determinare la cifra più grande in questo luogo". Quindi impostiamo r su r2 , usiamo un ciclo while per diminuire * p e spostiamo r verso sinistra e riempiamo il nastro con 1s, quindi usiamo un altro ciclo while per spostare r indietro a destra e incrementare nuovamente * p per ripristinare il valore. Ricorda che ogni ciclo while viene eseguito per una iterazione in meno rispetto al valore su cui lo utilizziamo; per questo motivo, il numero di 1 scritti sarà 3 in più (anziché 4 in più) rispetto al valore della cifra e il valore finale memorizzato in * p sarà 2 in più. Pertanto, questo ha effettivamente diminuito * p di 2.

Dopodiché, impostiamo p sul valore di p2 e poi lo facciamo di nuovo. Per la seconda volta, impostare q2 su 0, trovare la fine del numero spostando p verso destra, quindi scorrere le cifre di questo numero diminuendo p e q2 insieme. Ancora una volta incontreremo il 2 nella cella # −3 e scriveremo che molti 1 restano di * r .

Nel caso del terzo numero, finiamo per non fare nulla perché non ha un posto di centinaia (quindi q2 non raggiunge mai q ), ma va bene perché ciò non influisce sul calcolo del valore massimo della cifra.

inserisci qui la descrizione dell'immagine

Abbiamo anche impostato la cella * (r - 4) , che ho contrassegnato con una freccia senza etichetta qui, su 1 (anche se è già su 1). Non ti dirò ancora perché, ma forse hai già indovinato?

Il successivo incremento di * q ci porta alla fase 3, che è "sottrarre la cifra massima da tutte le cifre nella posizione corrente". Come prima, ripristiniamo p su 11 e q2 su 0 e quindi esaminiamo tutti i numeri proprio come abbiamo fatto nella fase precedente; tranne che questa volta, * q = 3 invece di 2. Ogni volta che q2 incontra q e p è in un posto di centinaia, usiamo un ciclo while per diminuire * p tante volte quante sono 1 s nel blocco a sinistra di * r2 (5 nel nostro esempio) usando rcome puntatore in esecuzione. In realtà la diminuiamo ancora una volta, in modo che la cifra più grande finisca a -2, per una ragione che diventerà più chiara in seguito:

inserisci qui la descrizione dell'immagine

Dopo aver elaborato tutti i numeri, siamo ora alla fine della fase 3. Qui eseguiamo due cose singolari.

  • Innanzitutto, sottraggiamo anche la dimensione del blocco r (più 1) da * q , ma usando il puntatore r2 , che lo lascia a sinistra. * q diventa negativo in questo modo. Nel nostro caso, il blocco r ha cinque 1, quindi * q diventa −3.
  • In secondo luogo, impostiamo una variabile su un valore diverso da zero per indicare che stiamo entrando nello stadio di output. (Tecnicamente, il fatto che * q sia negativo indica già lo stadio di uscita, ma questo è troppo difficile da verificare, quindi la variabile extra.)

Ora capisci che continuiamo a scorrere i numeri, a trovare il posto corrente (indicato dal valore non 1 di * q ) all'interno di ciascun numero e fare qualcosa in base al valore di * q . Vediamo che * q viene prima incrementato a 2 (= calcola il valore massimo della cifra), quindi 3 (sottrai il valore massimo della cifra da ogni cifra in questo posto) e quindi sottraggiamo da esso per renderlo negativo. Da lì, continuerà a salire fino a raggiungere 1, ripristinando così il valore che significa "non fare nulla". A quel punto, passiamo al posto successivo.

Ora, quando * q è negativo, stiamo producendo. * q ha esattamente il valore corretto in modo che emettiamo il numero corretto di righe di caratteri prima che raggiunga 1; se la cifra più grande è 2, dobbiamo generare 3 righe. Vediamo cosa succede ad ogni valore di * q :

  • * q = −2:
    • Per il primo numero, * p è −2, che indica che dobbiamo generare un '.'(punto) o un ':'(due punti). Decidiamo quale guardando q : se è −1, siamo nel posto giusto, quindi ':'produciamo a (che calcoliamo come '8'+2), altrimenti a '.'.
    • Per il secondo numero, * p è −3. Tutto ciò che non è −2 significa che viene emesso un '|'(pipe) e quindi incrementato il valore. In questo modo raggiungerà -2 nel posto giusto e quindi emetteremo '.'s / ':'s per il resto di quella cifra.
    • In ogni caso, impostiamo anche una variabile pd su 0 prima di elaborare il numero e impostiamo pd (= "stampato") su un valore diverso da zero per indicare che abbiamo stampato un carattere.
    • Per il terzo numero, non si verifica alcuna elaborazione poiché il terzo numero non ha un posto di centinaia. In questo caso, pd sarà ancora 0 dopo aver elaborato il numero, indicando che dobbiamo ancora produrre a '|'(ma solo se out è diverso da zero, perché altrimenti siamo ancora nella fase 2 o 3).
    • Dopo aver elaborato tutti i numeri, se out è diverso da zero, genera una nuova riga. Si noti che abbiamo bisogno della variabile out in modo da non generare la nuova riga nella fase 2 o 3.
  • * q = −1: uguale a prima, tranne per il fatto che * p è −2 per entrambi i primi due numeri, quindi entrambi producono a'.'(e il terzo a a'|'come prima).
  • * q = 0: quando * q è 0, questo significa "non fare nulla se ci troviamo in quel posto, altrimenti emettere una riga di'|'s indipendentemente da * p ". In questo modo otteniamo il riempimento tra le cifre.

Ora incrementiamo q per passare al posto successivo, il posto delle decine e aumentiamo * q lì. All'inizio della fase 2, il nastro è simile al seguente:

inserisci qui la descrizione dell'immagine

Quindi eseguiamo la fase 2 proprio come prima. Ricorda che questo sottrae effettivamente 2 da ogni cifra in questo posto e lascia anche un numero unario a sinistra di * r2 che indica la cifra massima. Lasciamo solo il precedente numero unario e continuiamo a estendere il nastro a sinistra; costerebbe solo il codice aggiuntivo non necessario per "ripulire". Quando abbiamo finito e incrementiamo * q , all'inizio della Fase 3 il nastro ora è:

inserisci qui la descrizione dell'immagine

In realtà, questa è una bugia. Ricordi in precedenza dove ho detto che abbiamo impostato * (r - 4) su 1 e non ti ho detto perché? Ora ti dirò perché. È per casi come questo, in cui la cifra più grande è in realtà 0, il che significa che tutte le cifre in questo posto sono 0. Impostando * (r - 4) , indicato dalla freccia senza etichetta sopra, a 1 si estende il numero unario di 1, ma solo in questo caso speciale. In questo modo facciamo finta che la cifra più grande fosse 1, il che significa che genereremo una riga aggiuntiva.

Dopo la fase 3 (sottrarre la cifra massima da tutte le cifre nella posizione corrente), incluso il passaggio aggiuntivo che rende negativo * q , il nastro appare così. L'ultima volta la cifra più grande è stata rappresentata da −2 nel blocco * p , ma questa volta sono tutte −3 perché in realtà sono tutte azzerate ma stiamo fingendo che la cifra massima fosse 1.

inserisci qui la descrizione dell'immagine

Ora vediamo cosa succede mentre * q avanza verso 1:

  • Quando * q = −1, i valori * p sono tutti −3, il che significa che emettiamo '|'s e li incrementiamo.
  • Quando * q = 0, produciamo '|'perché è quello che facciamo sempre quando * q = 0, indipendentemente da * p .

Quindi, otteniamo due file di tubi.

Infine, spostiamo * q al posto di uno. Questo diventa interessante perché dobbiamo emettere ':'s se la cifra effettiva è tutt'altro che 1, ma '8'se è 1. Vediamo come procede il programma. Innanzitutto, incrementiamo * q per avviare la fase 2:

inserisci qui la descrizione dell'immagine

Dopo la fase 2 ("calcola il valore massimo della cifra"), ci resta questo:

inserisci qui la descrizione dell'immagine

Dopo la fase 3 ("sottrarre il valore massimo della cifra da tutte le cifre nella posizione corrente") il nastro appare così:

inserisci qui la descrizione dell'immagine

Ora esaminiamo a turno ciascuna iterazione di * q :

  • * q = −2:
    • Primo numero: già a -2, quindi emetti a ':'(anziché a '.'perché q = −1).
    • Secondo numero: a −4, quindi emettere a '|'e incremento.
    • Terzo numero: a -3, quindi output a '|'. Tuttavia, questa volta, anziché incrementare, viene attivato un caso speciale. Solo se stiamo producendo l'ultimo posto ( q = −1), e siamo nella penultima riga per quello ( * q = −2), e la cifra è in realtà un 1 ( * p = −3) , quindi invece di incrementarlo su −2, lo impostiamo su −1. In altre parole, usiamo −1 come valore speciale per indicare che nella prossima iterazione, avremo bisogno di produrre '8'invece di ':'.
  • * q = −1:
    • Primo numero: già a -2, quindi output a ':'.
    • Secondo numero: a -3, quindi output a '|'. La condizione speciale non si attiva perché * q non è più −2. Pertanto, incrementare.
    • Terzo numero: a -1, quindi output '8'.
  • * q = 0: di solito, in questo caso viene visualizzata la riga di riempimento di'|'s, ma nel caso speciale in cui ci troviamo in quel punto ( q = −1), la ignoriamo.

Successivamente, q viene incrementato a 0 e il ciclo while grande termina.

Ora sai come funziona un input come 202,100,1. Tuttavia, c'è un altro caso speciale che non abbiamo ancora trattato. Potresti ricordare che mentre stavamo elaborando l'ultimo posto, quando * p era −3 lo impostiamo su −1 per 1(invece di incrementarlo a −2) in modo che la successiva iterazione produca '8'invece un . Questo funziona solo perché abbiamo un'iterazione in cui * p è −3 e prendiamo una decisione se incrementarlo o impostarlo su −1. Noi non abbiamo tale iterazione se tutte le cifre nel luogo quelli sono 0 o 1. In tal caso tutti i * p valori dei 1s sarebbe iniziare a -2; non vi è alcuna possibilità di decidere di impostarlo su -1piuttosto che incrementarlo da −3 . Per questo motivo, c'è un'altra condizione di involucro speciale all'interno della Fase 3 ("sottrarre la cifra massima da ogni cifra nella posizione corrente"). Ho affermato che dopo aver sottratto il valore massimo della cifra da ogni cifra (a quel punto la cifra massima è −1), la diminuiamo ancora una volta, ma in realtà c'è una condizione su ciò che segue:

Se la cifra che stiamo guardando è uguale alla cifra massima in questo posto ( * p = −1), e questo posto è quello in cui si trova ( q = −1) e la cifra massima è 1 ( * (r + 5) = 0, cioè il blocco unario all'estrema sinistra è lungo solo 5 celle), solo allora lasciamo * p a −1 per indicare che l'unica iterazione dell'uscita deve generare un '8'. In tutti gli altri casi lo diminuiamo ancora una volta.

Fatto. Felice anno nuovo!

  • Modifica 1 (3183 → 3001): un po 'di golf Happy New Year! Sono riuscito a sbarazzarmi del tutto delle variabili p2 e r2 ! p ora corre avanti e indietro per continuare a trovare l'inizio e la fine dei numeri, ma sembra essere più breve nel codice. Ho provato anche a sbarazzarmi di q2 , ma non ho potuto accorciare il codice in quel modo.

    Ho anche trovato alcuni altri posti in cui avrei potuto applicare i tipici trucchi del golf illeggibili come riutilizzare l'ultimo valore di un ciclo while. Per darti un esempio, invece di

    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
    

    Posso salvare il '""""(fai il primo, poi il secondo) e il '"""(costante 1) scrivendolo in un modo che è un po 'come

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

    Ovviamente, questo funziona solo se so che il ciclo while verrà eseguito per almeno un'iterazione, ma se lo fa, il suo valore di ritorno è pd, quindi posso usarlo come condizione per l'if.


"Illeggibile" è sicuramente un nome appropriato ...
Alex A.

9
-1 spiegazione non sufficiente
The Guy with The Hat

7

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

Sono nuovo di PPCG e ho pensato di provarlo pensando che fosse piuttosto semplice. Ragazzo ho sbagliato !! Ci sto lavorando da un po 'e ho molto da giocare a golf ... I
suggerimenti sono incoraggiati! - anche se dare un senso a questo non sarà un compito facile.

Emette le corde quando l'ingresso è un array di numeri (ad es [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)

Spiegazione

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
)

Esempio

Input: Matrice di numeri: [4,8,15,16,23,42]
Output:

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

+1 golf impressionante. Includerai un esempio con input e output?
David C

@DavidC Grazie! E l'esempio è incluso. Chiamalo dalla console e restituisce una stringa. :)
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 byte

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='')

Bene, poiché questa domanda aveva bisogno di una risposta, ne ho fornita una qui, in cui l'input dovrebbe essere una stringa di numeri separata da spazi, come "204 1". Ragazzo, è lungo. Eventuali suggerimenti sul golf (o risposte migliori) sono i benvenuti.

Modifica: byte salvati mescolando schede e spazi.

Modifica: ho salvato molti byte modificando il modo in cui ho ottenuto le cifre di un numero (crea un elenco dalla stringa del numero zero, quindi nel corpo del codice, trasponi per ottenere centinaia di cifre, dieci cifre, ecc. .)

Modifica: E ho salvato un po 'di più incorporando l'ultimo :8loop nel loop quipu principale. Ora, se solo potessi capire perché b=d[j*v+i]==m(d[i::v])non funziona. Capito e la soluzione richiede troppi byte. (Anche il conteggio dei byte è diminuito perché in qualche modo le schede sono tornate in quattro spazi. Probabilmente era la formattazione del blocco di codice su questo sito)

Modifica: ho riorganizzato come ha reso il quipus. Ora crea un filo alla volta, quindi traspone per la stampa.

Modifica: ho trasformato la mia risposta in un programma Python 3 per salvare altri byte.

Modifica: ho trovato un bug nel mio codice che lo ha fatto in modo che non stampasse correttamente gli zeri nel mezzo dei numeri (vedi il caso di prova 204 1sopra). Nel risolvere questo, sono riuscito a golf :)

Modifica: ho modificato la stampa per salvare 10 byte. E ho rimesso indietro tutti i vecchi byte, solo perché.

Modifica: golfato il compito di vutilizzare mapper quattro byte. Ringraziamo CarpetPython , poiché ho avuto l'idea dalla loro risposta qui .

Modifica: ha trasformato la parte centrale "per ciclo all'interno di un ciclo per", in un solo ciclo per sei byte.

Modifica: ora utilizzandoenumerate . Non più in uso l=len(z). Trasformato il ternario if-elsein un elenco ternario. Vedi sotto per i dettagli.

Modificare: Sp3000 ha suggerito una modifica printe una modifica alla condizione ternaria che ha salvato un byte ciascuno.

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

C'è qualcosa di specifico in Python 3 qui? Altrimenti, convertirlo in Python 2 potrebbe salvare parecchi byte
Cyoce,

@Cyoce Niente di troppo specifico per Python 3. Ho appena iniziato in Python 3 perché è la versione che ho. Proverò una versione di Python 2 su ideone o qualcosa del genere.
Sherlock9,

@Maltysen Non funziona con input che iniziano con 0, come 0 12 4.
Sherlock9,

Puoi salvare alcuni byte alternando tabulazioni e spazi per il rientro in Python 2. Credo che 1 carattere di tabulazione == 8 spazi secondo il parser di rientro di Python
Cyoce,

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

4

C, 238 235 byte

Affidarsi pesantemente al preprocessore C per rendere il codice il più breve possibile. Come effetto collaterale, lo rende anche praticamente illeggibile.

#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)}}

Su Ubuntu 14.04, puoi compilare il codice in modo semplice gcc quipu.c(ignora gli avvisi). Un esempio di esecuzione dell'eseguibile:

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

Testato contro tutti i casi di test di OP.

Codice sorgente non salvato:

// 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;
}

Congratulazioni! Come risposta più breve pubblicata entro il periodo di bounty, hai ricevuto la mia generosità di +50 rep. Bella risposta! :)
Alex A.

4

Mathematica 436 453 357 352 347 byte

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)

Quanto sopra

  • Suddivide ciascun numero intero in un elenco di cifre, usando IntegerDigits; sposta ogni numero con zeri a sinistra (per garantire una spaziatura uguale); ogni numero di input, ora scomposto in cifre, corrisponde a una riga di un array; ogni colonna rappresenta un valore di luogo. La matrice viene trasposta.
  • Sostituisce le cifre con un elenco di nodi con imbottitura. Per le unità viene utilizzata una routine di corrispondenza dei motivi leggermente diversa.

Esempio

g[Range[0, 50]]

cinquanta


Transpose@Join? Dovrebbe essere, giusto?
CalcolatriceFeline

Sì. Grazie per averlo colto.
DavidC

Spazio proprio prima di quello.
CalculatorFeline

1

R - 446 444

Vedo che non esiste ancora una soluzione R, quindi eccone una. La funzione accetta un vettore con numeri interi.

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)

Ti serve if(v>0)nella tua if(i<r)clausola? R accetta un intervallo come z+1:zquando v==0? Se così q[z+1:z,j]non fosse influenzato, penso. Inoltre, R ha una elseparola chiave e una sorta di else ifparola chiave? Se è così, saresti in grado di giocare a golf alcuni di questi condizionali.
Sherlock9,

if(v>0)è necessario perché se v=0l'indice sarà fuori dai limiti (ovvero, cerca di ottenere la riga nrow + 1). R ha else, e in realtà ho provato il tuo suggerimento e usato elsedove possibile, ma si è rivelato essere lo stesso numero di byte.
Slow loris,
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.