代码高尔夫 - 横幅生成

36
当感谢某人时,你不仅仅想发送一封“谢谢!”的电子邮件,你需要有更加耀眼夺目的东西:
Input: THANKS!!
Output:
TTT H H AAA N N K K SSS !!! !!! 
 T  H H A A NNN K K S   !!! !!! 
 T  HHH AAA NNN KK  SSS !!! !!! 
 T  H H A A N N K K   S            
 T  H H A A N N K K SSS !!! !!! 

编写一个程序来生成横幅。您只需生成大写A-Z字母以及空格和感叹号(没有感叹号的横幅算什么?)。所有字符都由相同字符的3x5网格组成(因此,S是由S组成的3x5网格)。所有输出应该在一行上(因此没有换行符)。以下是您需要的所有字母:
Input: ABCDEFGHIJKL
Output:
AAA BBB CCC DD  EEE FFF GGG H H III JJJ K K L
A A B B C   D D E   F   G   H H  I    J K K L
AAA BBB C   D D EE  FF  G G HHH  I    J KK  L
A A B B C   D D E   F   G G H H  I  J J K K L
A A BBB CCC DD  EEE F   GGG H H III JJJ K K LLL

Input: MNOPQRSTUVWX
Output:
M M N N OOO PPP QQQ RR  SSS TTT U U V V W W X X
MMM NNN O O P P Q Q R R S    T  U U V V W W  X
M M NNN O O PPP Q Q RR  SSS  T  U U V V WWW  X
M M N N O O P   QQQ R R   S  T  U U V V WWW  X
M M N N OOO P   QQQ R R SSS  T  UUU  V  WWW X X

Input: YZ!
Output:
Y Y ZZZ !!!
Y Y   Z !!!
YYY  Z  !!!
  Y Z
YYY ZZZ !!!

获胜者是 最短的源代码,按照以 utf-8编码 存储文件所需的字节数计算。源代码应从标准输入读取输入,并输出到标准输出。您可以假设输入仅包含 [A-Z! ]。如果您在输入不正确时侮辱用户,则会获得10个字符的折扣=P。
我本来打算要求这些确切的28个字符,但为了使它更有趣,您可以选择您希望它们看起来的方式 - 无论哪种方式都可以使您的代码更短!为了证明您的字母确实像普通字母一样,请展示最后三次运行的输出。
迄今为止,最短的代码(字符数,如果存在非ASCII则为utf8编码):

133 J

205 Python

209 Ruby

313 Haskell

345 C89

382 F#


4
我不明白:“所有输出都应该在一行上”。考虑到每行只有5个字符高度,这怎么可能实现呢? - user319799
4
@doublep: 我想这意味着没有多行横幅。 - back2dos
5
是否应该支持空格? - Marc
5
我们能否禁用 figlet 并通过 UTF-8 计算代码大小? - kennytm
1
http://codegolf.stackexchange.com/ - Marek Grzenkowicz
显示剩余3条评论
14个回答

43

J,133个字符(UTF-8编码)

;/5 3$"1(' ',.s){~"1#:3 u:(ucp'翇篭篯礧歮禧禤祯寭璗牯宭䤧彭忭筯篤筿殭秏璒孯孪寿咕寏犧'){~0>.64-~a.i.s=:

使用方法:

    ;/5 3$"1(' ',.s){~"1#:3 u:(ucp'翇篭篯礧歮禧禤祯寭璗牯宭䤧彭忭筯篤筿殭秏璒孯孪寿咕寏犧'){~0>.64-~a.i.s=:'ABCDEFGHIJKLMNOPQRSTUVWXYZ !'
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│AAA│BBB│CCC│DD │EEE│FFF│GGG│H H│III│JJJ│K K│L  │M M│N N│OOO│PPP│QQQ│RR │SSS│TTT│U U│V V│W W│X X│Y Y│ZZZ│   │!!!│
│A A│B B│C  │D D│E  │F  │G  │H H│ I │  J│K K│L  │MMM│NNN│O O│P P│Q Q│R R│S  │ T │U U│V V│W W│ X │Y Y│  Z│   │!!!│
│AAA│BBB│C  │D D│EE │FF │G G│HHH│ I │  J│KK │L  │M M│NNN│O O│PPP│Q Q│RR │SSS│ T │U U│V V│WWW│ X │YYY│ Z │   │!!!│
│A A│B B│C  │D D│E  │F  │G G│H H│ I │J J│K K│L  │M M│N N│O O│P  │QQQ│R R│  S│ T │U U│V V│WWW│ X │  Y│Z  │   │   │
│A A│BBB│CCC│DD │EEE│F  │GGG│H H│III│JJJ│K K│LLL│M M│N N│OOO│P  │QQQ│R R│SSS│ T │UUU│ V │WWW│X X│YYY│ZZZ│   │!!!│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘

    ;/5 3$"1(' ',.s){~"1#:3 u:(ucp'翇篭篯礧歮禧禤祯寭璗牯宭䤧彭忭筯篤筿殭秏璒孯孪寿咕寏犧'){~0>.64-~a.i.s=:'this is incorrect input.'
|index error

解释(NB.是J语言中的注释):

;/              NB. String together along the third dimension...
5 3$"1          NB. ... reshape each line to 5x3...
(' ',.s)        NB. ... a space before each letter of the input string...
{~"1            NB. ... indexed using...
#:              NB. ... the (15 bit) binary representation of ...
3 u:            NB. ... the integer representation of...
(ucp'翇篭篯礧歮禧禤祯寭璗牯宭䤧彭忭筯篤筿殭秏璒孯孪寿咕寏犧')  ... the unicode versions of these code points...
{~              NB. ...indexed using...
0>.             NB. ...the max of 0 and...
64-~            NB. ...64 less than...
a.i.            NB. the ascii indexes of s
s=:             NB. Assign the input string to the variable s.

11
@M28: 太棒了,这就是精髓。 - sepp2k
4
@M28:增加了解释。基本上,28个Unicode字符中的每一个都是一个15位整数,它是字母的二进制表示。例如,第一个表示字母"A",相当于111101111101101(或31725)。 - David
3
这让我感到头痛,眼睛酸涩,脸颊发热,舌头发麻,还有心痛。但是我依然喜欢它。 - Christian
8
我的防病毒软件抱怨了"篭篯礧歮禧禤祯寭璗牯宭䤧"这一部分。 - Dr. belisarius
16
嗯,好的,这是欺骗——至少涉及代码大小的计算。将文本保存在磁盘上需要多少空间呢? 你必须使用UCS-2格式保存它,占用158字节,或者使用__UTF-8格式,只需约135字节__。我认为在计数时选择utf8是一个很好的标准化方式,在其中每个汉字将占用3个字节。 - Nas Banov
显示剩余12条评论

16

Python, 250 224 chars

s=raw_input()
for i in range(5):
    for c in s:
        print''.join((' ',c)[int('2zj93fqzj6hsh2bc8i2b1ycncj5yc2v9i0m16dz91gcizj18blbw6wt0p3qqh8svchwc5onna2808of',36)>>((ord(c)-65 if c>'@'else 26)*15+i*3+j)&1]for j in[0,1,2]),
    print

注意:

  • 该内容在很大程度上依赖于2.x打印语句;
  • 支持空格。

运行(我仅出于美观原因,稍微改变了一些字母的外观):

$ echo ABCDEFGHIJKL | python code-golf.py
AAA BBB CCC DD  EEE FFF GGG H H III JJJ K K L   
A A B B C   D D E   F   G   H H  I    J K K L   
AAA BBB C   D D EEE FFF G   HHH  I    J KK  L   
A A B B C   D D E   F   G G H H  I  J J K K L   
A A BBB CCC DD  EEE F   GGG H H III JJJ K K LLL 

$ echo MNOPQRSTUVWX | python code-golf.py
M M N N OOO PPP QQQ RR  SSS TTT U U V V W W X X 
MMM NNN O O P P Q Q R R S    T  U U V V W W X X 
M M NNN O O PPP Q Q RR  SSS  T  U U V V WWW  X  
M M N N O O P   QQQ R R   S  T  U U V V WWW X X 
M M N N OOO P   QQQ R R SSS  T  UUU  V  W W X X 

$ echo YZ\! | python code-golf.py
Y Y ZZZ !!! 
Y Y   Z !!! 
YYY  Z  !!! 
  Y Z       
YYY ZZZ !!! 

存在末尾空格。


哦,2个修订版本?看起来 Stack Overflow 把几个短时间内的编辑合并成了一个。 - user319799
@Brian:是的,从第4版开始。 - user319799

9

Figlet (0 chars)

wget -q 3.ly/gzkv;figlet -f b

输出示例:

% wget -q 3.ly/gzkv;figlet -f b ABCDEFGHIJKLMNOPQRS

 A  BB   CC DD  EEE FFF  GG H H III  JJ K K L   M M NNN  O  PP   Q  RR   SS 
A A B B C   D D E   F   G   H H  I    J K K L   MMM N N O O P P Q Q R R S   
AAA BB  C   D D EE  FF  G G HHH  I    J KK  L   MMM N N O O PP  Q Q RR   S  
A A B B C   D D E   F   G G H H  I  J J K K L   M M N N O O P    QQ R R   S 
A A BB   CC DD  EEE F    GG H H III  J  K K LLL M M N N  O  P     Q R R SS 
% wget -q 3.ly/gzkv;figlet -f b TUVWXYZ \!

TTT U U V V W W X X Y Y ZZZ     !!! 
 T  U U V V W W X X Y Y   Z     !!! 
 T  U U V V WWW  X   Y   Z      !!! 
 T  U U V V WWW X X  Y  Z           
 T  UUU  V  W W X X  Y  ZZZ     !!! 

绝对比 Perl 版本好!虽然不算,但我还是点赞了。 - Claudiu
1
当尝试运行“wget -q 3.ly/gzkv;figlet -f b”时,我得到了“-bash: figlet: command not found”的错误提示。 "figlet" 是 Bash 的一部分吗? 我不这么认为... 将“语言”的名称从Bash更改为Figlet - Nas Banov
9
这大约是解决问题的恰当方法,就像声称“wget -q --output-document=- 3.ly/DhWP”可以解决“计算并打印Pi的前10000位数字”的问题一样。;-) - Nas Banov
踩票。这是一个不错的解决方案,但源代码大约有四千字节!这不是制作高尔夫解决方案的方法。 - MiffTheFox

7

Python, 205个字符,极简解决方案

这里提供了可能是最短的Python解决方案:-)
该解决方案仅有两行代码 - 为了可读性,最后一行被分成三段。

s=raw_input()
for i in range(5):print' '.join(''.join((' ',c)[ord(
'W_E__U__QQ_QN_UQ_EA_Q]_D_Q_QYQ__D[_PP_B__F__Q__EG_Y__EZWU]A_A_P_OPO_\\_QNQWT_YUS'
[max(0,3*ord(c)-192-k)])>>i&1]for k in(2,1,0))for c in s)

提示:感谢您的评论,我们已经解决了问题,并且现在仅使用7位ASCII代码!

测试横幅:

TTT H H EEE     QQQ U U III CCC K K     BBB RR  OOO W W N N     FFF OOO X X     JJJ U U M M PPP SSS     OOO V V EEE RR      TTT H H EEE     L   AAA ZZZ Y Y     DD  OOO GGG !!!
 T  H H E       Q Q U U  I  C   K K     B B R R O O W W NNN     F   O O  X        J U U MMM P P S       O O V V E   R R      T  H H E       L   A A   Z Y Y     D D O O G   !!!
 T  HHH EE      Q Q U U  I  C   KK      BBB RR  O O WWW NNN     FF  O O  X        J U U M M PPP SSS     O O V V EE  RR       T  HHH EE      L   AAA  Z  YYY     D D O O G G !!!
 T  H H E       QQQ U U  I  C   K K     B B R R O O WWW N N     F   O O  X      J J U U M M P     S     O O V V E   R R      T  H H E       L   A A Z     Y     D D O O G G    
 T  H H EEE     QQQ UUU III CCC K K     BBB R R OOO WWW N N     F   OOO X X     JJJ UUU M M P   SSS     OOO  V  EEE R R      T  H H EEE     LLL A A ZZZ YYY     DD  OOO GGG !!!

你能指定使用的版本吗?在我的Python 2.6.2安装中无法工作(保存为utf-8)。附注:ÃÂÁ不符合ASCII标准;-) - ChristopheD
@ChristopheD:没错。为了让这个程序在任何地方都能运行,你必须指定一个编码方式,在文件顶部占用一行注释。 - Claudiu
Python 2.6.1的翻译内容为:IndexError: 字符串索引超出范围 - Ponkadoodle
1
@wallacoloo:我已经检查过了,它可以在2.5.2和2.6.5上运行,没有理由认为它不能在其他版本上运行。你提供的字符串是小写字母或数字吗?;-) 只允许使用'A..Z !'。请自行感到受辱:“如果您在输入不正确时侮辱用户,您将获得10个字符的折扣”。 - Nas Banov

4

Haskell, 313 316 320

import Data.Bits
import Data.Char
c&True=c
c&_=' '
a ' '='@'
a '!'='['
a c=c
q s=unlines[s>>= \c->take 3(drop(84*n+3*(ord(a c)-64))$map((c&).testBit(0xffdebaf79f6fbfde7bfe8062f6a979b69b55a4d368ebaf6aeefbe9717add3f8f2ab6a36dbf9b1524d368fedb6fefff69bfdffbff8::Integer))[0..])++" "|n<-[0..4]]
main=getLine>>=putStr.q

对于好奇的人,大数字是以下代码中encoding的十六进制版本。该数字仅用作位图。即使使用非标准字符表示将数字编码为其他基数,我也无法进一步缩短代码。

formats :: [String] -- order: [ A-Z!] <- that's a space in front of A
formats = [
    "   AAABBBCCCDD EEEFFFGGGH HIIIJJJK KL  M MN NOOOPPPQQQRR SSSTTTU UV VW WX XY YZZZ!!!"
  , "   A AB BC  D DE  F  G  H H I   JK KL  MMMNNNO OP PQ QR RS   T U UV VW W X Y Y  Z!!!"
  , "   AAABBBC  D DEE FF G GHHH I   JKK L  M MNNNO OPPPQ QRR SSS T U UV VWWW X YYY Z !!!"
  , "   A AB BC  D DE  F  G GH H I J JK KL  M MN NO OP  QQQR R  S T U UV VWWW X   YZ     "
  , "   A ABBBCCCDD EEEF  GGGH HIIIJJJK KLLLM MN NOOOP  QQQR RSSS T UUU V WWWX XYYYZZZ!!!"
  ]

charToBool :: Char -> Bool
charToBool ' ' = False
charToBool _   = True

boolToInteger :: Bool -> Integer
boolToInteger True = 1
boolToInteger _    = 0

encoding :: Integer
encoding = foldr f 0 $ zip [0..] $ map charToBool $ concat formats
  where
    f (pow, bool) z = z + ((2^pow) * boolToInteger bool)

3

Python 2.6, 251 - 243 - 227个字符

我尝试了一种稍微不同的方法(对字母构成的部分进行位打包)……

  • 可以处理大写字母、空格和感叹号。
  • 这里添加了2个不必要的换行符以提高可读性(for循环可以是一行)。
  • 请务必将其保存为带BOM的UTF-8格式!

像往常一样,欢迎所有评论和建议!这是最短的Python解决方案之一(目前略逊几个字符)……

w=raw_input()
for l in range(5):print''.join("1111 11  11  1   1   "
[int(("%05d"%ord(u"<ϳϲࢬ禉ऐऒ࠾⬃ᅘᖆⰯ囌❿✛іϾь穏ࠂᅜ⭦⭪⫸㡩⬪㰼"
[max(0,ord(c)-64)]))[l])*3:][:3].replace("1",c)+" "for c in w)

啊,这个用于处理 '!' 的 max(-1, .. ) 真聪明 - 我借鉴到我的代码里了! - Nas Banov
输入中包含不支持的字符 :-( - Ponkadoodle
@wallacoloo:就像文本中所述,确保你的编辑器将它保存为utf-8带BOM标头(0xEF,0xBB,0xBF),以指示utf-8编码;某些编辑器可能不支持或会去除这个标头...作为一种替代方案(虽然更繁琐),你可以在文件顶部添加#coding:utf-8 - ChristopheD

2

C89,345个字符

为了您的明智考虑添加换行符(它们不包括在字符计数中,可以/应该被删除):

char o[5][99];
d[]={0x2df7fbef,0x3927bb6b,0x396792cf,0x3da7dbed,0x3a4bfb27,0x2d76f249,0x2dbedbfd,0x3db793ef,0x3fb7daeb,0x3ce7a497,0x3db6ab6d,0x3ff6d495,0x3cf6f2a7,0x38ff8000};
c,i,j;
main(){memset(o,32,495);
while((c=getchar())>0){
for(j=0;j<15;j++)
o[j/3][i+j%3]=d[c-33?(c-65)/2:13]>>((c&1)*15+j)&1?c:32;i+=4;}
for(j=0;j<5;j++)printf("%.*s\n",i,o[j]);}

2

Ruby : 207 215 252 345 characters

i=gets.chomp;5.times{|t|p i.gsub(/./){|c|j=3*(c>?@?c.ord-64:0);(3*t..3*t+2).map{|d|"mini5mbmzjf2bqjmof3prl72i5pn138iuhylmkpi65i278kq3qjfaihyjb66787odp8ktiy5hwt78tmnb"[j..j+2].to_i(36)[d]==1?c:" "}.join+" "}}

1

F#,382个字符

我将每行中的两个字母压缩成一个ASCII可打印字节,并特别处理了空格和感叹号。

let s,(!)=stdin.ReadLine(),printf"%s"
for n in 0..4 do
 for c in s do if c=' '||n=3&&c='!'then !"    "elif c='!'then !"!!! "else for x in 0..3 do printf"%c"(if(Array.collect(fun b->let B n=int b&&&n=0 in[|(B 64)||not(B 8);B 32;B 16;true;B 4;B 2;B 1;true|])"wvwuwTUwvwUUWUEDEiTwUUBURQwEfWidWWVrUrrUEDUmTUTuZUr\\WvtuwWUturruw"B).[n*104+(int c-int 'A')*4+x]then ' 'else c)
 !"\n"

以下是示例输入/输出:

HELLO WORLD!!!
H H EEE L   L   OOO     W W OOO RR  L   DD  !!! !!! !!!
H H E   L   L   O O     W W O O R R L   D D !!! !!! !!!
HHH EE  L   L   O O     WWW O O RR  L   D D !!! !!! !!!
H H E   L   L   O O     WWW O O R R L   D D
H H EEE LLL LLL OOO     WWW OOO R R LLL DD  !!! !!! !!!

ABCDEFGHIJKL
AAA BBB CCC DD  EEE FFF GGG H H III JJJ K K L
A A B B C   D D E   F   G   H H  I    J K K L
AAA BBB C   D D EE  FF  G G HHH  I    J KK  L
A A B B C   D D E   F   G G H H  I  J J K K L
A A BBB CCC DD  EEE F   GGG H H III JJJ K K LLL

MNOPQRSTUVWXYZ
M M N N OOO PPP QQQ RR  SSS TTT U U V V W W X X Y Y ZZZ
MMM NNN O O P P Q Q R R S    T  U U V V W W  X  Y Y   Z
M M NNN O O PPP Q Q RR  SSS  T  U U V V WWW  X  YYY  Z
M M N N O O P   QQQ R R   S  T  U U V V WWW  X    Y Z
M M N N OOO P   QQQ R R SSS  T  UUU  V  WWW X X YYY ZZZ

你可以用for something=start to end替换for something in start..end。同时,你也可以省略最后两行的缩进。我不知道如何进一步缩短它而不引起脑动脉瘤。 - cfern

1

Python,340个字符

d=dict((i,[23535,31727,29263,15211,29391,4815,31567,23533,29847,31527,23277,29257,23421,23549,31599,5103,32623,23275,31183,9367,31597,11117,32749,21653,31213,29351][i-65])for i in range(65,91))
d[33]=29183
d[32]=0
s=raw_input()
for l in range(5):
 p=""
 for c in s:
  for n in range(3):
   if d[ord(c)]&2**(3*l+n):p+=c
   else:p+=" "
  p+=" "
 print p

样例输出

>>> 
ABCDEFGHIJKLMNOPQRSTUVWXYZ !
aaa bbb ccc dd  eee fff ggg h h iii jjj k k l   m m n n ooo ppp qqq rr  sss ttt u u v v w w x x y y zzz     !!! 
a a b b c   d d e   f   g   h h  i    j k k l   mmm nnn o o p p q q r r s    t  u u v v w w  x  y y   z     !!! 
aaa bbb c   d d ee  ff  g g hhh  i    j kk  l   m m nnn o o ppp q q rr  sss  t  u u v v www  x  yyy  z      !!! 
a a b b c   d d e   f   g g h h  i  j j k k l   m m n n o o p   qqq r r   s  t  u u v v www  x    y z           
a a bbb ccc dd  eee f   ggg h h iii jjj k k lll m m n n ooo p   qqq r r sss  t  uuu  v  www x x yyy zzz     !!! 
>>> 

虽然不是很出色,但写它还是挺有趣的。

编辑 哎呀,我把输入变成小写了。现在已经修复了,还省了一个字符 :)


1
内部的 if...else 可以被一行代码替换:p+=(" ",c)[d[ord(c)]&2**(3*l+n)>0] - ChristopheD
d[32:34]=0,29183 可以替换 d[33]=29183;d[32]=0 (节省3个字符) - Ponkadoodle
@dwallacoloo d是一个字典,所以我很确定那样行不通(无论如何,IDLE都不同意)。 - Bwmat
@bwamat,是的。我以为它是一个列表 :< - Ponkadoodle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接