Читать ретро дисплей


22

Искусство украдено у какого размера цифра?


7-сегментные цифры могут быть представлены в ASCII с использованием _|символов. Вот цифры 0-9:

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

Ваша работа состоит в том, чтобы разобрать искусство в нормальные числа.

Примечания по номерам

  • Каждая цифра имеет разную ширину.
    • 1 имеет ширину 1
    • 3и 7в 2ширину
    • 245689и 0все 3широко

Также между каждой цифрой есть один символ заполнения. Вот полный набор символов:

 // <- должен быть один пробел, но SE форматирование испортило
|
|
-------------
 _ 
 _ |
| _ 
-------------
_ 
_ |
_ |
-------------

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

вход

Ввод может быть либо из консоли, либо в виде строкового аргумента функции.

Выход

Вывод либо выводится на консоль, либо возвращается из функции.

Примеры:

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

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

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

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

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

Это код-гольф, поэтому выигрывает самое короткое число байтов!



Я заинтересован в том, чтобы узнать о лучших алгоритмах для решения этой проблемы, и у меня возникают трудности с изучением ответов здесь (они хороши, просто очень кратки). Есть ли место, куда вы можете направить меня, чтобы увидеть более подробные объяснения, желательно с фотографиями?

Ну, мой способ работы довольно прост. Он переносит список и перебирает его. Затем он разбивается на пустые строки. Каждый номер сверяется с таблицей отпечатков пальцев для каждого номера. Другие работают немного похоже на мою, за исключением того, что вместо таблицы отпечатков пальцев у них в основном есть хеш-таблица, которую они используют.
Дж Аткин

Есть ли более общее название для этого типа проблемы в информатике?

Понятия не имею;)
J Аткин

Ответы:


4

Pyth, 33 30 байт

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

Вот идея: как только мы транспонируем ввод и разбиваем на цифры, мы можем сортировать строки отдельных цифр и назначать их значениям.

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.

Попробуй это здесь .


Круто, в основном похоже на мой подход, но гораздо короче!
Линн

@ Линн Извините за это; в основном есть один самый короткий способ сделать это в Pyth.
lirtosiast

4

Рубин, 184 байта

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

объяснение

  • принимает вход от стандартного ввода
  • преобразует строки в двоичные последовательности, 1/0 для включения / выключения сегмента
  • кодирует столбцы в 3-битное двоичное число
  • кодирует последовательности из 3-битных чисел в 9-битные, в качестве символов остановки используются столбцы '0'
  • используйте таблицу поиска для преобразования 9-битных чисел в цифры

Это мой первый код-гольф. Спасибо за веселье!


2
Добро пожаловать в PPCG! Очень хорошая работа в вашем первом посте!
Дж. Аткин


2

Japt, 119 байт

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!

О боже, этот действительно длинный. Я не думаю, что я закончил играть в гольф.

объяснение

подготовка

Мы берем входные данные и конвертируем любые |_в 1. Затем мы транспонируем, удаляем конечные пробелы и разбиваем вдоль двойных строк.

Перевод

Мы отображаем полученный массив и находим индекс, где форма появляется в ссылочном массиве. Вот диаграмма, чтобы помочь:

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

После этого мы объединяем массив чисел и выводим!

ПРИМЕЧАНИЕ . Возможно, вам интересно, почему мы должны поменять каждого художественного персонажа на серию из 1. Это потому, что, кажется, есть ошибка (или что-то в этом роде), которая не позволяет мне хранить символы как есть |_.


Я заметил _ошибку, но я не знаю, что ее вызвало.
ETHproductions

ОК, "\n\n"можно заменить на и "\\||_"с "%||_". Я думаю , вы можете также сохранить некоторые байты , кодирующие длинную строку в базе 4 (изменение каждого из 4 disinctive символов на 0, 1, 2, или 3, набивка на длину кратную 4, то работает r"...."_n4 d}над этим), но по какой - то причине Я не получил это работать еще.
ETHproductions

2

Python2, 299 261 244 байта

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

Мне очень понравился этот вызов, хорошая работа!

объяснение

Функция sпринимает три строки в качестве входных данных, она пытается найти разделение цифр (все символы - пробелы). Когда такое разделение обнаружено, оно вызывает sостальные три строки и добавляет значение, возвращаемое вызовом, к трем строкам, которые составляют цифру. Если нет разделения, это означает, что есть только одна цифра.

Функция pявляется точкой входа, поэтому она принимает строку, представляющую цифры. Цифры хранятся в виде «хеша», вычисляемого sum(ord(c)**i for i,c in enumerate("".join(n)))%108для экономии места (благодаря другим ответам!).

Exemple

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

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

Другие версии

261 байт (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 байт, этот транспонирует строки (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 байт

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

Начнем с того, что разделим на три строки, переназначим каждый столбец в значение, а затем создадим уникальный идентификатор для каждого столбца из этих значений. Затем он разделяется на 0(идентификатор пространства между столбцами) и, наконец, сопоставляет каждую идентичность с ее числовыми значениями, которые он объединяет и выводит.


Очень хорошо! Я бы хотел, чтобы у python была функция разделения списка ...
J Atkin

@JAtkin Я врезался joinв строку, чтобы разделить ее. Я полагаю, вы могли бы сделать это и на Python?
Mwr247

0

Python 3, 281 254 байта

редактировать

Я просто посмотрел код для другого ответа Python и заметил, что большая часть кода похожа. Это было достигнуто независимо.

(новые строки добавлены для «читабельности»)

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

тесты:

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

Как это устроено

(Примечание: здесь я объясняю некоголфированную программу, поскольку она более читабельна и имеет точно такой же код, за исключением того, что digitфункция встроена в лямбду)

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

Основная функция есть parse. Сначала он разбивает входные данные на строки и создает numbersмассив.

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

Это моя любимая часть (так как это заняло так много времени). Здесь мы zipлинии, так что мы можем в основном вертикально пройти ввод. Когда в строке есть символы, мы добавляем ее к последнему числу в numbersмассиве. Если на нем нет символов, мы добавляем новый номер в массив.

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

Действительно простой, numbersотображается с помощью digitфункции и преобразуется в строку.

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

Это (довольно) просто. fingerprintявляется строковым представлением цифр, созданных выше, минус первые 2 символа (это был самый маленький отпечаток, который я мог найти). Мы возвращаем индекс первого матча.


0

Haskell, 270 207 байт

Не будь слишком жестким, это моя первая в истории программа на Haskell;) Я почти уверен, что это может быть продолжено, но я не знаю, как, учитывая мои ограниченные знания языка.

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

Большое спасибо @nimi за советы!


Сначала плохие новости: боюсь, вы должны включить import Data.Listв свой счетчик байтов. Хорошие новости: а) если вы Data.Listsустановили, вы можете импортировать его и заменить aна splitOn: ...map c$splitOn[" "]$transpose...и ...f<-splitOn",""|_.... б) intercalate "" nесть concat nили id=<<n. в) заменить resодним именем буквы. г) использование модели охранники вместо того , чтобы let ... in: c n|e<-drop 2$id=<<n,Just r<-elemIndex ... ]=(show r)!!0.
Ними

Хехехе, упс! Импорт был потерян в копировании / вставке;) Спасибо за все советы!
Дж Аткин

@nimi Извините, что беспокою вас об этом, но вы не могли бы объяснить, что =<<делает? Ни документы Google, ни тип подписи не очень полезны для меня.
Дж Аткин

=<<в контексте списка есть concatMap, то есть он отображает данную функцию над списком и объединяет результаты в один список. >>=делает то же самое, но с переброшенными аргументами. id =<< n(или n >>= id) отображает функцию идентичности над списком (списков), то есть ничего не делает с подсписками и объединяет их. Так что это так же, как concat.
Ними
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.