Leer una pantalla retro

22

Arte robado de ¿ De qué tamaño es el dígito?


Los dígitos de 7 segmentos se pueden representar en ASCII utilizando _|caracteres. Aquí están los dígitos 0-9:

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

Su trabajo es analizar el arte en números normales.

Notas sobre números

  • Cada dígito tiene un ancho diferente.
    • 1 tiene un ancho de 1
    • 3y 7son 2anchas
    • 245689y 0son todos 3anchos

También entre cada dígito hay un char de relleno. Aquí está el conjunto completo de caracteres:

 // <- debería ser un espacio, pero el formato SE lo estropeó
El |
El |
-------------
 _ _ 
 _ |
| _ 
-------------
_ _ 
_ |
_ |
-------------

| _ |
  El |
-------------
 _ _ 
| _ 
 _ |
-------------
 _ _ 
| _ 
| _ |
-------------
_ _ 
 El |
 El |
-------------
 _ _ 
| _ |
| _ |
-------------
 _ _ 
| _ |
 _ |
-------------
 _ _ 
El | El |
| _ |

Entrada

La entrada puede ser desde la consola o como una cadena arg a una función.

Salida

La salida se coloca en la consola o se devuelve desde la función.

Ejemplos:

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

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

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

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

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

Este es el código de golf, ¡así que el conteo de bytes más corto gana!

J Atkin
fuente
Relacionado
J Atkin
Estoy interesado en conocer los mejores algoritmos para resolver este tipo de problema, y ​​tengo dificultades para aprender de las respuestas aquí (son buenas, muy concisas). ¿Hay algún lugar donde me puedan recomendar para ver explicaciones más largas, preferiblemente con fotos?
Bueno, la forma en que funciona el mío es bastante simple. Se transpone la lista y bucles sobre ella. Luego se divide en líneas vacías. Cada número se compara con una tabla de huellas digitales para cada número. Los otros funcionan un poco como el mío, excepto que en lugar de una tabla de huellas digitales, básicamente tienen una tabla hash que usan.
J Atkin
¿Existe un nombre más general para este tipo de problema en informática?
No tengo idea;)
J Atkin

Respuestas:

4

Pyth, 33 30 bytes

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

Aquí está la idea: una vez que transponemos la entrada y la dividimos en dígitos, podemos ordenar las cadenas de dígitos individuales y asignarlas a sus valores.

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.

Pruébalo aquí .

lirtosiast
fuente
Genial, básicamente se parece a mi enfoque, pero mucho más corto.
Lynn
@ Lynn Lo siento por eso; básicamente hay una forma más corta de hacer esto en Pyth.
lirtosiast
4

Rubí, 184 bytes

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

Explicación

  • toma la entrada de stdin
  • convierte las cadenas en secuencias binarias, 1/0 para activar / desactivar el segmento
  • codifica columnas a un número binario de 3 bits
  • codifica secuencias de números de 3 bits a números de 9 bits, use columnas '0' como símbolos de parada
  • use una tabla de búsqueda para convertir los números de 9 bits a dígitos

Este es mi primer código de golf. Gracias por la diversion!

bogl
fuente
2
Bienvenido a PPCG! Muy buen trabajo en tu primer post!
J Atkin
2

Japt, 119 bytes

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 cielos, este es muy largo. No creo que haya terminado de jugar golf.

Explicación

Preparación

Tomamos la entrada y convertimos cualquiera |_a 1. Luego, transponemos, eliminamos los espacios finales y los dividimos a lo largo de líneas nuevas dobles.

Traducción

Hacemos un mapa sobre la matriz resultante y encontramos el índice donde aparece el formulario en una matriz de referencia. Aquí hay un diagrama para ayudar:

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

Después de eso, ¡nos unimos al conjunto de números y resultados!

NOTA : Quizás se pregunte por qué tenemos que cambiar cada personaje de arte a una serie de 1. Esto se debe a que parece haber un error (o algo así) que no me permite almacenar los personajes tal como están |_.

Mama Fun Roll
fuente
Noté el _error, pero no sé qué lo causó.
ETHproductions
OK, "\n\n"se puede reemplazar con y "\\||_"con "%||_". Creo que se podría también ahorrar algo de bytes por codificar la cadena larga en la base 4 (cambio de cada uno de los 4 caracteres disinctive a 0, 1, 2, o 3, relleno de una longitud de un múltiplo de 4, a continuación, ejecutar r"...."_n4 d}sobre él), pero por alguna razón Aún no he conseguido que esto funcione.
ETHproductions
2

Python2, 299 261 244 bytes

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

Realmente me gustó este desafío, ¡buen trabajo!

Explicación

La función stoma las tres líneas como entrada, trata de encontrar una separación de dígitos (todos los caracteres son espacios). Cuando se encuentra tal separación, llama scon el resto de las tres líneas y agrega el valor devuelto por la llamada a las tres líneas que componen el dígito. Si no hay separación, significa que solo hay un dígito.

La función pes el punto de entrada, por lo que toma una cadena que representa los dígitos. Los dígitos se almacenan como un "hash" calculado sum(ord(c)**i for i,c in enumerate("".join(n)))%108para ahorrar espacio (¡gracias a otras respuestas!).

Ejemplo

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

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

Otras versiones

261 bytes (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 bytes, este transpone las líneas (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')))]
Dica
fuente
2

JavaScript (ES6), 169 bytes

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``

Comienza dividiendo en tres líneas, reasignando cada columna en un valor y luego construyendo una identidad única para cada columna a partir de esos valores. Luego se divide por 0(la identidad para el espacio entre columnas), y finalmente asigna cada identidad a sus valores numéricos, que concatena y genera.

Mwr247
fuente
¡Muy agradable! Desearía que Python tuviera una función de división de lista ...
J Atkin
@JAtkin Edité joinen una cadena para poder dividirla. ¿Creo que podrías hacer eso también en Python?
Mwr247
0

Python 3, 281 254 bytes

Editar

Acabo de mirar el código para la otra respuesta de Python y noté que gran parte del código es similar. A esto se llegó independientemente.

(nuevas líneas agregadas para "legibilidad")

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

Sin golf:

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

Pruebas:

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

Cómo funciona

(Nota: estoy explicando el programa no protegido aquí ya que es más legible y tiene exactamente el mismo código, con la excepción de que la digitfunción está integrada en una lambda)

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

La función principal es parse. Primero divide la entrada en líneas y crea la numbersmatriz.

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

Esta es mi parte favorita (ya que tardó mucho en darse cuenta). Aquí tenemos ziplas líneas para que básicamente podamos atravesar verticalmente la entrada. Cuando la línea tiene caracteres, la agregamos al último número de la numbersmatriz. Si no tiene caracteres, agregamos un nuevo número a la matriz.

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

Realmente simple, numbersse asigna con la digitfunción y se convierte en una cadena.

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

Esto es (bastante) simple. fingerprintes la representación de cadena de los dígitos creados anteriormente menos los primeros 2 caracteres (esta fue la huella digital más pequeña que pude encontrar). Devolvemos el índice del primer partido.

J Atkin
fuente
0

Haskell, 270 207 bytes

No seas demasiado duro, este es mi primer programa de haskell;) Estoy casi seguro de que esto se puede jugar más, pero no sé cómo dado mi limitado conocimiento del idioma.

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

Sin golf:

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

¡Muchas gracias a @nimi por los consejos!

J Atkin
fuente
malas noticias primero: me temo que tiene que incluir el import Data.Listen su conteo de bytes. Buenas noticias: a) si lo ha Data.Listsinstalado, puede importarlo y reemplazarlo acon splitOn: ...map c$splitOn[" "]$transpose...y ...f<-splitOn",""|_.... b) intercalate "" nes concat no id=<<n. c) reemplazar rescon un solo nombre de letra. d) patrón de uso en lugar de guarda let ... in: c n|e<-drop 2$id=<<n,Just r<-elemIndex ... ]=(show r)!!0.
nimi
Jejeje, ¡Vaya! La importación se perdió en copiar / pegar;) ¡Gracias por todos los consejos!
J Atkin
@nimi Perdón por molestarte, pero ¿te importaría explicar qué =<<hace? Ni los documentos de hoogle ni la firma de tipo son muy útiles para mí.
J Atkin
=<<en el contexto de la lista es concatMap, es decir, asigna la función dada sobre la lista y combina los resultados en una sola lista. >>=hace lo mismo pero con los argumentos invertidos. id =<< n(o n >>= id) asigna la función de identidad sobre la lista (de listas), es decir, no hace nada con las sublistas y las concatena. Entonces es lo mismo que concat.
nimi