Отображать слова с помощью 7-сегментного дисплея


13

Моим первым в мире программированием головоломок и Code Golf является дисплей с семью слэшами . Вот мой первый вызов, также основанный на 7-сегментном дисплее.

Помимо цифр, я часто думаю о том, какие буквы я могу отображать, используя простой 7-сегментный дисплей. Оказывается, много букв могут быть отображены. Фактически, все буквы, кроме букв K, M, V, W, X, могут отображаться с использованием одного 7-сегментного дисплея. Это потому, что вы можете отображать либо строчные, либо прописные буквы. например

«abcdef» может отображаться как

 _     _     _  _
!_!!_ !   _!!_ !_ 
! !!_!!_ !_!!_ !  

Обратите внимание, что каждый символ представляет собой матрицу 3x3, состоящую из !и _.

Конечно, 7-сегментный дисплей может использоваться для отображения цифр и символов:

 _     _  _  _           _  _     _    
  ! _ !_ !_ !      _!  !!_ !_!!  !_!!_!
  !    _!!_ !_!   !_!  ! _!!  !_ ! ! _!

Некоторые буквы могут иметь как верхний, так и нижний регистр:

 _                 _          
!   _ !_!!_   !   ! ! _ ! !   
!_ !_ ! !! !  !  !!_!!_!!_!!_!

Вот полный набор символов:

 _     _  _     _  _  _  _  _                       _
! !  ! _! _!!_!!_ !_   !!_!!_!    _ !_     _     _  _!
!_!  !!_  _!  ! _!!_!  !!_! _!   !_ ! !  !!_!!_!   !  

 _     _     _  _  _                 _  _  _     _           _ 
!_!!_ !   _!!_ !_ !  !_!  !  !!   _ ! !!_!!_! _ !_ !_ ! !!_! _!
! !!_!!_ !_!!_ !  !_!! !  !!_!!_ ! !!_!!    !!   _!!_ !_! _!!_ 

Обратите внимание, что есть пробел ( ), тире ( -) и знак вопроса ( ?). В письме I, Oи Zтакие же , как числа 1, 0и 2соответственно.

В этом задании вы напишите программу или функцию для отображения строки, используя 7-сегментный формат отображения выше.

правила

  1. Вы можете написать программу или функцию

  2. Это код-гольф, выигрывает самый короткий код в байтах

  3. Ваша программа или функция должны получать ввод из STDIN или в качестве параметра. И выводит строку в STDOUT или в виде строки в 3 строки без пробела, но завершается символом новой строки. Обрабатывать верхний / нижний регистр CHIOUправильно.

  4. При желании вы можете распечатать конечные пробелы

  5. Вы должны следовать формату выше. Использование подчеркивания _и восклицательного знака !для формирования вашего 7-сегментного дисплея.

  6. Вы должны поддерживать пробелы ( ), тире ( -) и вопросительный знак ( ?)

  7. Если строка содержит неподдерживаемый символ (k, m, v, w, x), отображается один символ ошибки (линия 3 горизонта, см. Пример). Помимо 5 неподдерживаемых символов, вы можете предположить, что ввод состоит только из поддерживаемого набора символов.

  8. Я решил не использовать букву в нижнем регистре L ( l) из-за путаницы, но если вы склонны, вы можете отобразить ее как 1справа или слева.

Примеры

$./a.out Start
 _     _    
!_ !_ !_! _ !_
 _!!_ ! !!  !_
$./a.out "7-seg dIsplay"
 _     _  _  _           _  _     _ 
  ! _ !_ !_ !      _!  !!_ !_!!  !_!!_!
  !    _!!_ !_!   !_!  ! _!!  !_ ! ! _!
$./a.out "0123456789 chiou-?"
 _     _  _     _  _  _  _  _                       _
! !  ! _! _!!_!!_ !_   !!_!!_!    _ !_     _     _  _!
!_!  !!_  _!  ! _!!_!  !!_! _!   !_ ! !  !!_!!_!   !
$./a.out "ABCDEFGHIJLNOPQRSTUZ"
 _     _     _  _  _                 _  _  _     _        _
!_!!_ !   _!!_ !_ !  !_!  !  !!   _ ! !!_!!_! _ !_ !_ ! ! _!
! !!_!!_ !_!!_ !  !_!! !  !!_!!_ ! !!_!!    !!   _!!_ !_!!_
$./a.out "abcdefghijlnopqrstuz"
 _           _  _  _                    _  _     _        _
!_!!_  _  _!!_ !_ !  !_      !!   _  _ !_!!_! _ !_ !_     _!
! !!_!!_ !_!!_ !  !_!! !  !!_!!_ ! !!_!!    !!   _!!_ !_!!_
$./a.out "Bad Form"
 _
 _
 _
$./a.out "Hello"
    _       
!_!!_ !  !   _
! !!_ !_ !_ !_!
$./a.out "World"
 _
 _
 _

Да, вы можете предположить, что нет неподдерживаемых символов. Я намерен сделать так, чтобы строки, содержащие k, m, v, w, xих, не отображались.
некий пользователь


Я думаю, что вы перепутали возврат каретки (CR, \r) с переводом строки (LF, \n). * nix использует LF, а Windows использует CRLF. Только некоторые устаревшие системы используют CR самостоятельно. Более подробная информация здесь: en.wikipedia.org/wiki/Newline
Винни

Ваш персонаж "8", кажется, имеет полосу "|" вместо восклицательного знака "!". Это предназначено?
coredump

1
@ Винни, ты прав, конечно. Мне было лень искать это, когда я это написал.
некий пользователь

Ответы:


7

CJam, 123 114 112 110 байт

Qq_eu";=KMVWX":T&"@"@?" -chiou"Tereu{i"^A^W^G;^Þ¯     ^Þ^Û9³·^É¿»
^@
^P
^Ü^Ò½7¦^_¶´§=   ^O^V&5^U¯¼¹^T³6/"=i2b9Ue[3/"!_!"f.{S?}.+}/N*

Выше используется символ каретки, так как код содержит непечатаемые символы. Одним из них является null byte ( ^@), что означает, что этот код может быть выполнен только из командной строки.

Мы можем исправить это только за счет двух дополнительных байтов (всего 112 ).

Qq_eu";=KMVWX":T&"@"@?" -chiou"Tereu{i"AWG{ÞïIÞÛyó÷Éÿû
@
P
ÜÒýwæ_öôç}IOVfuUïüùTóvo"=i448+2b1>3/"!_!"f.{S?}.+}/N*

На этот раз все символы для печати. Попробуйте онлайн в интерпретаторе CJam .

Пример запуска

$ LANG=en_US
$ xxd -ps -r > 7seg.cjam <<< 51715f6575223b3d4b4d565758223a5426224022403f22202d6368696f752254657265757b69220117073b9eaf099e9b39b3b789bfbb0a000a100a9c92bd37a61fb6b4a73d090f16263515afbcb914b3362f223d6932623955655b332f22215f2122662e7b533f7d2e2b7d2f4e2a
$ wc -c 7seg.cjam 
110 7seg.cjam
$ echo -n '0123456789 chiou-?' | cjam 7seg.cjam; echo
 _     _  _     _  _  _  _  _                       _ 
! !  ! _! _!!_!!_ !_   !!_!!_!    _ !_     _     _  _!
!_!  !!_  _!  ! _!!_!  !!_! _!   !_ ! !  !!_!!_!   !  
$ echo -n 'ABCDEFGHIJLNOPQRSTUYZ' | cjam 7seg.cjam; echo
 _     _     _  _  _                 _  _  _     _           _ 
!_!!_ !   _!!_ !_ !  !_!  !  !!   _ ! !!_!!_! _ !_ !_ ! !!_! _!
! !!_!!_ !_!!_ !  !_!! !  !!_!!_ ! !!_!!    !!   _!!_ !_! _!!_ 
$ echo -n 'World' | cjam 7seg.cjam; echo
 _ 
 _ 
 _

Идея (версия для печати)

Каждый символ может быть показан на 9-сегментном дисплее

!_!
!_!
!_!

заменив некоторые из его символов символов пробелами.

Мы можем превратить определенный символ в целое число, заменив каждый показанный сегмент в естественном порядке чтения на 1 , каждый не показанный сегмент на 0 и учитывая полученные двоичные цифры.

Первый и третий сегменты никогда не показываются, поэтому это даст целые числа в диапазонах [0,64) и [128,192) .

Мы можем закодировать каждое из этих целых чисел одним байтом, но половина из них приведет к непечатным символам. Таким образом, мы добавляем 64 к каждому целому числу перед приведением к символу, что гарантирует, что кодовые точки находятся в диапазонах [64,128) и [192,256) .

Единственным непечатаемым символом в этих двух диапазонах является DEL (кодовая точка 127), что соответствует следующей неподдерживаемой конфигурации дисплея:

!_!
!_!

Мы можем изменить приведенную выше кодировку, добавив 448 == 512 - 64 к каждой кодовой точке, преобразовав в базу 2 и удалив первую двоичную цифру.

Все, что осталось, чтобы найти эффективный способ связывания этих закодированных сегментов с соответствующими им символами ASCII.

Если мы сопоставим символы символов " -chiou"с символами ";=KMVWX"и преобразуем весь ввод в верхний регистр, мы можем просто сохранить кодировку для всех символов между 0(кодовая точка 48) и Z(кодовая точка 90), давая диапазон 43.

Индексирование массива является модульным в CJam, поэтому если Aэто строка длиной 43 A86=, A43=и A0=все они дают одинаковые результаты. Символ с кодовой точкой 86 таков V, что мы просто сохраняем закодированные сегменты V - Z и 0 - U по порядку.

В реальном коде мы выбираем знак at как символ «плохой формы», заменяем весь ввод на строку, "@"если он содержит запрещенную букву, и выполняем шаги, описанные выше.

Код (версия для печати)

Q            e# Push an empty array for posterior concatenation.
q            e# Read from STDIN.
_eu          e# Copy the input and convert is to uppercase.
";=KMVWX":T& e# Intersect the result with with T := ";=KMVWX".
"@"@?        e# Select "@" if truthy and the input if falsy.
" -chiou"Ter e# Perform transliteration.
eu           e# Convert everything to uppercase.
{            e# For each character in the modified input:
  i          e#   Push its code point.
  "…"=       e#   Select the corresponding character from the string.
  i448+      e#   Push that character's code point and add 448.
  2b1>       e#   Convert to base 2 and discard the first digit.
  3/         e#   Group into triplets of digits (rows).
  "!_!"      e#   Push that string.
  f.{        e#   For each group of digits:
    S?       e#     Select the corresponding char of "!_!" for 1 and " " for 0.
  }          e#
  .+         e#   Concatenate along the rows with the previous results.
}/           e#
N*           e# Join, separating by linefeeds.

2

Perl, 475 469 424 390 280 272 байта

$_=<>;die" -
"x3if/[kmvwx]/i;y/chiou/kmvwx/;$_=lc;while(/(.)/g){$z=ord($1=~y/a-z0-9\-\? /{v\x17nWS7z(.F\x16rb?[yBuV> f&|O?(Omxuw)\x7f}@K\0/r);$i.=$z&1?' _ ':$"x3;$m.=($z&16?'!':$").($z&64?'_':$").($z&8?'!':$");$p.=substr("  !  _!_",$z&6,2).($z&32?'!':$")}print"$i
$m
$p
"

многострочный с комментариями:

$_=<>;   # accept input
die" -   # check for invalid chars
"x3if/[kmvwx]/i;
y/chiou/kmvwx/;$_=lc;   # substitute invalid chars, convert to lowercase
while(/(.)/g)   # loop over each character
    # lookup character from string using transliteration and convert to
    # number using ord() for bit checking:
    {$z=ord($1=~y/a-z0-9\-\? /{v\x17nWS7z(.F\x16rb?[yBuV> f&|O?(Omxuw)\x7f}@K\0/r);
    $i.=$z&1?' _ ':$"x3;    # first row
    $m.=($z&16?'!':$").($z&64?'_':$").($z&8?'!':$");   # second row
    $p.=substr("  !  _!_",$z&6,2).($z&32?'!':$")}    # third row
# print result:
print"$i
$m
$p
"

Битовые шаблоны, кодирующие сегменты, хранятся в строке (за исключением 3 непечатаемых символов с использованием \xи использованием \0для пробела) и отображаются на входные символы с помощью оператора транслитерации Perl.

Для 5 из 7 сегментов, побитовых и используется вместе с троичным оператором для вывода пробела или символа сегмента. Для двух нижних левых сегментов (кодированных 2 и 4 в наборе битов) используется поиск подстроки в 8-символьную строку для сохранения 2 байтов.

Спасибо Dom Hastings за советы по игре в гольф на Perl.

Старая версия (с использованием регулярных выражений для кодирования шаблонов), 390 байт:

$_=<>;if(/[kmvwx]/i){print" -\n"x3;exit}y/chiou/kmvwx/;$_=lc;while(/(.)/g){$z=$1;$i.=($z=~/[acefgopqsz\?0235-9]/?' _ ':'   ');$m.=($z=~/[abce-hlmopqstuy045689]/?'!':' ').($z=~/[abdefhkmnp-twyz\-\?2-689]/?'_':' ').($z=~/[adhijopquyz\?0-4789]/?'!':' ');$p.=($z=~/[a-hj-prtuwxz\?0268]/?'!':' ').($z=~/[b-egjklostuw-z0235689]/?'_':' ').($z=~/[abdg-jmnoqsu-y013-9]/?'!':' ')}print"$i\n$m\n$p\n"

многострочный с комментариями:

$_=<>;   # accept input
if(/[kmvwx]/i){print" -\n"x3;exit}   # check for invalid chars
y/chiou/kmvwx/;$_=lc;   # substitute invalid chars, convert to lowercase
while(/(.)/g)
{$z=$1;$i.=($z=~/[acefgopqsz\?0235-9]/?' _ ':'   '); # first row
$m.=($z=~/[abce-hlmopqstuy045689]/?'!':' ').
($z=~/[abdefhkmnp-twyz\-\?2-689]/?'_':' ').
($z=~/[adhijopquyz\?0-4789]/?'!':' '); # second row
$p.=($z=~/[a-hj-prtuwxz\?0268]/?'!':' ').
($z=~/[b-egjklostuw-z0235689]/?'_':' ').
($z=~/[abdg-jmnoqsu-y013-9]/?'!':' ')} # third row
print"$i\n$m\n$p\n" # print result

Строка считывается и проверяется на наличие недопустимых символов, используя регулярное выражение, и завершается, если они найдены. Затем допустимые символы нижнего регистра заменяются на недопустимые символы, а вся строка преобразуется в нижний регистр.

Строки генерируются по одной, с 1 сегментом на букву в первой строке и 3 на двух других. Для каждой строки строка обрабатывается по одному символу за раз, и этот символ сопоставляется с регулярным выражением для каждого сегмента, чтобы проверить, если a! или _ должен отображаться. Использование регулярных выражений означает, что для символов, где сегмент не задан, требуется 0 бит на сегмент для каждого символа, чтобы кодировать, следует ли его устанавливать, а для тех, где он установлен, в среднем требуется чуть менее 8 бит, поскольку диапазоны символов регулярного выражения могут быть используемый. Таким образом, получается около 3 или 4 бит на сегмент на символ в наборе, или около 21-24 бит на символ.

Он не обрабатывает перенос строк.


1
Эй @ samgak, рад видеть больше любви Perl! Я заметил несколько вещей, которые могут помочь вам сбрить некоторые байты, и хотел поделиться ими! Вы можете использовать некоторые из магических переменных Perl, чтобы помочь уменьшить это; ' 'может быть заменен на $"и ' 'может быть, $"x3который урезает несколько, ваши \nмогут быть буквальными символами новой строки, чтобы избавиться от еще нескольких. Ваш ранний выход тоже может быть закорочен, используя die, так что это if(/[kmvwx]/i){print" -\n"x3;exit}становится die" - "x3if(/[kmvwx]/i). Также вы можете перестроить цикл, чтобы избежать скобок, и вам не нужно $zэкономить еще несколько!
Дом Гастингс

1
Я надеюсь, что вы не обижены, но я посмотрел на снижение еще, gist.github.com/dom111/e651b5de8c7e7fc9a6cf . До 323!
Дом Гастингс

@DomHastings без обид, вообще, спасибо за отличные советы по игре в гольф! Я использовал столько их, сколько мог в своем отредактированном ответе, который я изменил, чтобы использовать побитовое кодирование вместо регулярных выражений для шаблонов сегментов. К сожалению, $ z вернулся, и я не могу понять, как от него избавиться. Кроме того, $_=lc<>не работает, потому что тогда код не может различить
CHIOU в

1

Обыкновенный Лисп, 488 416

(lambda(z)(dotimes(r 3)(map()(lambda(c)(do((i 0(+ 17 i))n)((or(and(> i 901)(setf n 146))(=(char-code c)(ldb(byte 8 9)(setf n(ldb(byte 17 i)#36RIL884OIVFXJY4DCQ0O8DPH8MOMR2DSLPP3O4ESYHS234A9HEQYSV8IBDBZI6Z3C3MCVR77OYD3QN5G6CX2UQWGL4UY5R9PKYI1JQ5Y6DC27MQQGUZSCGI8Q9JCYP9N1L4YYKRWM1ZNMSVTSB4792UUWV6Z3906VSP981WCCBMDNJ02)))))(loop for v from(* 3 r)for d across"!_!"do(format t"~:[ ~;~A~]"(logbitp v n)d)))))z)(terpri)))

пример

С "abcdefg'hijklnopqrstuz"отпечатками:

 _           _  _  _  _           _           _  _     _        _ 
!_!!_  _  _!!_ !_ !   _ !_   !  ! _ !   _  _ !_!!_! _ !_ !_     _!
! !!_!!_ !_!!_ !  !_! _ ! !  !!_! _ !_ ! !!_!!    !!   _!!_ !_!!_ 

замечания

Символы и их представления закодированы в этом числе в базе 36:

IL884OIVFXJY4DCQ0O8DPH8MOMR2DSLPP3O4ESYHS234A9HEQYSV8IBDBZI6Z3C3MCVR77OYD3QN5G6CX2UQWGL4UY5R9PKYI1JQ5Y6DC27MQQGUZSCGI8Q9JCYP9N1L4YYKRWM1ZNMSVTSB4792UUWV6Z3906VSP981WCCBMDNJ02

Двоичное представление этой цифры разделено на группы по 17 бит.

Например, последняя группа из 17 битов 110000111101010, которая здесь разбита на две части:

  1. 110000, код символа 0
  2. 111101010кодировка чертежа, лучше всего представленная следующим образом:

    010 (bits 0-2)         _ 
    101 (bits 3-5)   =>   ! !
    111 (bits 6-8)        !_!
    

    Биты в первом и последнем «столбце» предназначены для !символов, а в среднем столбце - для _символа. При необходимости хранятся версии символов в верхнем и нижнем регистре.

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


Спасибо за участие в конкурсе. Я заметил, что ваш «K» отображается как «L» в вашем выводе. Возможно, вы неправильно поняли, что неподдерживаемый символ не может быть напечатан вместе с другим допустимым символом. Кроме того, я вижу, что вы добавили 'персонажа, что приятно; однако он будет отображаться за пределами того, на что способен 7-сегментный дисплей. Если вы переместитесь !вниз на 1 строку, это будет идеально.
какой-то пользователь

Я обновлю 'символ и отредактирую вопрос, Kпотому что на самом деле я поставил не Kв том месте во входной строке ("... jlKn ...") ;-) Вы можете увидеть тройные бары (ошибка) просто после Л. Спасибо, что заметили.
coredump

1

JavaScript (ES6), 380 352 324 байта

( Примечание. В коде используется символ каретки, поскольку он содержит некоторые непечатаемые символы. Чтобы получить оригинальный код, щелкните здесь и выберите необработанные данные. И нет, hэто не программа CJam.;)

d=s=>{a=' ',u=n=>r>>n&1?'!':a,v=n=>r>>n&1?'_':a,g='ABCDEFGHIJLNOPQRSTUYZabcdefghijlnopqrstuyz0123456789-? ÿ',h='{vUnWSuz(lTb}[;B7V|>O{vFnWSur lTbf[;B7Vd>O}(O/:7w)^??^BK^0^G',x=y=z='';for(i=0;i<s.length;x+=a+v(0)+a,y+=u(4)+v(1)+u(3),z+=u(6)+v(2)+u(5)){q=g.indexOf(s[i++]);if(q<0)return d`ÿ`;r=h.charCodeAt(q)}return x+`
${y}
`+z}

Называется как d("7-seg display")или похожий. Работает в Firefox 40, но может не работать в других браузерах. По какой-то причине фрагмент HTML / JS не сохраняет непечатаемые, но вы можете скопировать и вставить необработанные данные отсюда .

Ungolfed:

( Примечание: g и hбыли дополнены пробелами , чтобы соответствовать 8, -, ÿи spaceс их соответствующими значениями Unicode) .

d = function (s) {
  t = function (n) { return Math.floor(n) % 2; };
  g = 'ABCDEFGHIJLNOPQRSTUYZabcdefghijlnopqrstuyz012345679? 8      -      ÿ      space ';
  h = '{vUnWSuz(lTb}[;B7V|>O{vFnWSur lTbf[;B7Vd>O}(O/:7w)?K \u007f \u0002 \u0007 \u0000';
  x = y = z = '';
  for(var i = 0; i < s.length; i++) {
    q = g.indexOf(s.charAt(i));
    if (q < 0)          // if g does not contain the character
      return d('ÿ');    // ÿ is equivalent to the error character, '\u0007'
    r = h.charCodeAt(q);
    x += ' ' + (r % 2 === 1 ? '_' : ' ') + ' ';
    y += (t(r / 16) === 1 ? '!' : ' ') + (t(r / 2) === 1 ? '_' : ' ') + (t(r / 8) === 1 ? '!' : ' ');
    z += (t(r / 64) === 1 ? '!' : ' ') + (t(r / 4) === 1 ? '_' : ' ') + (t(r / 32) === 1 ? '!' : ' ');
  }
  return x + '\n' + y + '\n' + z;
}

Объяснение:

Я сразу заметил, что 7 сегментов, преобразованные в 0/ 1бит, будут хорошо сочетаться с первыми 128 символами Юникода. Проблема с этой идеей состоит в том, что 1/4 из этих символов являются непечатными управляющими символами. Используя их в моем коде, выглядело бы невероятно грязно (или невероятно умно; я не решил, какой именно). Чтобы решить эту проблему, сохранив при этом простоту остального кода, мне пришла в голову эта идея:

За исключением -, пространства и ошибок , ни один из персонажей не отсутствовали оба нижних вертикальных сегментов. Поэтому, чтобы убедиться, что все эти символы остались между 0020и 007f, я просто отобразил 64 и 32 бита в эти сегменты, вот так:

     1
    ---
16 |   | 8
  2 ---
64 |   | 32
    ---
     4

Номера других 5 сегментов не слишком важны; они могут быть расположены любым другим способом и все еще иметь все те же символы "в границах".

В качестве примера, вот кодированная версия A :

     1
    ---
16 |   | 8
  2 ---
64 |   | 32

Dec: 64 + 32 + 16 + 8 + 2 + 1 = 123
Hex: 40 + 20 + 10 + 8 + 2 + 1 = 7B = u+007B = {

Затем я вставил закодированную версию каждого 7-сегментного символа в h. Однако, в 8результате 007f( управляющий код удаления ; постоянная независимо от того, как сегменты расположены), пробел не привело 0000нулевом коде, также константа), -в результате 0002, и ошибка привела 0007. Я копировать-вставить необработанные байты в правильное положение 8, -и ошибка ; пространство было легко достигнуто с \0.

После всего этого кодирования все, что мне нужно было сделать, это использовать его для декодирования строки и вывода в 7-сегментном читаемом формате. Я использовал для цикла и трех переменных ( x, y, и z, каждая из которых соответствует выходной линии) , чтобы пройти через каждый символ в строке , и добавить его 7-сегм эквивалент к выходу. Я выбрал ÿдля ошибки характера , потому что AFAIK, это не на любой клавиатуре, и это последний символ в u+0000-u+00ffдиапазоне. Возможно, я мог бы быть остроумным и избранным Ξ(греческая буква XI) вместо ....;)

Edit 1: Сохраненный кучу пространства путем создания мини-функции , чтобы определить , является ли !, _или требуется.

Изменить 2: сэкономил много места, используя уловки, которые я выучил с тех пор, как в последний раз посетил этот пост

Как обычно, предложения очень ценятся!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.