Leia um display retrô

22

Arte roubada De que tamanho é o dígito?


Os dígitos de 7 segmentos podem ser representados em ASCII usando _|caracteres. Aqui estão os dígitos 0-9:

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

Seu trabalho é analisar a arte em números normais.

Notas sobre números

  • Cada dígito tem uma largura diferente.
    • 1 tem uma largura de 1
    • 3e 7são 2amplos
    • 245689e 0são todos 3largos

Também entre cada dígito há um caractere de preenchimento. Aqui está o conjunto completo de caracteres:

 // <- deve ser um espaço, mas a formatação SE estragou tudo
|
|
-------------
 _ 
 _
| _ 
-------------
_ 
_
_
-------------

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

Entrada

A entrada pode ser do console ou como uma string arg para uma função.

Saída

A saída é colocada no console ou é retornada da função.

Exemplos:

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

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

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

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

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

Isso é código-golfe, e a menor contagem de bytes ganha!

J Atkin
fonte
Relacionado
J Atkin
Estou interessado em aprender sobre os melhores algoritmos para resolver esse tipo de problema e estou tendo dificuldades em aprender com as respostas aqui (elas são boas, apenas muito concisas). Existe um lugar que você pode me indicar para ver explicações mais longas, de preferência com fotos?
Bem, o modo como o meu funciona é bastante simples. Ele transpõe a lista e loops sobre ele. Em seguida, ele se divide em linhas vazias. Cada número é verificado em uma tabela de impressões digitais para cada número. Os outros funcionam um pouco como o meu, exceto que, em vez de uma tabela de impressões digitais, eles basicamente têm uma tabela de hash que usam.
J Atkins
Existe um nome mais geral para esse tipo de problema na ciência da computação?
Eu não tenho idéia;)
J Atkin

Respostas:

4

Pitão, 33 30 bytes

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

Aqui está a idéia: Depois de transpormos a entrada e dividirmos em dígitos, podemos classificar as seqüências de dígitos individuais e atribuí-las aos seus 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.

Experimente aqui .

lirtosiast
fonte
Legal, basicamente se parece com a minha abordagem, mas muito mais curta!
Lynn
@ Lynn Desculpe por isso; existe basicamente uma maneira mais curta de fazer isso em Pyth.
lirtosiast
4

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

Explicação

  • pega a entrada de stdin
  • converte as seqüências de caracteres em seqüências binárias, 1/0 para o segmento on / off
  • codifica colunas para um número binário de 3 bits
  • codifica seqüências de números de 3 a 9 bits, use colunas '0' como símbolos de parada
  • use uma tabela de pesquisa para converter os números de 9 bits em dígitos

Este é o meu primeiro código de golfe. Obrigado pela diversão!

bogl
fonte
2
Bem-vindo ao PPCG! Trabalho muito bom em seu primeiro post!
precisa
2

Pitão, 39 bytes

sm@"413-928-506--7"%%Crd6C\524cjbC.z*3d

Isso parece funcionar? Experimente online .

Lynn
fonte
2

Japonês, 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 nossa, esse é realmente longo. Acho que não terminei o golfe.

Explicação

Preparação

Pegamos a entrada e convertemos qualquer |_para 1. Em seguida, transpomos, eliminamos espaços finais e dividimos ao longo de novas linhas duplas.

Tradução

Mapeamos a matriz resultante e encontramos o índice em que o formulário aparece em uma matriz de referência. Aqui está um diagrama para ajudar:

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

Depois disso, juntamos a matriz de números e a saída!

NOTA : Você pode estar se perguntando por que precisamos alterar cada caractere de arte para uma série de 1s. Isso ocorre porque parece haver um bug (ou algo parecido) que não me permite armazenar os personagens como estão |_.

Mama Fun Roll
fonte
Percebi o _bug, mas não sei o que o causou.
ETHproductions
OK, "\n\n"pode ser substituído por e "\\||_"com "%||_". Eu acho que você também poderia salvar alguns bytes por que codifica a longa seqüência na base 4 (mudando cada um dos 4 caracteres disinctive para 0, 1, 2ou 3, padding para um comprimento de um múltiplo de 4, em seguida, executando r"...."_n4 d}sobre ele), mas por alguma razão , Ainda não consegui fazer isso funcionar.
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'))]

Gostei muito desse desafio, bom trabalho!

Explicação

A função srecebe as três linhas como entrada, tenta encontrar uma separação de dígitos (todos os caracteres são espaços). Quando essa separação é encontrada, ela chamas com o restante das três linhas e adiciona o valor retornado pela chamada às três linhas que compõem o dígito. Se não houver separação, significa que há apenas um dígito.

A função pé o ponto de entrada, portanto, é necessária uma string que representa os dígitos. Os dígitos são armazenados como um "hash" calculado sum(ord(c)**i for i,c in enumerate("".join(n)))%108para economizar espaço (graças a outras respostas!).

Exemplo

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

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

Outras versões

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 transpõe as linhas (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
fonte
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``

Começa dividindo em três linhas, remapeando cada coluna em um valor e construindo uma identidade exclusiva para cada coluna a partir desses valores. Em seguida, ele divide 0(a identidade do espaço entre as colunas) e, por fim, mapeia cada identidade para seus valores numéricos, que concatena e gera.

Mwr247
fonte
Muito agradável! Eu desejo python teve uma função lista de divisão ...
J Atkin
@JAtkin Editei joinuma string para poder dividi-la. Eu acredito que você poderia fazer isso em Python também?
Mwr247
0

Python 3, 281 254 bytes

Editar

Eu apenas olhei o código para a outra resposta python e notei que grande parte do código é semelhante. Isto foi alcançado independentemente.

(novas linhas adicionadas para "legibilidade")

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

Testes:

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

Como funciona

(Observação: estou explicando o programa não-golfado aqui, pois é mais legível e tem exatamente o mesmo código, com a exceção de que a digitfunção está alinhada em um lambda)

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

A função principal é parse. Primeiro, divide a entrada em linhas e cria a numbersmatriz.

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

Esta é a minha parte favorita (uma vez que demorou tanto tempo para descobrir). Aqui nós zipas linhas para que possamos basicamente atravessar verticalmente a entrada. Quando a linha possui caracteres, nós a adicionamos ao último número da numbersmatriz. Se ele não possui caracteres, adicionamos um novo número ao array.

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

Realmente simples, numbersé mapeado com a digitfunção e é convertido em uma string.

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

Isto é (razoavelmente) simples. fingerprinté a representação de string dos dígitos criados acima, menos os 2 primeiros caracteres (essa foi a menor impressão digital que pude encontrar). Retornamos o índice da primeira partida.

J Atkin
fonte
0

Haskell, 270 207 bytes

Não seja muito difícil, este é o meu primeiro programa de haskell;) Estou quase certo de que isso pode ser ainda mais aprimorado, mas não sei como, devido ao meu conhecimento limitado do 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

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

Muito obrigado a @nimi pelas dicas!

J Atkin
fonte
más notícias primeiro: receio que você precise incluir a import Data.Listcontagem de bytes. Boas notícias: a) se você tiver Data.Listsinstalado, pode importá-lo e substituí-lo apor splitOn: ...map c$splitOn[" "]$transpose...e ...f<-splitOn",""|_.... b) intercalate "" né concat nou id=<<n. c) substitua respor um único nome de letra. d) o uso padrão de guarda em vez de let ... in: c n|e<-drop 2$id=<<n,Just r<-elemIndex ... ]=(show r)!!0.
nimi 16/02
Hehehe, Opa! A importação foi perdida na copiar / colar;) Obrigado por todas as dicas!
111316 J J Atkin
@nimi Desculpe incomodá-lo, mas você se importa em explicar o que =<<faz? Nem os documentos do hoogle nem a assinatura de tipo são muito úteis para mim.
precisa
=<<no contexto da lista concatMap, isto é , ele mapeia a função fornecida sobre a lista e combina os resultados em uma única lista. >>=faz o mesmo, mas com os argumentos invertidos. id =<< n(ou n >>= id) mapeia a função de identidade sobre a lista (de listas), ou seja, não faz nada com as sublistas e as concatena. Então é o mesmo que concat.
nimi 17/02