代码高尔夫:七段
挑战
按字符计数的最短代码生成给定hex数的七段显示表示。
input
input只能由数字[0-9]和hex字符组成,只有大写和小写[a-fA-F]。 没有必要处理特殊情况。
产量
输出将是input的七段表示,使用这些ASCII面:
_ _ _ _ _ _ _ _ _ _ _ _ | | | _| _| |_| |_ |_ | |_| |_| |_| |_ | _| |_ |_ |_| | |_ _| | _| |_| | |_| _| | | |_| |_ |_| |_ |
限制
禁止使用以下内容:eval,exec,system,figlet,toilet和external libraries。
testing用例:
Input: deadbeef Output: _ _ _ _ _ _||_ |_| _||_ |_ |_ |_ |_||_ | ||_||_||_ |_ | Input: 4F790D59 Output: _ _ _ _ _ _ |_||_ ||_|| | _||_ |_| || | _||_||_| _| _|
代码计数包括input/输出(即完整程序)。
Perl,134个字符
所有linebreaks可能被删除。
@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未使用)。 值被存储在string中,因此有更多的可打印字符。 ~
运算符翻转位,解压缩给我的数字(perl的按位运算符是非常笨拙的,当涉及到string)。
有了这些数据,我就可以读取input,并循环三次; 三个循环之间的唯一区别是所需的位掩码。 对于input的每个字符,打印输出的三个字符。 要打印的字符是
$s[ hex $& ] & (1 << ($_ + $s) ) ? ($_ % 2 ? "_" : "|" ) : " "
其中@s
是查找表, $s
是取决于行的转换,而$_
是我们是否在行中打印第1,第2或第3个字符。 如果查找表项中的正确位是假,则打印一个空格; 否则会打印一个“|” 或者中间是“_”。
C89(181个字符;参数)
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-ra*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-ra*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), ie 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-ra*3:r-1?7:6); /* Print the segment, mapping position to the bit. */ }
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几个调整!
x86(146字节;参数)
受乔纳斯·古勒 ( Jonas Gulle)的启发,在代码高尔夫(Code Golf)的浪潮中: 通常我会写一个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
男人…不能打败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
。 写在hex,这是0xb4b61fa637bdbbbf89b7b3399b9e09af
,比0xb4b61fa637bdbbbf89b7b3399b9e09af
进制列表短90个字符。 要使用它,当然你必须重写代码。 看起来像
def code_a_8(i): return [255&a_8>>int(x,16)*8 for x in i]
b
可以连接, ''.join(b)
是26个字符,包括引号。 查找function也必须改变以支持这一点。
def lookup_b_cat(d, l): return b_cat[(7&(d>>6-l*3))*3:][:3]
接下来,我只是通过将函数和常量折叠到expression式中来消除所有不需要的语法,这就是它。
也可以稍微收紧打印。 不要join线路,只需立即打印即可。 这会导致修改后的fmt()
:
def fmt_print(i): [print(''.join(lookup(d,l) for d in code(i))) for l in [0,1,2]]
那么,很难打败像Perl这样的专门语言。 不过,这里是160字节的Python版本:
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_))
Golfscript – 116个字符
$ echo -n deadbeef | ./golfscript.rb led.gs _ _ _ _ _ _||_ |_| _||_ |_ |_ |_ |_||_ | ||_||_||_ |_ |
确保在最后保存时没有多余的换行符,否则input的string将被打印在最后。
{32:^|}%: {^' _':$@'14bd'{?~!=}:&~^}%n {:x' |':|\'1237d'&$x'017c'&|x'56bcef'&}%n {:x|\'134579'&$x'147af'&|x'2cef'&}%
怎么运行的
请注意,范围0-F中打开的分段数多于closures分段数。 列出每个分段的例外情况(分段closures的数字)。
#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)
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);}
这将inputstring作为命令行参数。 转换为使用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);}
标准input版本最多可以接受98个input字符。 当然,超过floor(terminalWidth / 3)
会造成混乱的换行。
每个字符的输出被视为一个3×3网格,其中每一行中的单元格都是段。 段是“开”还是“关”。 如果某个细分受众群处于“开”状态,那么'|'
或输出'_'
,具体取决于位置。 如果closures,则输出空间。 字符数组是一个确定每个段是打开还是closures的位数组。 更多关于后面的代码:
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. */ }
字符数组描述字符网格。 数组中的每个字符都描述两个input字符的输出网格的一个水平行。 网格中的每个单元格都由一位表示,其中1
表示该段位于“开”(因此根据位置输出'|'
或'_'
), 0
表示该段位于“closures”。
数组中需要三个字符来描述两个input字符的整个网格。 数组中每个字符的最低三位(位0-2)描述了两行的偶数input字符的一行。 接下来的三位(位3-5)描述了两行中奇数input字符的一行。 位6和位7未使用。 这种排列方式,偏移量为+33,允许arrays中的每个字符都是可打印的,没有转义码或非ASCII字符。
我玩了几个不同的编码,包括把input字符的所有7个段的位都放到一个字符中,但是发现这个是最短的。 虽然这个scheme在数组中需要24个字符来表示只有16个input字符的分段,但是其他的编码要么使用非ASCII字符(当我在我的摩尔斯电码高尔夫球回答中使用这个时不会出现问题),许多转义码和/或复杂的解码代码。 该scheme的解码代码非常简单,尽pipe它充分利用C的运算符优先级来避免添加任何括号。
让我们把它分解成很小的步骤来理解它。
"##3#3133X=W.<X/`^_G0?:0@"
这是编码数组。 让我们抓住适当的字符解码。
[i*8
前8个字符描述了最上面的一行,后面的8个描述了中间的一行,最后8个描述了最后一行。
+c/2]
请记住,此时,c包含一个从0到15的值,对应于ABCDEF0123456789的input,并且该数组对每个编码字符编码两个input字符。 因此,数组中的第一个字符'#'
包含“A”和“B”的第一行的位,第二个字符也是'#'
,编码“C”和“D” , 等等。
-33
编码的结果是几个值在32以下,这将需要转义码。 该偏移将每个编码字符都带入可打印,非转义字符的范围内。
>>
右移运算符的优先级低于算术运算符,所以在减去偏移量之后,这个移位对字符完成。
c%2*3
对于偶数, c%2
计算为零,而对于奇数, c%2
计算为零,所以我们将奇数字符右移3位,得到3-5位,而不是完全移位偶数字符,提供位0-2。 虽然我宁愿使用c&1
进行偶数/奇数检查,而这正是我在其他地方使用的情况,但是&
运算符的优先级太低,无法添加括号。 %
运算符只有正确的优先权。
+j
移位另外的j
位以获得当前输出位置的正确位。
&1
按位和运算符比算术运算符和移位运算符的优先级低,所以这将testing在移位将相关位带入位0 之后是否设置位0。
?
如果位零被设置…
"|_"
…输出这些字符中的一个,由…select
[j&1]
…我们的水平循环variables是偶数还是奇数。
:32
否则(位0未设置),输出32(空格字符)。
如果有的话,我不认为我可以减less更多,当然也不足以击败霍布斯的进入 。
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
我的第一个代码高尔夫 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-jn) & d[ord(c)-(ord('0') if c.isdigit() else ord('a')+6)]: w(s) else: w(' '*len(s)) j += n+1 w('\n')
BrainF ***, 920 906 885 868 863 860 858 chars for digital clock
我开始在(现在closures的)数字时钟代码高尔夫上,所以:也支持。 待办事项:处理小写。
-[>+<-----]->----[>,]<[<]>>[[->]<+[-<+]->]<+>-[>]+++[[<]>>[[>]>[>]+[<]<[<]+[>]>[ >]+[-<+]->[[>]>[>]<+[<]<[<]>+[>]+[-<+]->-]->]<[<]>+[-[>]+[-<+]+<[<]>[[>]+[-<+]-> +<[<]>-]>+]+[-->]+[->]-[>-<-----]>+++>-->->----<<<[>>+++>+++++>-[+++<]>]-<+[>]-[ <]>>>+[-<<+[->+]<<-[-[++>->>[>]>>+++++>>+++++>>>>>+++++>>>+++++++>>>>>>+++++>>>+ ++++>>+[<+]<[<]<]>[-<++>>>[>]<--->+>+>->++++++>+>-->>>>>>>+++>-->-->>+>+>-->->-> >+++++>+[<++++]<[<]]<]>[-<+>>>[>]<--->++++++>+>-->+>-->+++++>>>>>>>+++>->-->>--> ->>->+>>-->+[<++++]<[<]]<+>-[[>]>[>]<[-]<[<]<[<]>-]>[>]>[>]+<-[-[-[-[-[-[-[-[-[[ <]<<.>...>>[>]<-]>[<+[<]<<.>.<.>.>>[>]<->]<]>[<+[<]<..>>[>]<->]<]>[<+[<]<<<<.>>> .>>[>]<->]<]>[<+[<]<....>>[>]<->]<]>[<+[<]<<.<.>>..>>[>]<->]<]>[<+[<]<..<.>.>>[> ]<->]<]>[<+[<]<.<<.>.>.>>[>]<->]<]>[<+[<]<<.<.>.>.>>[>]<->]<]>[<+[<]<.<<.>>..>>[ >]<->]<<[[-]<]-[<]>>>+]++++++++++.[>]<[[-]<]+[-<+]-[>]<-] $ echo 01:23456789DEADBEEF | beef clock.b _ _ _ _ _ _ _ _ _ _ _ _ _ | | | . _| _| |_| |_ |_ | |_| |_| _| |_ |_| _| |_ |_ |_ |_ |_| | . |_ _| | _| |_| | |_| _| |_| |_ | | |_| |_| |_ |_ |
这在很大程度上取决于8位的平台。
Python共188个字符
我没有看太多的其他解决scheme,但我相信还有很大的改进空间。
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)
F#,294个字符
我没有做任何聪明的事情,但仍然得到一个可敬的分数。
let rec G s=for r in[" _ _ _ _ _ _ _ _ _ _ _ _ ";"| | | _| _||_||_ |_ ||_||_||_||_ | _||_ |_ ";"|_| ||_ _| | _||_| ||_| _|| ||_||_ |_||_ | "]do Seq.iter(printf"%s"<<S r)s;printfn"" and S ah=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 ah= a.Substring(3*(int h - if h<'A' then 48 elif h<'a' then 55 else 87),3)
样品:
G("abcdefFEDCBA9876543210")
输出:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |_||_ | _||_ |_ |_ |_ _|| |_ |_||_||_| ||_ |_ |_| _| _| || | | ||_||_ |_||_ | | |_ |_||_ |_|| | _||_| ||_| _| | _||_ ||_|
C ++,286字节
呵呵,每个人都拿出一个更简洁的方式来表示数据。
无论如何,这不是完全浪费时间(从命令行input):
#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'); } }
幻数是指哪些字符有_或a | 在一个特定的位置。 例如,如果0,3,5和'A'都有| | 在某个地方,这个数字是1 << n('0') | 1 << n('3') | 1 << n('5') | 1 << n('A')
1 << n('0') | 1 << n('3') | 1 << n('5') | 1 << n('A')
1 << n('0') | 1 << n('3') | 1 << n('5') | 1 << n('A')
– 其中n(x)
表示x - '0'
。 这个假设至less是32位整数,因为ASCII图表中的'9'
和'A'
之间有一个小的差距。
这两个代码最近被编辑:使用一维数组而不是二维(d),拥有非错误certificate的“ toupper
”,而不是包括cctype,将所有东西都移到main中,另一种循环通过命令行参数的方式,更精简variables声明,魔术值而不是字符常量和其他一些小的变化。
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();}}}
我并不矮,但这样做很有趣:
~ 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[]={shk,add,sfj,sff,akd,sjf,sjk,sdd,skk,skd, "","","","","","","", skh,ajk,sgj,afk,sjj,sjg}; 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个字符,或482,如果你拿出换行符和argc>1&&
需要VT100转义码支持,并且在80列terminal上不会输出超过26个字符的输出。
PS我想看到更多的人显示他们的输出。
C# – 576个字符(没有linebreaks)
可能有更好的方法来做到这一点,但这是我的解决scheme:
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);}}
Haskell, 259 chars.
Is Haskell bad for golf or is it me (my first golf)?
import Char i=iterate db=map(`mod`b).i(`div`b) z _ 0=' ' za 1=a r=take 3 main= getLine>>= putStr.unlines.foldl1(zipWith(++)). map(r.map ri(drop 3).take 9.zipWith z(cycle"|_|").(0:).d 2. (d 256(0xddfd91edcd9cd97990f5*2^384+0x2d6df865ecbd*(2^520+2^776))!!).ord)
(split main to lines for readability)
Javascript 333 Characters When Packed
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"));
dc – 172 chars
A bit late but a dc
entry, almost to spec: it does only accept uppercase numbers, ie [0-9A-F] and may print extra 0s at the beginning. Anyway, here it is:
16iD9B4FE55FFBDFFA5BF5BAB774977sK [ ][ _ ][ |][ _|][| ][|_ ][| |][|_|]8[1-ds_:al_d0<L]dsLx ?dsNZdsZ 40sr[[1-dlNr10r^/10%80r^lKr/80%lr/8%;aPd0<L]dsLxAP]dsAx lZ8srlAxlZ1srlAx
A little explanation (line breaks are not required):
The constant 0xD9B4FE55FFBDFFA5BF5BAB774977 encodes each digit in 7 bit, eg the number '4' is encoded as 0 111 010, meaning use the string '0' for the top (' '), string 7 for the middle ('
|_|
') and string 2 for the bottom (' |
').
The second line defines the strings and stores them in array 'a'
The third lines handles the input and checks how long the number is.
The fourth line does the computation. It created the "subroutine" A and execute it for the first line. The subroutine extracts the appropriate digit ( 1-dlNr10r^/10
), then extracts the 7-bit encoding data ( 80r^lKr/80%
), then takes the appropriate part for the specific line ( lr/8%
) loads the string and prints it ( ;aP
) then it loops over all the digits ( d0<L
)
The last line does the same for lines 2 and 3 of the display.
Scala, 234 bytes
val a=Seq("|_|"," _ "," |","| |"," _|","| ","|_ "," ") val m=argv(0).toLowerCase.map(_-'0').map(i=>if(i<10)i else i-39) for(s<-Seq(0,16,32)) println(m.map(i=>a("171171111117171132440662000654660264240204306065"(i+s)-'0')).mkString)
Code is quite straight-forward: all 9 possible segments are packed into array and mapping between hex number and position. Probably, it could be packed better.
The code to calculate magic numbers:
val s = " _ _ *all numbers in one line here* |_||_ | " val gl = (0 to s.size / 3-1).map(c => s.substring(c*3, c*3+3 )) // gl now contains flat list of string of 3 chars each val arr=gl.toSet.toArray // remove duplicates // for each segment string find corresponding packed index val n = gl.map( arr indexOf _).mkString
as result, n is the magic number, arr is the array of strings
Windows PowerShell, 157
$i=[char[]]"$input" '☺ ☺☺ ☺☺☺☺☺☺ ☺ ☺☺','♠☻♥♥♦♣♣☻♦♦♦♣•♥♣♣','♦☻♣♥☻♥♦☻♦♥♠♦♣♦♣•'|%{$c=$_ ""+($i|%{('···0·_·0··|0·_|0|_|0|_·0|·|0|··'-split0)[$c[("0x$_"|iex)]]})}
Compiles with -Wall and can be understood; not very short (~400 chars). In a serious implementation, I'd pull the char->index out of the output part (and store the indices in a buffer rather than the chars). Global r is initialized to 0, which it wouldn't if it were a local in main.
#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; }
Python one-liner (322 characters)
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())
Most of the length due to me being lazy and using zlib and base64 builtins for the lookup table. Run it from the command line like this:
$ python golf.py fedcba9876543210
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', # ie 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);
优化:
- The arrays are generated dynamically using
str_split()
- Both arrays are joined into one
- Characters are mapped numerically using
hexdec()
JavaScript, 309 304 bytes.
Requires that no prototype functions are added to 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}
Test case (formatting due to first "
marking a String:
d("0123456789abcdef"); " _ _ _ _ _ _ _ _ _ _ _ _ | | | _| _||_||_ |_ ||_||_||_||_ | _||_ |_ |_| ||_ _| | _||_| ||_| _|| ||_||_ |_||_ | "