代码高尔夫:七段

时间:2009-09-10 20:03:26

标签: language-agnostic code-golf rosetta-stone

挑战

按字符数排序的最短代码,用于生成给定十六进制数的七段显示表示。

输入

输入仅由数字[0-9]和小写字母[a-fA-F]中的十六进制字符组成。没有必要处理特殊情况。

输出

输出将是输入的七段表示,使用 ASCII 面:

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

限制

禁止使用以下内容:eval,exec,system,figlet,toilet和外部库。

测试用例:

Input:
    deadbeef

Output:
        _  _        _  _  _ 
     _||_ |_| _||_ |_ |_ |_ 
    |_||_ | ||_||_||_ |_ |  


Input:
    4F790D59

Output:
        _  _  _  _     _  _ 
    |_||_   ||_|| | _||_ |_|
      ||    | _||_||_| _| _|

代码计数包括输入/​​输出(即完整程序)。

26 个答案:

答案 0 :(得分:30)

C89(181个字符; args)

char*q,a=3;p(l){putchar(*q?"|#]u&rzc~vn:X=ZJ"[*q-(*q&64?55:48
)&15]+1>>l&1?"|_||_|_"[l]:32:10);}main(r,v)char**v;{for(;a--
;p())for(q=v[1];*q;++q)for(r=3;r--;)p(a-2?5-r-a*3:r-1?7:6);}

C89(192个字符; stdin

char*q,b[9],gets(char*),a=3;p(l){putchar(*q?"|#]u&rzc~vn:X=ZJ"[*
q-(*q&64?55:48)&15]+1>>l&1?"|_||_|_"[l]:32:10);}main(r){for(gets
(b);a--;p())for(q=b;*q;++q)for(r=3;r--;)p(a-2?5-r-a*3:r-1?7:6);}

说明:

char*q,b[9],gets(char*),a=3;
p(l){
    putchar(*q?
        /*
         * Each element of the magic string is decremented so 0x7F is
         * '~' (0x7E).  Each bit before the decrement represents
         * a segment (thus "8" is 0x7F (0x7E), i.e. all 7 bits on).
         * Bit 7 is always cleared so p(7) always prints a space.
         */
        "|#]u&rzc~vn:X=ZJ"
        [*q-(*q&64?55:48)&15]+1 /* d[ascii2hex(*q)] + 1 */
        >>l&1                   /* Is bit 'l' set? */
            ?"|_||_|_"[l]       /* Yes; choose _ or | by position. */
            :32                 /* No; enter a space. */
    :10);                       /* End of line. */
}
main(r){
    for(gets(b);a--;p())                /* Grab input and loop through each of 3 lines (a = 2, 1, 0). */
        for(q=b;*q;++q)                 /* Iterate across input. */
            for(r=3;r--;)               /* For each of three characters across... */
                p(a-2?5-r-a*3:r-1?7:6); /* Print the segment, mapping position to the bit. */
}

答案 1 :(得分:30)

Perl,134个字符

可能会删除所有换行符。

@s=unpack"C*",~"P\xdbLI\xc3a`[\@AB\xe0t\xc8df";
$_=<>;for$s(6,3,0){print map$s[hex$&]&1<<$_+$s?$_%2?"_":"|":" ",
0..2while/./g;print$/}

解释

@s存储每个段的位。这些条目的顺序从0到F(感谢hex()),这些位按顺序映射到段:

6 7 x
3 4 5
0 1 2

0是LSB。 (第6位未使用)。这些值被打包存储在字符串中,因此存在更多可打印字符; ~运算符翻转位并解包给我数字(perl的按位运算符在字符串方面非常笨拙)。

随着手中的数据,我读取输入并继续循环三次;三个循环之间的唯一区别是所需的位掩码。对于输入的每个字符,打印三个输出字符。要打印的字符是

$s[ hex $& ] & (1 << ($_ + $s) )
? ($_ % 2 ? "_" : "|" )
: " "

其中@s是查找表,$s是根据行的效果变化,$_是我们是否在打印第1,第2或第3个字符排。如果查找表条目中的右侧位为false,则打印一个空格;否则会打印“|”在两侧或中间的“_”。

答案 2 :(得分:14)

COM可执行文件:102字节

使用A86(这是原始的更大版本)汇总以下内容:

dd 0801E8Ah,0BD80C380h,03B50154h,0D789D58Ah,0B20082BEh,077F33B03h,0C048A29h,0149F0420h
dd 020AD431h,088C402C4h,01468BC1h,0F8C1E0D3h,046220Fh,0AA036E8Dh,0DD75CAFEh,04609ED83h
dd 0C583D1EBh,0D0AB809h,075CDFEABh,0AA24B0C3h,021CD09B4h,05F0000C3h,020B7EBh,8EFB7C00h
dd 07C3EF75Fh,0BF7CF9E4h,0B6DE5FA2h
dw 0F47Ch
db 0DFh

编辑:

DosBox问题可能是程序在启动时假定寄存器值的方式。无论如何,这里是修改后的源,它组装成102个字节,应该与DosBox一起使用:

    mov bp,d1
    mov ch,3
    mov dx,ds ; if you want to use dos box, put "mov dx,08000h" here instead, it might fix the problem
    mov di,dx
l4: mov si,082h
l3: mov bl,3
    cmp byte ptr [si],0dh
    je l5
    mov cl,[si]
    cmp cl,40h
    jle l2
    add cl,9
l2: and cl,0fh
l1: mov ax,word ptr [bp+1]
    shl ax,cl
    sar ax,15
    and al,byte ptr [bp]
    add bp,3
    stosb
    dec bl
    jnz l1
    sub bp,9
    inc si
    jmp l3
l5: add bp,9
    mov ax,0d0ah
    stosw
    dec ch
    jnz l4
    mov al,'$'
    stosb
    mov ah,9
    int 21h
d1: ret
    dw 0
    db '_'
    dw 01011011111101011xb
    db ' '
    dw 0
    db '|'
    dw 01000111011111011xb
    db '_'
    dw 00011111011110111xb
    db '|'
    dw 01111100111100100xb
    db '|'
    dw 01010001010111111xb
    db '_'
    dw 01011011011011110xb
    db '|'
    dw 01101111111110100xb

感谢ephemient的一些调整!

答案 3 :(得分:13)

x86(146字节; args)

受到Jonas Gulle Code Golf: The wave的启发。通常我会编写32位Linux ELF,但16位DOS COM要小得多(指令更短,开销为零)。

46条指令和24条未执行的单词。 (它们最终在那里显然很突出,不是吗?)没有什么比将代码重用为数据更棘手;无论如何,它可能不会节省超过10个字节。

C:\>od -xAn ss.com
 c930 82be ac00 0d3c 3e74 403c 027e 0904
 0f24 0198 bbc8 0162 c301 0eb4 078a 0424
 0474 7cb0 02eb 20b0 10cd 078a 0224 0474
 5fb0 02eb 20b0 10cd 078a 0124 0474 7cb0
 02eb 20b0 10cd bdeb f980 7420 b014 cd0d
 b010 cd0a 6610 c381 0010 0000 c180 eb10
 c3a1 0002 0202 0200 0202 0202 0002 0002
 0202 0105 0303 0607 0106 0707 0607 0304
 0606 0107 0306 0301 0107 0307 0705 0706
 0406
C:\>ss deadbeef
    _  _        _  _  _ 
 _||_ |_| _||_ |_ |_ |_ 
|_||_ | ||_||_||_ |_ |  

这只是逐字母打印第一行,然后是第二行等,使用3个字节来存储每个字符的9位数据。显然还有剩余空间用于增强...(这是我第一次使用NASM语法;我更习惯gas但我无法说服它输出原始二进制文件。)

org 0x100

; initialize registers
    xor cl,cl

; reset ds:[si] to start of arguments
start:
    mov si,0x82

; load one character of arguments
read:
    lodsb
    cmp al,0xd
    je next

; transform [0-9A-Fa-f] to [\x00-\x0f]
    cmp al,0x40
    jle skipa
    add al,0x9
skipa:
    and al,0xf

; load font definition
    cbw
    add ax,cx
    mov bx,letters
    add bx,ax
    mov ah,0xe

; print first char
    mov al,[bx]
    and al,0x4
    jz s1
    mov al,0x7c
    jmp short w1
s1:
    mov al,0x20
w1:
    int 0x10

; print second char
    mov al,[bx]
    and al,0x2
    jz s2
    mov al,0x5f
    jmp short w2
s2:
    mov al,0x20
w2:
    int 0x10

; print third char
    mov al,[bx]
    and al,0x1
    jz s3
    mov al,0x7c
    jmp short w3
s3:
    mov al,0x20
w3:
    int 0x10

; next character
    jmp short read

; print newline
next:
    cmp cl,0x20
    je end
    mov al,0xd
    int 0x10
    mov al,0xa
    int 0x10
    add ebx,0x10
    add cl,0x10
    jmp short start

end:
    ret

letters:
    db 2,0,2,2,0,2,2,2,2,2,2,0,2,0,2,2
    db 5,1,3,3,7,6,6,1,7,7,7,6,4,3,6,6
    db 7,1,6,3,1,3,7,1,7,3,5,7,6,7,6,4

答案 4 :(得分:6)

嗯,很难击败像Perl这样的专业语言。但是,这里的 Python 版本为 160字节

i=input().lower()
for x in[' #_ 14bd# ','| 1237d#_ 017c#| 56bcef','| 134579#_ 147af#| 2cef']: print(' '.join(''.join(y[j in y]for y in x.split('#'))for j in i))

ungolfed版本:

input_ = input().lower()

for magic in [' #_ 14bd# ',
          '| 1237d#_ 017c#| 56bcef',
          '| 134579#_ 147af#| 2cef',
         ]:
    # We have three lines, so x iterates over 3 magic strings.
    print(' '.join(
                # This is the cycle iterating over digits.
                ''.join(
                    # For each line and digit we need to print several
                    # letters. To do this, we break a magic string into
                    # 3 chunks. A chunk usually contains digits that
                    # *don't* have an element there. 
                    chunk[digit in chunk]
                    # For example, lower right chunk y="| 2cef". For digits
                    # 2, c, e, f, there should be " ", for all others there
                    # should be "|". So for digits 2, c, e, f, `j in y` returns
                    # False and indexes y[0], for other digits it indexes y[1]. 
                for chunk in magic.split('#'))
          for digit in input_)) 

答案 5 :(得分:6)

男人......无法击败perl。这里有163个字符的py3k。

i=input()
[print(''.join('     | _  _||  | ||_ |_|'[(7&(d>>l))*3:][:3]for d
in[255&0xb4b61fa637bdbbbf89b7b3399b9e09af>>int(x,16)*8 for x in i]))for
l in[6,3,0]]

解释。首先,这看起来完全没有优化:

# segment positions, easily understandable as octal.  first digit is top row
# last digit is bottom row.  high bit is first column, low bit last.

a=[0o257, 0o011, 0o236, 0o233,
   0o071, 0o263, 0o267, 0o211,
   0o277, 0o273, 0o275, 0o067,
   0o246, 0o037, 0o266, 0o264]

# and the corresponding segments:
#   421    421    421    421    421    421    421    421  
b=['   ', '  |', ' _ ', ' _|', '|  ', '| |', '|_ ', '|_|']

# function to look for the proper segment for a decoded digit:
def lookup(digit, line):
    return b[ 7& (digit>>(6-line*3))]

#function to encode an ascii hex string into coded form suitible for
#above function
def code(i):
    return [a[int(x,16)] for x in i]

def fmt(i):
    return '\n'.join(''.join(lookup(d,l) for d in code(i)) for l in [0,1,2])

i = input()
print(fmt(i))

然后我开始寻找打包数据的方法。首先,我可以将a转换为一个大的长整数,最后一个元素,一次8位。这产生,八进制:0o2645541764615736673577046675463463347404657。以十六进制表示,即0xb4b61fa637bdbbbf89b7b3399b9e09af,比八进制列表短90个字符。要使用它,你必须重写代码。看起来像是

def code_a_8(i):
    return [255&a_8>>int(x,16)*8 for x in i]

b可以连接,''.join(b)是26个字符,包括引号。查找功能也必须更改以支持此功能。

def lookup_b_cat(d, l):
    return b_cat[(7&(d>>6-l*3))*3:][:3]

接下来我只是通过将函数和常量折叠到表达式中来消除所有不需要的语法,这就是它。

也可以稍微收紧打印。不要加入线条,只需立即打印即可。这导致修改后的fmt()

def fmt_print(i):
    [print(''.join(lookup(d,l) for d in code(i))) for l in [0,1,2]]

答案 6 :(得分:5)

Golfscript - 116个字符

$ echo -n deadbeef | ./golfscript.rb  led.gs 
    _  _        _  _  _ 
 _||_ |_| _||_ |_ |_ |_ 
|_||_ | ||_||_||_ |_ | 

确保在结尾处没有额外的换行符保存,或者输入字符串将在末尾打印。

{32:^|}%:
{^' _':$@'14bd'{?~!=}:&~^}%n
{:x' |':|\'1237d'&$x'017c'&|x'56bcef'&}%n
{:x|\'134579'&$x'147af'&|x'2cef'&}%

工作原理

请注意,对于0-F范围,更多的段打开而不是关闭。列出每个段的例外(关闭段的数字)。

#Python version of the algorithm above
s=raw_input().lower()
J=''.join()
print J(' '+'_ '[c in'14bd']+' 'for c in s)
print J('| '[c in'1237d']+'_ '[c in'017c']+'| '[c in'56bcef']for c in s)
print J('| '[c in'134579']+'_ '[c in'147af']+'| '[c in'2cef']for c in s)

答案 7 :(得分:5)

C(170个字符)

i,j;main(c,s){char**r=s,*p=*++r;for(;i<3;)j--?putchar(!p[-1]?p=*r,++i,j=0,10:
"##3#3133X=W.<X/`^_G0?:0@"[i*8+c/2]-33>>c%2*3+j&1?"|_"[j&1]:32):(j=3,c=*p++&31,
c-=c>6?10:1);}

这将输入字符串作为命令行参数。转换为使用stdin将是另一个字符:

i,j;main(c){char s[99],*p=s;for(gets(s+1);i<3;)j--?putchar(!*p?p=s,++i,j=0,10:
"##3#3133X=W.<X/`^_G0?:0@"[i*8+c/2]-33>>c%2*3+j&1?"|_"[j&1]:32):(j=3,c=*++p&31,
c-=c>6?10:1);}

stdin版本最多可以接受98个输入字符。当然,任何超过floor(terminalWidth / 3)都会导致令人困惑的换行。

每个字符的输出被视为3x3网格,其中每行中的单元格是段。段是“开”或“关”。如果细分受众群“开启”,则会输出'|''_',具体取决于位置。如果它关闭,则输出一个空格。字符数组是一个位数组,用于确定每个段是打开还是关闭。关于代码之后的更多信息:

i,j; /* Loop variables. As globals, they'll be initialized to zero. */
main(c,s){
    /* The signature for main is
     *
     *     main(int argc, char **argv)
     *
     * Rather than add more characters for properly declaring the parameters,
     * I'm leaving them without type specifiers, allowing them to default to
     * int.  On almost all modern platforms, a pointer is the same size as
     * an int, so we can get away with the next line, which assigns the int
     * value s to the char** variable r.
     */

    char**r=s,*p=*++r;
    /* After coercing the int s to a char** r, offset it by 1 to get the
     * value of argv[1], which is the command-line argument.  (argv[0] would
     * be the name of the executable.)
     */

    for(;i<3;) /* loop until we're done with 3 lines */

        j--?
         /* j is our horizontal loop variable.  If we haven't finished a
          * character, then ... */

            putchar(  /* ...we will output something */
                !p[-1]? /* if the previous char was a terminating null ... */

                    p=*r,++i,j=0,10
                    /* ... reset for the next row.  We need to:
                     *
                     * - reinitialize p to the start of the input
                     * - increment our vertical loop variable, i
                     * - set j to zero, since we're finished with this
                     *   "character" (real characters take 3 iterations of
                     *   the j loop to finish, but we need to short-circuit
                     *   for end-of-string, since we need to output only one
                     *   character, the newline)
                     * - finally, send 10 to putchar to output the newline. */

                    :"##3#3133X=W.<X/`^_G0?:0@"[i*8+c/2]-33>>c%2*3+j&1?
                    /* If we haven't reached the terminating null, then
                     * check whether the current segment should be "on" or
                     * "off".  This bit of voodoo is explained after the
                     * code. */

                        "|_"[j&1]:32
                        /* if the segment is on, output either '|' or '_',
                         * depending on position (value of j), otherwise,
                         * output a space (ASCII 32) */
            )/* end of putchar call */

            :(j=3,c=*p++&31,c-=c>6?10:1);
            /* this is the else condition for j--? above.  If j was zero,
             * then we need to reset for the next character:
             *
             * - set j to 3, since there are three cells across in the grid
             * - increment p to the next input character with p++
             * - convert the next character to a value in the range 0–15.
             *   The characters we're interested in, 0–9, A–F, and a–f, are
             *   unique in the bottom four bits, except the upper- and
             *   lowercase letters, which is what we want.  So after anding
             *   with 15, the digits will be in the range 16–25, and the
             *   letters will be in the range 1–6.  So we subtract 10 if
             *   it's above 6, or 1 otherwise.  Therefore, input letters
             *   'A'–'F', or 'a'–'f' map to values of c between 0 and 5,
             *   and input numbers '0'–'9' map to values of c between
             *   6 and 15.  The fact that this is not the same as the
             *   characters' actual hex values is not important, and I've
             *   simply rearranged the data array to match this order.
             */
}

字符数组描述字符网格。数组中的每个字符描述两个输入字符的输出网格的一个水平行。网格中的每个单元格由一位表示,其中1表示该段处于“打开”状态(因此根据位置输出'|''_'),{{1 }表示该段是“关闭”。

数组中需要三个字符来描述两个输入字符的整个网格。数组中每个字符的最低三位(位0-2)描述了两行的偶数输入字符的一行。接下来的三位,即位3-5,描述了两个奇数输入字符的一行。第6和第7位未使用。这种排列的偏移量为+33,允许阵列中的每个字符都是可打印的,没有转义码或非ASCII字符。

我玩了几种不同的编码,包括将输入字符的所有7个段的位放入数组中的一个字符,但发现这个是整体最短的。虽然这个方案需要数组中的24个字符来表示只有16个输入字符的段,但是其他编码要么使用非ASCII字符(当我在我的Morse Code golf answer中使用它时不出所料地引起了问题),很多逃脱代码和/或复杂的解码代码。这个方案的解码代码非常简单,虽然它确实充分利用了C的运算符优先级来避免添加任何括号。

让我们把它分解成很小的步骤来理解它。

0

这是编码数组。让我们抓住适当的字符进行解码。

"##3#3133X=W.<X/`^_G0?:0@"

前8个字符描述了段的顶行,接下来的8个描述了段的中间行,后8个描述了最下面的段。

[i*8

请记住,到目前为止,c包含0到15之间的值,它对应于ABCDEF0123456789的输入,并且该数组对每个编码字符编码两个输入字符。因此,数组中的第一个字符 +c/2] 保存“A”和“B”顶行的位,第二个字符也是'#',编码“C”的顶行和'D',等等。

'#'

编码会产生多个低于32的值,这将需要转义码。此偏移将每个编码字符都放入可打印的未转义字符范围内。

-33

右移位运算符的优先级低于算术运算符,因此在减去偏移量后对字符进行此移位。

>>
对于偶数,

c%2*3 求值为零,对于奇数则为{1}},因此对于奇数字符,我们将右移3,得到3-5位,而对于偶数字符则不移位,提供对0-2位的访问。虽然我更喜欢使用c%2进行偶数/奇数检查,这就是我在其他地方使用的内容,c&1运算符的优先级太低,无需添加括号。 &运算符具有正确的优先级。

%

移位另外的+j 位以获得当前输出位置的正确位。

j

bitwise和运算符的优先级低于算术运算符和移位运算符,因此这将测试在移位将相关位置为零位后是否将位0设置为

&1

如果设置了位0 ......

?

...输出其中一个字符,由......选择

"|_"

...我们的水平循环变量是偶数还是奇数。

[j&1]

否则(未设置位0),输出32(空格字符)。


我认为如果有的话,我可以减少更多,但肯定不足以击败hobbs's perl entry

答案 8 :(得分:5)

Ruby:175

d="3yy0nxcoypnk4185nbr3k9ddjlhe".to_i 36
s=gets.chomp
o=''
for i in 0..2
s.each_char{|c|q=d>>c.to_i(16)*3
"|_|".each_char{|z|o<<(q&1>0?z:' ')
q>>=1}}
d>>=48
o<<"\n"
end
puts o

当更具可读性时......

d="3yy0nxcoypnk4185nbr3k9ddjlhe".to_i 36
s=gets.chomp
o=''
for i in 0..2
  s.each_char { |c|
    q = d >> c.to_i(16) * 3
    "|_|".each_char { |z|
      o << (q & 1 > 0 ? z : ' ')
      q >>= 1
    }
  }
  d >>= 48
  o << "\n"
end
puts o

答案 9 :(得分:4)

我的第一个代码高尔夫球。 279个非空白字符,433个包含空格。我确信它在Python中可能更短。

<强>的Python

import sys
w = sys.stdout.write
i = raw_input()
d = [111,9,94,91,57,115,119,73,127,123,125,55,102,31,118,116]
p = [' _ ','|','_','|','|','_','|']
j = 0
for r in range(3):
    for c in i.lower():
        for n in range(3 if r else 1):
            s = p[j+n]
            if (1<<6-j-n) & d[ord(c)-(ord('0') if c.isdigit() else ord('a')+6)]:
                w(s)
            else:
                w(' '*len(s))
    j += n+1
    w('\n')

答案 10 :(得分:4)

答案 11 :(得分:3)

F#,294个字符

我没有做任何聪明的事情,但仍然得到了可观的分数。

let rec G s=for r in[" _     _  _     _  _  _  _  _  _     _     _  _ ";"| |  | _| _||_||_ |_   ||_||_||_||_ |   _||_ |_ ";"|_|  ||_  _|  | _||_|  ||_| _|| ||_||_ |_||_ |  "]do Seq.iter(printf"%s"<<S r)s;printfn""
and S a h=a.Substring(3*(int h-if h<'A'then 48 elif h<'a'then 55 else 87),3)

为了清晰起见,用空格:

let rec G s=
    for r in[" _     _  _     _  _  _  _  _  _     _     _  _ ";
             "| |  | _| _||_||_ |_   ||_||_||_||_ |   _||_ |_ ";
             "|_|  ||_  _|  | _||_|  ||_| _|| ||_||_ |_||_ |  "] do 
        Seq.iter (printf "%s" << S r) s;
        printfn""
and S a h=
    a.Substring(3*(int h - if h<'A'
                           then 48 
                           elif h<'a'
                           then 55 
                           else 87),3)

样品:

G("abcdefFEDCBA9876543210")

输出:

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

答案 12 :(得分:3)

Python,共188个字符

我对其他解决方案并没有太多关注,但我确信仍有很大的改进空间。

n=int(raw_input(),16)
O=[""]*3
while n:O=["".join(" |_"[(m>>n%16*3+i&1)*(i%2+1)]for i in[2,1,0])+o
for o,m in zip(O,[0x482092490482,0xd9cdff3b76cd,0x9bef5f3d978f])];n>>=4
print"\n".join(O)

答案 13 :(得分:2)

C ++,286字节

呵呵,每个人都想出了一种更简洁的方式来表示数据。

无论如何,这样就不会完全浪费时间(从命令行输入):

#include<cstdio>
#define P(x)putchar(x);
int main(int,char**v){int i,j,d[]={0,6947821,0,7209841,7734140,1180575,8257861,
3933037,1442811};char*p,c[]="|_|";for(++v;*v;++v){for(i=0;i<9;i+=3){for(p=*v;*p;
++p){for(j=0;j<3;++j)P(1<<((*p>96?*p-32:*p)-48)&d[i+j]?c[j]:32)P(32)}P(10)}P(10)
}}

并且没有混淆:

#include <cstdio>

void out(const char* s)
{
    int i, j;
    const char* c = "|_|";
    unsigned d[9] = {0, 6947821, 0, 7209841, 7734140, 1180575, 8257861, 3933037, 1442811};
    for (i = 0; i < 9; i += 3) {
        for (const char* p = s; *p; ++p) {
            for (j = 0; j != 3; ++j)
                putchar(1 << ((*p > 96 ? *p - 32 : *p) - '0') & d[j + i] ? c[j] : ' ');
            putchar(' ');
        }
        putchar('\n');
    }
}

int main(int, char** argv)
{
    for (++argv;*argv;) {
        out(*argv++);
        putchar('\n');
    }
}

幻数指的是哪个字符有_或_ |在特定的位置。例如,如果0,3,5和'A'都有|某处,数字为1 << n('0') | 1 << n('3') | 1 << n('5') | 1 << n('A') - 其中n(x)表示x - '0'。这假定至少32位整数,因为ASCII图表中'9''A'之间存在小的差距。

最近编辑了两个代码:使用一维数组而不是二维(d),使用非错误证明“toupper”而不是包含cctype,将所有内容移动到main,另一种循环方式over命令行参数,更多精简变量声明,魔术值而不是char常量以及一些其他微小变化。

答案 14 :(得分:2)

Java 1.5 - 删除了不必要的空格的272个字符

比早期版本短得多,使用了JRL的一些想法。可以通过使用命令行参数缩短,但这违反了规范。

class D{public static void main(String[]a){char[]q=new java.util.Scanner
(System.in).nextLine().toCharArray();int j=0,k;for(;j<9;j+=3){for(int c:
q){for(k=j;k<j+3;k++){System.out.print(("{H=mNgwI\177o_v3|7\027".charAt(
"0123456789abcdef".indexOf(c|32))&"\0\1\0\2\4\10\20 @".charAt(k))>0?
" _ |_||_|".charAt(k):32);}}System.out.println();}}}

答案 15 :(得分:1)

答案 16 :(得分:1)

dc - 172 chars

有点晚但是dc条目,差不多符合规范:它只接受大写数字,即[0-9A-F],并且可能在开头打印额外的0。无论如何,这是:

16iD9B4FE55FFBDFFA5BF5BAB774977sK
[   ][ _ ][  |][ _|][|  ][|_ ][| |][|_|]8[1-ds_:al_d0<L]dsLx
?dsNZdsZ
40sr[[1-dlNr10r^/10%80r^lKr/80%lr/8%;aPd0<L]dsLxAP]dsAx
lZ8srlAxlZ1srlAx

一点解释(不需要换行符):

常数0xD9B4FE55FFBDFFA5BF5BAB774977对7位中的每个数字进行编码,例如数字'4'编码为0 111 010,意味着使用字符串'0'表示顶部(''),字符串7表示中间('|_|')和字符串2表示底部('|')。

第二行定义字符串并将它们存储在数组'a'

第三行处理输入并检查数字的长度。

第四行进行计算。它创建了“子程序”A并为第一行执行它。子例程提取相应的数字(1-dlNr10r^/10),然后提取7位编码数据(80r^lKr/80%),然后获取特定行(lr/8%)的相应部分加载字符串和打印它(;aP)然后它遍历所有数字(d0<L

最后一行对显示的第2行和第3行也是如此。

答案 17 :(得分:1)

Windows PowerShell,157

$i=[char[]]"$input"
'☺ ☺☺ ☺☺☺☺☺☺ ☺ ☺☺','♠☻♥♥♦♣♣☻♦♦♦♣•♥♣♣','♦☻♣♥☻♥♦☻♦♥♠♦♣♦♣•'|%{$c=$_
""+($i|%{('···0·_·0··|0·_|0|_|0|_·0|·|0|··'-split0)[$c[("0x$_"|iex)]]})}

答案 18 :(得分:1)

Haskell,259个字符。

Haskell对高尔夫不利还是我(我的第一次打高尔夫球)?

import Char
i=iterate
d b=map(`mod`b).i(`div`b)
z _ 0=' '
z a 1=a
r=take 3
main=
  getLine>>=
  putStr.unlines.foldl1(zipWith(++)).
  map(r.map r.i(drop 3).take 9.zipWith z(cycle"|_|").(0:).d 2.
    (d 256(0xddfd91edcd9cd97990f5*2^384+0x2d6df865ecbd*(2^520+2^776))!!).ord)

(为了便于阅读,将主要分为行)

答案 19 :(得分:1)

包装后的Javascript 333个字符

s=" ";
function r(p)
{
if(t[p]=="0")
return s;
return "_|_||_|".split("")[p];
}
function g(w){
a="";b=a;c=a;
z=[];
for(x=0;x<w.length;x++){
t=("000"+parseInt("6F095E5B397377497F7B7D37661F7674".substr(parseInt(w.substr(x,1),16)*2,2),16).toString(2)).slice(-7).split("");
a+=s+r(0)+s+s;
b+=r(1)+r(2)+r(3)+s;
c+=r(4)+r(5)+r(6)+s;
}
return a+"\n"+b+"\n"+c;
}

alert(g("0123456789deadbeef"));

答案 20 :(得分:1)

C# - 576个字符(没有换行符)

这可能是一种更好的方法,但这是我的解决方案:

using C=System.Console;class Z{static void Main(){new Z();}int L=0;Z(){
try{var s=C.ReadLine().ToUpper();C.Clear();foreach(var c in s){int n=(
int)c;var p=(n==48?"_ ;| |;|_|":n==49?";  |;  |":n==50?"_; _|;|_":n==51
?"_; _|; _|":n==52?";|_|;  |":n==53?"_;|_; _|":n==54?"_;|_;|_|":n==55?
"_;  |;  |":n==56?"_;|_|;|_|":n==57?"_;|_|; _|":n==65?"_;|_|;| |":n==66
?";|_;|_|":n==67?"_;|;|_":n==68?"; _|;|_|":n==69?"_;|_;|_":n==70?"_;|_;|"
:";;").Split(';');P(0);C.Write(" "+p[0]);P(1);C.Write(p[1]);P(2);C.Write
(p[2]);L+=4;}C.WriteLine();}catch{}}void P(int t){C.SetCursorPosition(L,t);}}

答案 21 :(得分:1)

我的不是很短,但这很有趣:

~ dlamblin$ ./7seg 31337aAbcdeF
 _     _  _  _  _  _     _     _  _ 
 _|  | _| _|  ||_||_||_ |   _||_ |_ 
 _|  | _| _|  || || ||_||_ |_||_ |  

#include <stdio.h>
#define P(x) fputs(x,stdout)
#define Z "\33[3D\33[B"
#define a "   " Z
#define s " _ " Z
#define d "  |" Z
#define f " _|" Z
#define g "|  " Z
#define h "| |" Z
#define j "|_ " Z
#define k "|_|" Z
int main(int argc, char** argv){
char m=0,n,*b[]={s h k,a d d,s f j,s f f,a k d,s j f,s j k,s d d,s k k,s k d,
"","","","","","","",
s k h,a j k,s g j,a f k,s j j,s j g};
P("\n\n\n\33[3A");
while (argc>1&&0!=(n=argv[1][m++])){
P(b[n>96?n-80:n-48]);P("\33[3A\33[3C");
}
P("\n\n\n");
}

你可以通过删除一些新行来保存几个字符,但我不在乎。 这是500个字符,如果你拿出换行符argc>1&&

,则为482个字符

需要VT100转义码支持,并且80列终端上的输出不会超过26个字符。

PS我希望看到更多人展示他们的输出。

答案 22 :(得分:0)

PHP,232 characacters

$d=str_split('    _ | ||_ |_| _|  ||  124066153155046135134166144145142034173054133137',3);
foreach(str_split(strtolower($s))as$c){
    $c=hexdec($c)+8;$r[0].=$d[$d[$c][0]];$r[1].=$d[$d[$c][1]];$r[2].=$d[$d[$c][2]];i
}
echo implode("\n",$r);

解释

# Array containing possible lines
$d=array(
    0 => '   ',
    1 => ' _ ',
    2 => '| |',
    3 => '|_ ',
    4 => '|_|',
    5 => ' _|',
    6 => '  |',
    7 => '|  '
);

# Array mapping characters to 3 lines
$m=array(
    0 => '124', # i.e. The character '0' is represented by $d[1], $d[2] and $d[4]
    1 => '066',
    2 => '153',
    3 => '155',
    4 => '046',
    5 => '135',
    6 => '134',
    7 => '166',
    8 => '144',
    9 => '145',
    a => '142',
    b => '034',
    c => '173',
    d => '054',
    e => '133',
    f => '137',
);

# traverse $s and append to array $r
foreach (str_split(strtolower($s)) as $c) {
    $r[0].=$d[$m[$c][0]];
    $r[1].=$d[$m[$c][1]];
    $r[2].=$d[$m[$c][2]];
}

# echo $r
echo implode("\n",$r);

优化:

  • 使用str_split()
  • 动态生成数组
  • 两个阵列都加入了一个
  • 使用hexdec()
  • 以数字方式映射字符

答案 23 :(得分:0)

Python one-liner(322个字符)

print(lambda l:(lambda s:'\n'.join([' '.join(x) for x in zip(*[l[c].split('\n')
for c in s])])))(dict(zip('0123456789abcdef', 'eJxdjrEBwDAIw3au0Ac9iUd0fJM2DTQD'
'g5ExJgkxTOMKYIzPDDUYORlNsZ3zppwuXsqt/pmmjVmZ\nH6M+9BTXZvU8Umg9fd03SOgvPw=='
.decode('base64').decode('zlib').split('\n/\n'))))(__import__('sys').argv[-1]
.lower())

由于我很懒,并且使用zlib和base64内置函数来查找表,因此大部分长度。从命令行运行它,如下所示:

$ python golf.py fedcba9876543210

答案 24 :(得分:0)

使用-Wall编译并且可以理解;不是很短(约400个字符)。在一个严肃的实现中,我将char-&gt;索引从输出部分中拉出来(并将索引存储在缓冲区而不是字符中)。全局r初始化为0,如果它是主要的本地则不会。

#include <stdio.h>
typedef char const* R;
R _=" _ ",S="   ",I="  |",J=" _|",L="|_ ",U="|_|",N="| |",C="|  ";
R s[][16]={
    {_,S,_,_,S,_,_,_,_,_,_,S,_,S,_,_},
    {N,I,J,J,U,L,L,I,U,U,U,L,C,J,L,L},
    {U,I,L,J,I,J,U,I,U,J,N,U,L,U,L,C}};
int r,c,i;
int main(){
    char b[999];
    scanf("%s",b);
    for(;r<3;++r)
        for(c=0;;) {
            i=b[c++]-'0';
            if (i>16) i-=7;
            if (i>15) i-=32;
            if (i<0||i>15){putchar('\n');break;}
            printf("%s",s[r][i]);
        }
    return 0;
}

答案 25 :(得分:0)

JavaScript, 309 304字节。

要求没有原型函数添加到String / Array。

function d(b){r="";o='î$º¶tÖÞ¤þöü^Ê>ÚØ'.split("");p=b.split(r);a=[" 0 ",
"132","465"];c="036";for(k in a){for(var e in p)for(var f in a[k])r+=(U=
a[k][f])==" "?" ":(y=((Q=o[parseInt(p[e],16)].charCodeAt().toString(2))
.length==6?"00"+Q:Q.length==7?0+Q:Q)[U])==0?" ":c.indexOf(U)>-1?"_":"|";
r+="\n"}return r}

测试用例(由于第一个"标记字符串而格式化:

d("0123456789abcdef");

" _     _  _     _  _  _  _  _  _     _     _  _ 
| |  | _| _||_||_ |_   ||_||_||_||_ |   _||_ |_ 
|_|  ||_  _|  | _||_|  ||_| _|| ||_||_ |_||_ |  "