使用7段显示器显示单词


13

我的第一个编程拼图和代码高尔夫球是“ 七斜线显示器”。这是我的第一个挑战,也是基于7段显示的。

除了数字以外,我经常考虑使用简单的7段显示器可以显示哪种字母。原来可以显示很多字母。实际上,除字母K,M,V,W,X之外的所有字母都可以使用单个7段显示器显示。这是因为您可以显示字母的小写或大写。例如

“ abcdef”可以显示为

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

请注意,每个字符都是由!和组成的3x3矩阵_

当然,可以使用7段显示器来显示数字和符号:

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

某些字母可以同时大小写:

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

这是完整的字符集:

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

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

注意,有一个空格(),破折号(-)和问号(?)。信中IOZ是相同的号码102分别。

在此挑战中,您将编写一个程序或函数来使用上面的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
Winny

您的“ 8”字符似乎带有一个竖线“ |” 而不是感叹号“!”。有意吗
coredump

1
@Winny,你当然是对的。当我写它的时候,我懒得去找它。
一些用户

Answers:


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*

由于代码包含不可打印的字符,因此上面使用了插入符号。其中之一是空字节(^@),这意味着只能从命令行执行此代码。

我们只需再多两个字节(总共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)[128192)

我们可以将每个整数编码为单个字节,但是其中一半将导致无法打印的字符。因此,我们在强制转换为字符之前将64添加到每个整数,以确保代码点在[64,128)[192,256)范围内。

这两个范围中唯一不可打印的字符是DEL(代码点127),它对应于以下未使用的显示配置:

!_!
!_!

我们可以通过将448 == 512-64添加到每个代码点,转换为基数并删除第一个二进制数字来逆转上述编码。

找到所有将这些编码的段与它们对应的ASCII字符相关联的有效方法。

如果我们将的字符映射" -chiou"到的字符";=KMVWX"并将整个输入转换为大写,我们可以简单地存储0(代码点48)和Z(代码点90)之间所有字符的编码,范围为43。

数组索引是在CJam模块化的,因此,如果A是长度43的字符串,A86=A43=A0=所有产生相同的结果。代码点为86的字符是V,因此我们仅按顺序存储V-Z0-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
"

编码段的位模式存储在字符串中(使用\x和使用\0空格转义3个不可打印的字符),并使用Perl音译运算符将其映射到输入字符。

对于7个段中的5个,按位与和三元运算符一起使用以输出空格或段字符。对于左下两段(在位集中由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个。对于每一行,该字符串一次处理一个字符,并且针对每个段将该字符与正则表达式进行匹配,以检查是否有!或_应该显示。使用正则表达式意味着,对于未设置段的字符,每段每个字符占用零位来编码是否设置该字符;对于那些未设置该段的字符,则平均花费不到8位,因为正则表达式的字符范围可以是用过的。因此,它计算出集合中每个字符每段大约3或4位,或者每个字符大约21-24位。

它不处理换行。


1
嘿@samgak,很高兴看到更多Perl的爱!我注意到一些可以帮助您减少一些字节并想要共享的事情!您可以使用Perl的一些魔术变量来减少这种情况。' '可以替换为$"' '也可以$"x3修剪一些,您的\ns可以是字面换行符,以去除更多内容。您也可以使用die缩短您的提前退出时间,从而if(/[kmvwx]/i){print" -\n"x3;exit}成为die" - "x3if(/[kmvwx]/i)。加上更多的伪装,您可以重新排列循环,避免使用括号,您无需$z再多保存一些!
Dom Hastings

1
希望您不会感到冒犯,但我查看了更多减少方法gist.github.com/dom111/e651b5de8c7e7fc9a6cf。降至323!
Dom Hastings

@DomHastings丝毫没有冒犯,感谢您的出色高尔夫技巧!我在编辑后的答案中使用了尽可能多的样式,已将其更改为对段模式使用按位编码而不是正则表达式。不幸的是,$ z又回来了,我不知道该如何摆脱它。另外,$_=lc<>它也不起作用,因为这样代码就无法区分大小写的CHIOU
samgak 2015年

1

普通Lisp 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 ...”);-)您可以看到三栏(错误)在L.之后感谢您的注意。
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代码段不会保存不可打印的内容,但是您可以从此处复制粘贴原始数据。

取消高尔夫:

注: gh已用空格填充匹配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;
}

说明:

我立即注意到,转换为0/ 1位的7个段与前128个Unicode字符配合得很好。这个想法的问题是这些字符中的1/4是不可打印的控制字符。在我的代码中使用它们会使它看起来令人难以置信的混乱(或令人难以置信的聪明;我还没有决定哪一个)。为了在保持其余代码简单的同时解决此问题,我想到了这个想法:

除了-spaceerror之外,没有一个字符遗漏了两个较低的垂直段。因此,要确保所有这些字符都位于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段可读格式输出它。我使用了for循环和三个变量(xyz,每个对应于一条输出线)遍历字符串中的每个字符,并将其7段等效值添加到输出中。我选择ÿ错误字符,因为AFAIK不在任何键盘上,它是u+0000-u+00ff范围中的最后一个字符。也许我本可以很机灵,然后选择了Ξ(希腊字母xi)。

编辑1:保存通过创建的最小函数一堆空间,以确定是否!_或者是需要的。

编辑2:使用我上次访问此帖子以来学到的技巧,节省了一堆空间。

与往常一样,建议非常感谢!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.