Leggi un display retrò


22

Arte rubata da Che dimensione è la cifra?


Le cifre a 7 segmenti possono essere rappresentate in ASCII usando _|caratteri. Ecco le cifre 0-9:

 _     _  _       _   _  _   _   _ 
| | |  _| _| |_| |_  |_   | |_| |_|
|_| | |_  _|   |  _| |_|  | |_|  _|

Il tuo compito è di analizzare l'arte in numeri normali.

Note sui numeri

  • Ogni cifra ha una larghezza diversa.
    • 1 ha una larghezza di 1
    • 3e 7sono 2larghi
    • 245689e 0sono tutti 3ampi

Inoltre tra ogni cifra c'è un carattere di riempimento. Ecco il set completo di caratteri:

 // <- dovrebbe essere uno spazio, ma la formattazione SE l'ha incasinato
|
|
-------------
 _ 
 _ |
| _ 
-------------
_ 
_ |
_ |
-------------

| _ |
  |
-------------
 _ 
| _ 
 _ |
-------------
 _ 
| _ 
| _ |
-------------
_ 
 |
 |
-------------
 _ 
| _ |
| _ |
-------------
 _ 
| _ |
 _ |
-------------
 _ 
| |
| _ |

Ingresso

L'input può essere dalla console o come stringa arg per una funzione.

Produzione

L'output viene inserito nella console o restituito dalla funzione.

Esempi:

  _  _   _ 
|  |  | |_ 
|  |  | |_|
1776

 _   _     _ 
 _| | | | |_ 
|_  |_| | |_|
2016

   _       _ 
| |_| |_| |_ 
|  _|   |  _|
1945

   _   _   _   _   _   _ 
| | | | | | | | | | | | |
| |_| |_| |_| |_| |_| |_|
1000000

 _     _  _       _   _  _   _   _ 
| | |  _| _| |_| |_  |_   | |_| |_|
|_| | |_  _|   |  _| |_|  | |_|  _|
0123456789

Questo è il golf del codice, quindi vince il conteggio dei byte più breve!



Sono interessato a conoscere i migliori algoritmi per risolvere questo tipo di problema e ho difficoltà a imparare dalle risposte qui (sono buone, solo molto concise). C'è un posto in cui mi puoi riferire per vedere spiegazioni più lunghe, preferibilmente con le immagini?

Bene, il modo in cui funziona il mio è abbastanza semplice. Esso recepisce la lista e loop su di esso. Si divide quindi su linee vuote. Ogni numero viene verificato rispetto a una tabella delle impronte digitali per ciascun numero. Gli altri funzionano un po 'come il mio, tranne per il fatto che al posto di una tabella delle impronte digitali hanno sostanzialmente una tabella hash che usano.
J Atkin,

Esiste un nome più generale per questo tipo di problema nell'informatica?

Non ne ho idea;)
J Atkin,

Risposte:


4

Pyth, 33 30 byte

sm@."/9Àøw"%%Csd409hTcC.z*3d

Ecco l'idea: una volta trasposto l'input e diviso in cifre, possiamo ordinare l'hash delle singole stringhe di cifre e assegnarle ai loro valori.

sm@."/9Àøw"%%Csd409hTcC.z*3d     Implicit: z=input
                      C.z        Transpose input.
                     c   *3d     Split that on "   ", a space between digits.
 m@."/9Àøw"%%Csd409hT            Map the following lambda d over that. d is a digit string.
             Csd                   Flatten the digit string, and convert from base 256.
            %   409                Modulo that by 409
           %       hT              and then by 11. All digits go to a distinct num mod 11.
   ."/9Àøw"                        The compressed string "03924785/61".
  @                                Index into that string.
s                                Flatten and implicitly output.

Provalo qui .


Bene, in pratica sembra il mio approccio ma molto più breve!
Lynn,

@Lynn Mi dispiace per quello; c'è sostanzialmente un modo più breve per farlo in Pyth.
lirtosiast,

4

Rubino, 184 byte

a=0
l=$<.map{|x|x.bytes.map{|y|y==32?0:1}+[0]*2}
(0..l[0].count-1).map{|i|l[0][i]+2*l[1][i]+4*l[2][i]}.each{|x|
x>0?(a=x+2*a):(p Hash[[40,6,32,20,18,26,42,8,44,64].zip(0..9)][a];a=0)}

Spiegazione

  • accetta l'input da stdin
  • converte le stringhe in sequenze binarie, 1/0 per il segmento on / off
  • codifica le colonne in un numero binario a 3 bit
  • codifica sequenze di numeri da 3 bit a numeri a 9 bit, utilizzare le colonne "0" come simboli di arresto
  • utilizzare una tabella di ricerca per convertire i numeri a 9 bit in cifre

Questo è il mio primo codice-golf. Grazie per il divertimento!


2
Benvenuti in PPCG! Ottimo lavoro per il tuo primo post!
J Atkin,


2

Japt, 119 byte

Ur"[|_]"1 z r" +
"R x1 qR² £"11
1 1
1151151
111
 15111
115 1
 1
115 1
111
1511
111
15  1
11511
111
115 1
111
11"q5 bXÃq

Try it here!

Oh cavolo, questa è davvero lunga. Non penso di aver finito di giocare a golf.

Spiegazione

Preparazione

Prendiamo l'input e convertiamo qualsiasi |_in 1. Quindi trasponiamo, eliminiamo gli spazi finali e li dividiamo lungo le doppie linee.

Traduzione

Mappiamo sull'array risultante e troviamo l'indice in cui il modulo appare in un array di riferimento. Ecco un diagramma per aiutare:

MAPITEM
  11
  1 1 --> This same form appears at index 0 in the reference array
  11                            |
                                |
                                V
                        change the mapitem to 0!

Successivamente, ci uniamo alla matrice di numeri e output!

NOTA : ti starai chiedendo perché dobbiamo cambiare ogni personaggio artistico in una serie di 1. Questo perché sembra che ci sia un bug (o qualcosa del genere) che non mi consente di memorizzare i personaggi così com'è |_.


Ho notato il _bug, ma non so cosa l'abbia causato.
ETHproductions

OK, "\n\n"può essere sostituito con e "\\||_"con "%||_". Penso che si potrebbe anche risparmiare un po 'di byte di codifica per la lunga serie in base 4 (cambiando ciascuno dei 4 caratteri disinctive a 0, 1, 2, o 3, imbottitura per una lunghezza di un multiplo di 4, poi eseguire r"...."_n4 d}su di esso), ma per qualche motivo , Non l'ho ancora fatto funzionare.
ETHproductions

2

Python2, 299 261 244 byte

s=lambda a,i=0:[a]if i==len(a[0])else[[j[:i]for j in a]]+s([j[i+1:]for j in a])if all(j[i]==' 'for j in a)else s(a,i=i+1)
p=lambda l:['95572431508448853268'.find(`sum(ord(c)**i for i,c in enumerate("".join(n)))%108`)/2for n in s(l.split('\n'))]

Mi è davvero piaciuta questa sfida, bel lavoro!

Spiegazione

La funzione sprende le tre linee come input, cerca di trovare una separazione delle cifre (tutti i caratteri sono spazi). Quando viene trovata una tale separazione, chiama scon il resto delle tre linee e aggiunge il valore restituito dalla chiamata alle tre linee che compongono la cifra. Se non c'è separazione significa che c'è solo una cifra.

La funzione pè il punto di ingresso, quindi prende una stringa che rappresenta le cifre. Le cifre sono memorizzate come un "hash" calcolato sum(ord(c)**i for i,c in enumerate("".join(n)))%108per risparmiare spazio (grazie ad altre risposte!).

Esempio

digits="""
 _     _ 
| | |  _|
|_| | |_ """[1:]  # remove the '\n' at the beginning

p(digits)  # [0, 1, 2]

Altre versioni

261 byte (py3):

s=lambda a,i=0:[a]if i==len(a[0])else[[j[:i]for j in a]]+s([j[i+1:]for j in a])if all(j[i]==' 'for j in a)else s(a,i=i+1)
def p(l):[print([91,21,84,31,58,76,88,41,80,68].index(sum(ord(c)**i%20 for i,c in enumerate("".join(n)))),end="")for n in s(l.split('\n'))]

249 byte, questo traspone le linee (py2):

f="".join
s=lambda a,i=0:[a]if i==len(a)else[a[:i]]+s(a[i+1:])if all(c==' 'for c in a[i])else s(a,i=i+1)
h=lambda s:ord(s[0])**len(s)+h(s[1:])if s else 0
p=lambda l:["10220907112527153129".index(`h(f(map(f,n)))%34`)/2for n in s(zip(*l.split('\n')))]

2

JavaScript (ES6), 169 byte

a=>[...(a=a.split`
`)[0]].map((b,c)=>(d={' ':0,'|':1,'_':2})[b]+d[a[1][c]]*2+d[a[2][c]]).join``.split(0).map(b=>[343,3,182,83,243,281,381,23,383,283].indexOf(+b)).join``

Inizia dividendo in tre righe, rimappando ciascuna colonna in un valore e quindi costruendo un'identità univoca per ogni colonna da quei valori. Quindi si divide per 0(l'identità per lo spazio tra le colonne) e infine associa ciascuna identità ai suoi valori numerici, che concatena e genera.


Molto bella! Vorrei che Python avesse una funzione di suddivisione in liste ...
J Atkin,

@JAtkin Ho joininserito una stringa in modo da poterla dividere. Credo che potresti farlo anche in Python?
Mwr247,

0

Python 3, 281 254 byte

modificare

Ho appena guardato il codice per l'altra risposta di Python e ho notato che gran parte del codice è simile. Questo è arrivato in modo indipendente.

(nuove righe aggiunte per "leggibilità")

def p(i):
 n=[[]]
 for l in zip(*i.split('\n')):
  if all(i==" "for i in l):n+=[[]]
  else:n[-1]+=l
 return''.join(map(lambda l:str([''.join(l[2:])==x for x in
             "|_ _ ||,|,|___ | ,_ ||,  _  ||, ___  |,|___  |,  ||,|___ ||, ___ ||"
                     .split(',')].index(1)),n))

Ungolfed:

def parse(input):
    lines = list(input.split('\n'))
    numbers = [[]]
    for lst in zip(*lines):
        if all(i==" " for i in lst):
            numbers += [[]]
        else:
            numbers[-1] += lst
    return ''.join(map(digit, numbers))

def digit(num):
    fingerprint = 
        "|_ _ ||,|,|___ | ,_ ||,  _  ||, ___  |,|___  |,  ||,|___ ||, ___ ||".split(',')
    return str([''.join(num[2:]) == y for y in fingerprint].index(True))

test:

assert (parse("   _   _   _   _   _   _ \n| | | | | | | | | | | | |\n| |_| |_| |_| |_| |_| |_|") == '1000000')
assert (parse("   _       _ \n| |_| |_| |_ \n|  _|   |  _|") == '1945')
assert (parse(" _   _     _ \n _| | | | |_ \n|_  |_| | |_|") == '2016')
assert (parse(" _     _  _       _   _  _   _   _ \n| | |  _| _| |_| |_  |_   | |_| |_|\n|_| | |_  _|   |  _| |_|  | |_|  _|") == '0123456789')
assert (parse("  _  _   _ \n|  |  | |_ \n|  |  | |_|") == '1776')

Come funziona

(Nota: sto spiegando qui il programma non golfato poiché è più leggibile e ha lo stesso codice esatto, con l'eccezione che la digitfunzione è incorporata in un lambda)

def parse(input):
    lines = list(input.split('\n'))
    numbers = [[]]

La funzione principale è parse. Per prima cosa divide l'input in righe e crea l' numbersarray.

    for lst in zip(*lines):
        if all(i==" " for i in lst):
            numbers += [[]]
        else:
            numbers[-1] += lst

Questa è la mia parte preferita (dal momento che ci è voluto tanto tempo per capire). Qui abbiamo ziple linee in modo da poter sostanzialmente attraversare verticalmente l'input. Quando sulla riga sono presenti caratteri, lo aggiungiamo all'ultimo numero numbersdell'array. Se non contiene alcun carattere, aggiungiamo un nuovo numero all'array.

    return ''.join(map(digit, numbers))

Davvero semplice, numbersè mappato con la digitfunzione e viene convertito in una stringa.

def digit(num):
    fingerprint = 
        "|_ _ ||,|,|___ | ,_ ||,  _  ||, ___  |,|___  |,  ||,|___ ||, ___ ||".split(',')
    return str([''.join(x[2:]) == y for x, y in zip([num]*10, fingerprint)].index(True))

Questo è (abbastanza) semplice. fingerprintè la rappresentazione in forma di stringa delle cifre create sopra meno i primi 2 caratteri (questa era l'impronta digitale più piccola che ho trovato). Restituiamo l'indice della prima partita.


0

Haskell, 270 207 byte

Non essere troppo duro, questo è il mio primo programma haskell in assoluto;) Sono quasi certo che questo possa essere ulteriormente approfondito, ma non so come vista la mia limitata conoscenza della lingua.

import Data.Lists
b n=map c$splitOn["   "]$transpose$lines n
c n|e<-drop 2$concat n,Just r<-elemIndex True[e==f|f<-splitOn",""|_ _ ||,|,|___ | ,_ ||,  _  ||, ___  |,|___  |,  ||,|___ ||, ___ ||"]=(show r)!!0

Ungolfed:

module Main where
import Data.Lists

main :: IO ()
main = print $ parse " _     _  _       _   _  _   _   _ \n| | |  _| _| |_| |_  |_   | |_| |_|\n|_| | |_  _|   |  _| |_|  | |_|  _|"

parse :: String -> String
parse n = let lst = transpose $ lines n
              numbers = splitOn ["   "] lst --"   " lst
              number = map digit numbers
          in number

digit :: [String] -> Char
digit n | e <- drop 2 $ intercalate "" n
        , fingerprint <- ["|_ _ ||","|","|___ | ","_ ||","  _  ||"," ___  |","|___  |","  ||","|___ ||"," ___ ||"]
        , Just res <- elemIndex True [e == finger | finger <- fingerprint]
        = head $ show res

Grazie mille a @nimi per i suggerimenti!


prima una brutta notizia: temo che tu debba includere il import Data.Listnel conteggio dei byte. Buone notizie: a) se è stato Data.Listsinstallato, è possibile importarlo e sostituirlo acon splitOn: ...map c$splitOn[" "]$transpose...e ...f<-splitOn",""|_.... b) intercalate "" nè concat no id=<<n. c) sostituire rescon un nome di una sola lettera. d) uso modello custodisce invece di let ... in: c n|e<-drop 2$id=<<n,Just r<-elemIndex ... ]=(show r)!!0.
nimi,

Hehehe, Whoops! L'importazione è stata persa nella copia / incolla;) Grazie per tutti i suggerimenti!
J Atkin,

@nimi Mi dispiace disturbarti, ma ti dispiace spiegare cosa =<<fa? Né i documenti hoogle né la firma del tipo sono molto utili per me.
J Atkin,

=<<nel contesto dell'elenco è concatMap, ovvero mappa la funzione data sull'elenco e combina i risultati in un unico elenco. >>=fa lo stesso ma con gli argomenti capovolti. id =<< n(o n >>= id) mappa la funzione identità sulla lista (di liste), cioè non fa nulla con le liste secondarie e le concatena. Quindi è lo stesso di concat.
nimi,
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.