代码高尔夫:连接点

你可能还记得小时候的这些绘画,但现在是时候让电脑画出来了(完整的ascii辉煌)。 玩的开心!

描述:

input是多行(以换行符结尾),描述了一个“字段”。 分散在这个领域的“数字”(用空格分开)。 所有的行可以被认为是相同的长度(你可以填充空格到最后)。

  • 数字总是从1开始
  • 他们遵循自然数的顺序:每个“下一个数字”增加1
  • 每个数字在其左侧和右侧被(至less)一个空白包围

任务:

在这些数字之间以自然顺序(1 -> 2 -> 3 -> ...N) (假定N <= 99)绘制具有以下特征的线条

  1. 用“ + ”字符replace一个数字
  2. 对于水平线:使用' - '
  3. 对于垂直线:使用“ |
  4. 向左或向下或向右向上: /
  5. 向左,向上或向右向下: \

重要笔记:

  1. 当绘制types4和5的线条时,可以假定(给定要与坐标x1,y1和x2,y2连接的点)该distance(x1,x2) == distance(y1,y2) 。 或换句话说(就像jball用户所评论的那样):“不水平或垂直alignment的连续元素总是alignment斜线或反斜线的斜率”。

  2. 遵循点的连接顺序是重要的(较新的一行可以打出较旧的行)。

– 样本input1 –

                                   8 

                                   7 6 
                       10 9       

                                        五            

                                      3 4        
                  11 

                    12 13    
           1 2                     

– 样本输出1 –

                                  +                                
                                 / |                                
                                / +  -  +                             
                      + -------- + \                            
                     / \                           
                    / +                          
                   / |                          
                  / +  -  +                          
                 + |                             
                  \ |                             
                   + ------------------------ +                      
          + -------------------------- +        

– 样本input2 –

                         64          
                         63              



                     62 61                             
                1 65                                   
                  66 57 58                               
                2 56 59 45                
                    67 55 46              
              3 44           
                          54 60 47              
                           53 52 49 48              
              4 51 50 43            

            5 42              
                                             41               
            6 23                                 
                           22 25 26 40              
                       20 21 24 34                 
               7 13 12 33                    
                     19 27 32                     
                 14 35               
            8 15                                           
                 16                                         
                                    39                        
                 17 18 28 31 36                  
                9 38                       
                 10 11 29 30 37                       

– 样本输出2 – ( 独angular兽参考 )

                        +        
                       / +      
                      //          
                     //        
                    //           
                   / +  -  +        
               + + \         
               |  + +  -  \ +          
               + \ + \ +         
              / + + \ + \    
             + \ \ |  +       
             |  + + + /           
             |  +  -  + + ------- + /               
             + +  -  + +              
            / \              
           + +               
           |  +                 
           + + /             
            \ + \ + --- + +           
             \ +  -  + + \ / +              
              + +  -  + / \ / + |             
             / |  | + + / + |                 
            / + ||  / / / +            
           + + ||  / // /                
            \ + ||  / // /              
             \ |  ||  / + / /                  
              \ + --- + + + \ +                  
               + |  |  |  + |                 
                +  -  + + --- + +               

优胜者:

最短的解决scheme(通过代码字符数)。 input可以通过标准input读取。

Perl,222 char(211)

Perl, 384 365 276 273 253 225 222 218 211个字符(222比赛结束时)。 换行符仅用于“可读性”,不包含在字符数中。

上次编辑:不再覆盖$" ,直接打印@S

  $_=join'',@S=map{$n=s/$/$"x97/e;(/./g)[0..95],$/}<>; while(/\b$n /){$S[$q=$-[0]]='+';($P,$Q)=sort{$a-$b}$q,$p||$q; for(qw'\98 |97 /96 -1'){/\D/;$S[$P]=$&until($Q-$P)%$'||$Q<=($P+=$')} $n++;$p=$q}s/\d/ /,print for@S 

说明:

 $_=join'',@S=map{$n=s/$/$"x97/e;(/./g)[0..95],$/}<>; 

如果所有的行长度相同(比如说97个字符),这个任务会更容易。 这个语句采用每行input,用96个空格replace行尾字符,然后将前96个字符加一个换行符压入数组@S 。 注意我们也设置$n=1 ,因为1是我们在input中要查找的第一个数字。 join语句从数组@S创build单个string。 使用标量variables$_进行模式匹配比较方便,使用数组@S更新图片更方便。

 while(/\b$n /){ 

在variables$_search数字$n 。 在Perl中评估正则expression式有几个副作用。 一个是将特殊variables$-[0]设置为匹配的string中匹配模式的开始位置。 这给了我们在string$_数字$n的位置以及数组@S

当然,当$n足够高以至于我们在input中找不到它时,循环将会结束。

  $S[$q=$-[0]]='+'; 

$q为string$_数字$n的位置和数组@S ,并在该位置分配字符“+”。

  $ P =($ P || = $ Q)+ $ Q - ($ Q = $ Q> $ P $ Q:$ P 2)
         ($ P,$ Q)=sorting{$ A- $ B} $ P || $ Q,$ Q; 

第一次通过循环,将$p设置为$q 。 在第一次之后, $p将保持$q前一个值(这将参考前一个数字的input中的位置)。 分配$P$Q使得$P = min( $p$q ), $Q = max( $p$q

  for(qw'\98 |97 /96 -1'){ 

通过build设,连续的数字也是

  • 由一条垂直线连接。 由于input被构造成每行有97个字符,这个例子意味着$p-$q可以被97整除。

  • “与斜杠的斜率alignment”,这将使得$p-$q可以被98整除

  • “与斜线的斜率alignment”,这将使得$p-$q除以96

  • 在同一水平线上

该列表的元素编码线段之间可能的位置数,以及编码该段的字符。

  /\D/; 

另一个微不足道的正则expression式评估。 作为一个副作用,它将特殊variables$& ( MATCHvariables)设置为线段字符( \ | /- )和$' ( POSTMATCHvariables)为编码的数字(98 97 96或1)列表元素。

  $S[$P]=$&until($Q-$P)%$'||$Q<=($P+=$') 

此语句绘制两个数字之间的线段。 如果$Q-$P可以被$'整除,那么继续增加$P $'并且分配字符$&$S[$P]直到$P达到$Q 更具体地说,例如如果$Q-$P可以被97整除,那么把$P加97,并设置$S[$P]='|' 。 重复,直到$P>=$Q

  $n++;$p=$q 

准备循环的下一个迭代。 将$n增加到下一个要在input中search的数字,并让$p保存前一个数字的位置。

 s/\d/ /,print for@S 

输出数组,将任何剩余的数字(来自input中的双位数标识符,我们只用'+'覆盖第一个数字)转换为空格。

Commodore 64 BASIC – 313个字符

编辑:请参阅下面的高尔夫版本

沿着与PETgraphics, POKE s和PEEK s和一切的记忆通道一个小小的旅程:)

它适合在一个单一的屏幕:)

该程序直接在屏幕内存中操作,所以您只需继续,清除屏幕,放置点,然后键入RUN

输入

你必须等待一分钟左右,find点,然后开始画。 这不是快 – 你可以看到画的线,但这是最酷的部分:)

产量

高尔夫版本:

Commodore BASIC似乎是打高尔夫球的好语言,因为它不需要空格:)也可以通过input一个未转移的第一个字母,后跟一个移位的第二个字母来缩短大部分命令。 例如, POKE可以键入P [SHIFT + O],在屏幕上显示为P┌

高尔夫版本

MS-DOS批处理 (是的,你阅读正确的!)

我经常听到(或者说)人们说批次不是很强大,你不能和他们做很多事情,对他们来说,我说,看看BATCH的力量!

实际的脚本(script.bat):

 set file=%~1 call :FindNextNum 1 for /F "tokens=2 delims=:" %%i IN ('find /c /V "" "%file%"') DO set /a totalLines=%%i set maxLen=0 for /F "delims=" %%i IN (%file%) DO ( call :CountChars "%%i" if /i !charCount! gtr !maxLen! set maxLen=!charCount! ) for /L %%i IN (0,1,%totalLines%) DO set "final_%%i=" & for /L %%j IN (0,1,%maxLen%) DO set "final_%%i=!final_%%i! " :MainLoop set currLineNum=%lineNum% set currCol=%linePos% set currNum=%nextNum% set /a targetNum=%currNum%+1 call :FindNextNum %targetNum% if "%nextNum%"=="" goto MainEnd REM echo %currNum% -^> %nextNum% if /I %currLineNum% lss %lineNum% ( call :DrawLine %currCol% %currLineNum% %linePos% %lineNum% ) else ( call :DrawLine %linePos% %lineNum% %currCol% %currLineNum% ) goto MainLoop :MainEnd for /L %%i IN (0,1,%totalLines%) DO echo.!final_%%i! goto:eof :DrawLine if /I %2 equ %4 goto:DrawHoriz set "char=" & set "pos=%1" & set "inc=0" if /I %1 LSS %3 set "char=\" & set "pos=%1" & set "inc=1" if /I %1 GTR %3 set "char=/" & set "pos=%1" & set "inc=-1" for /L %%i IN (%2,1,%4) DO call :DrawChar %%i !pos! %char% & set /a "pos+=%inc%" goto:DrawEnds :DrawHoriz set "start=%1+1" & set "end=%3" if /I %start% gtr %end% set "start=%3+1" & set "end=%1" set /a lineEnd=%end%+1 set lineEnd=!final_%2:~%lineEnd%! for /L %%i IN (%start%,1,%end%) DO set final_%2=!final_%2:~0,%%i!- set final_%2=!final_%2!!lineEnd! :DrawEnds call :DrawChar %2 %1 + call :DrawChar %4 %3 + goto:eof :DrawChar set /a skip2=%2+1 if "%3"=="" ( set final_%1=!final_%1:~0,%2!^|!final_%1:~%skip2%! ) else ( set final_%1=!final_%1:~0,%2!%3!final_%1:~%skip2%! ) goto:eof :CountChars set charCount=0 set val=%~1 :CountChars_loop if not "%val:~1%"=="" ( set /a charCount+=1 set val=!val:~1! goto CountChars_loop ) goto:eof :FindNextNum for /F "delims=" %%i IN ('type "%file%" ^| find /V /N ""') DO ( for /F "tokens=1,2 delims=[]" %%j IN ("%%i") DO ( set /a lineNum=%%j-1 call :FindNext_internal "%%k" %1 if /I !nextNum! equ %1 goto :eof ) ) goto:eof :FindNext_internal set currLine=%~1 set linePos=0 :FindNext_internal_loop call :NextNumInLine "%currLine%" set /a linePos+=%spaceInterval% if "%nextNum%"=="" goto :EOF if /I %nextNum% equ %2 goto :EOF set /a spaceInterval+=1 set /a linePos+=1 if /I %nextNum% GTR 9 set /a "spaceInterval+=1" & set /a linePos+=1 set currLine=!currLine:~%spaceInterval%! goto FindNext_internal_loop :NextNumInLine set nextNum= for /F %%i IN (%1) DO set /a nextNum=%%i if "%nextNum%"=="" goto :eof set /a spaceInterval=0 set val=%~1 :NextNumInLine_loop if "%val:~0,1%"==" " ( set /a spaceInterval+=1 set val=!val:~1! goto NextNumInLine_loop ) goto :eof 

这就是你如何称呼它

 echo off setlocal ENABLEDELAYEDEXPANSION call script.bat input.txt 

其中“input.txt”是一个包含“程序”input的文件。

PS这实际上并没有针对线路长度进行优化,但是我已经花了几个小时到达这一点,现在我需要睡觉…我会看看我明天是否可以改进它(目前'script.bat位于2755字节)

雷布姆 :218个字符

Ma L{-|\/}Qb|[sg?SBaB]Da|[feSm[TfiSrj[spAsp]iT[++Tbr]]t]Xa|[i?A]Ya|[i?FImHDa]Ca|[skPCmSCaBKfsA]wh[Jd++N][roG[xJyJ]]Bf+GwhB[JcB Ff+GiF[KcF HqXkXj VqYkYju[chCbPClEZv1[ezH2[eeHv3 4]]e?A+bRE[hV]f]]chJeFIlSCj{+}{+ }Jk Bf]wM

我非常擅长以拉丁语的forms阅读和编辑它。 (虽然我使用换行符:)):)

但是,当这个不区分大小写的“蠢事”的伎俩被煮熟了,人们就习惯了这个方言,这就是口译如何改变了方言。 我会添加一些评论。 (提示: fi是find, fe是foreach, sp是空格字符, i?是索引, hd是head, ch是change, sk是skip, pc是pick, bk是break, i是if, e也是, ee是平等的,ad nauseum)

 ; copy program argument into variable (m)atrix m: a ; string containing the (l)etters used for walls l: {-|\/} ; q is a "b|function" (function that takes two parameters, a and b) ; it gives you the sign of subtracting b from a (+1, -1, or 0) q: b| [sg? sb ab] ; d finds you the iterator position of the first digit of a two digit ; number in the matrix d: a| [fe sm [t: fi s rj [sp a sp] it [++ t br]] t] ; given an iterator position, this tells you the x coordinate of the cell x: a| [i? a] ; given an iterator position, this tells you the y coordinate of the cell y: a| [i? fi m hd a] ; pass in a coordinate pair to c and it will give you the iterator position ; of that cell c: a| [sk pc m sc a bk fr a] ; n defaults to 1 in Rebmu. we loop through all the numbers up front and ; gather their coordinate pairs into a list called g wh [j: d ++ n] [ro g [xjyj]] ; b is the (b)eginning coordinate pair for our stroke. f+ returns the ; element at G's current position and advances G (f+ = "first+") ; advance g's iteration position b: f+ g wh b [ ; j is the iterator position of the beginning stroke j: cb ; f is the (f)inishing coordinate pair for our stroke f: f+ g ; if there is a finishing pair, we need to draw a line if [ ; k is the iterator position of the end of the stroke k: cf ; the (h)orizontal and (v)ertical offsets we'll step by (-1,0,1) h: qxkxjv: qykyju [ ; change the character at iterator location for b (now our ; current location) based on an index into the letters list ; that we figure out based on whether v is zero, h is zero, ; v equals h, or v doesn't equal h. ch cb pc l ez v 1 [ez h 2 [ee hv 3 4]] ; if we update the coordinate pair by the offset and it ; equals finish, then we're done with the stroke e? a+ b re [hv] f ] ] ; whether we overwrite the number with a + or a plus and space ; depends on whether we detect one of our wall "letters" already ; one step to the right of the iterator position ch je fi l sc j {+} {+ } ; update from finish pair to be new begin pair for next loop iteration j: k b: f ] ; write out m wm 

语言和样本都是新的,处于实验阶段。 例如,在我改变它来帮助这个样本之前, ad不能用来把vector和matrix加在一起。 但是我认为这就是专门为代码高尔夫devise的语言必须具备的东西。 这是“语言”与“图书馆”之间的微妙界限。

有GitHub上的评论的最新来源

哈斯克尔,424个字符

当前字数:424 430 451 466 511 515 516 518 525 532 541 545 550 556 569 571 577 582 586 592

 import List x%c=[(i,c)|i<-x] lkpq|p>q=lkqp|True=head[[p,p+j..q]%c|m<-zip[k-1,k,k+1,1]"/|\\-",let (j,c)=m,mod(qp)j==0] w=map snd q(k,m,x)z=w$sort$nubBy((==)&fst)$x%'+'++(concat$zipWith(lk)x$tail x)++z%'\n'++[1..m]%' ' r(z,m,x)=q(last z,m-1,w$sort x)z u[(m,_)]nx=(-m::Int,n):x;u _ _ x=x t(z,n,x)s|s=="\n"=(n:z,n+1,x)|True=(z,n+length s,u(reads s)nx) y&x=(.x).yx main=interact$r.foldl t([],1,[]).groupBy((&&)&(>' ')) 

这个版本从下面的原始Haskell条目中吸取了很多灵感,但做了一些重大的改变。 最重要的是,它代表具有单个索引的图像位置,而不是一对坐标。

有一些变化:

  1. input现在必须将所有行填充到相同的长度(由规则允许)。
  2. 不再需要任何语言扩展

原始版本:

(需要-XTupleSections ,也许-XNoMonomorphismRestriction

 import List b=length f=map g=reverse a(x,y)" "=(x,y+1) a(x,y)z=([y,read z]:x,y+bz) x%y=[min x y+1..max x y-1] j([x,y],[w,z])|y==z=f(,'-')$f(y,)$x%w|x==w=f(,'|')$f(,x)$y%z|(y<z)==(x<w)=f(,'\\')$zip(y%z)$x%w|True=f(,'/')$zip(y%z)$g$x%w k 0='\n' k _=' ' y&x=(.x).yx y?x=f y.sort.x.concat rz=snd?(nubBy((==)&fst).g)$[((y,x),kx)|x<-[0..maximum$fbd],y<-[1..bd]]:[((y,x),'+')|[x,y]<-e]:(fj$zip e$tail e)where d=f(groupBy$(&&)&(>' '))$lines z;e=tail?fg$zipWith(f.(:))[1..]$f(fst.foldl a([],1))d main=interact r 

说明:

(1) d=... :将input分割为空格和数字,例如

  z = " 6 5\n\n1 2\n\n 4 3\n\n 7" => d = [[" ","6"," "," ","5"],[],["1"," "," "," "," "," "," "," ","2"],[],[" "," "," "," ","4"," "," "," ","3"],[],[" ","7"]] 

(2) e=... :将d转换成每个数字的(y,x)坐标列表。

  e = [[1,3],[9,3],[9,5],[5,5],[5,1],[2,1],[2,7]] --- // 1 2 3 4 5 6 7 

(3)

  • [((y,x),kx)|...]是空板。 ( k根据x坐标返回空格或\n 。)
  • [((y,x),'+'))|...]是数字上的加号。
  • (fj$zip e$tail e)是连接数字的线。 ( j将一对坐标映射成表示线的(坐标,字符)列表)。

这3个组件被连接并过滤以形成实际的输出。 注意顺序很重要,所以nubBy(...).g只能保留最后一个字符在同一个位置。

AWK – 296 317 321 324 334 340

不是获奖者(尚),但我很高兴的努力(显示换行)。 这个新版本使用VT-100转义序列。 '^ ['只是一个字符,逃脱! 使用此版本剪切和粘贴将不起作用 ,因为序列“^ [”必须用真正的ESC字符replace。 为了使论坛友好,ESC可以被指定为“\ 0x1b”,但它占用太多的空间…

 BEGIN{FS="[ ]"}{for(j=i=0;i<NF;j+=length(g)){if(g=$++i){x[g]=k=i+j;y[g]=NR; m=m>k?m:k}}}END{printf"^[[2J[%d;%dH+",Y=y[i=1],X=x[1];while(a=x[++i]) {a-=X;b=y[i]-Y;t=a?b?a*b>0?92:47:45:124;A=a?a>0?1:-1:0;B=b?b>0?1:-1:0; for(r=a?a*A:b*B;--r;){printf"^[[%d;%dH%c",Y+=B,X+=A,t} printf"^[[%d;%dH+",Y+=B,X+=A}} 

较旧的标准版本

 BEGIN{FS="[ ]"}{for(j=i=0;i<NF;j+=length(g)){if(g=$++i){x[g]=k=i+j;y[g]=NR; m=m>k?m:k}}}END{q[X=x[1],Y=y[i=1]]=43;while(a=x[++i]){a-=X;b=y[i]-Y; t=a?b?a*b>0?92:47:45:124;A=a?a>0?1:-1:0;B=b?b>0?1:-1:0;for(r=a?a*A:b*B;--r; q[X+=A,Y+=B]=t);q[X+=A,Y+=B]=43}for(j=0;++j<NR;){for(i=0;i<m;){t=q[i++,j]; printf"%c",t?t:32}print}} 

现在有点解释

 # This will break the input in fields separated by exactly 1 space, # ie the fields will be null or a number. BEGIN{FS="[ ]"} # For each line we loop over all fields, if the field is not null # it is a number, hence store it. # Also account for the fact the numbers use space. # Also, find the maximum width of the line. { for(j=i=0;i<NF;j+=length(g)){ if(g=$++i){ k=j+i;x[g]=k;y[g]=NR;m=m>k?m:k } } } # Once we have all the data, let start cooking. END{ # First, create a matrix with the drawing. # first point is a + q[X=x[1],Y=y[i=1]]=43; # loop over all points while(a=x[++i]){ # Check next point and select character # If a == 0 -> - # If b == 0 -> | # If a and b have same sign -> \ else / a-=X;b=y[i]-Y;t=a?b?a*b>0?92:47:45:124; # there is no sgn() function A=a?a>0?1:-1:0;B=b?b>0?1:-1:0; # Draw the line between the points for(k=0;++k<(a?a*A:b*B);){ q[X+=A,Y+=B]=t } # store + and move to next point q[X+=A,Y+=B]=43 } # Now output all lines. If value in point x,y is 0, emit space for(j=0;++j<NR;){ for(i=0;i<m;){ t=q[i++,j];printf("%c",t?t:32) } print } } 

C,386

C中402 386个字符。第一个之后的Newlines只是为了可读性。

 #include <stdio.h> int x[101],y[101],c=1,r,w,h,b,i,j,k,m,n; int main(){ while((b=getchar())-EOF) b-' '?b-'\n'?ungetc(b,stdin),scanf("%d",&b),x[b]=c++,y[b]=h,c+=b>9:(w=c>w?c:w,++h,c=1):++c; for(r=0;r<h&&putchar('\n');++r) for(c=0;c<w;++c){ for(b=' ',i=2,m=x[1]-c,n=y[1]-r;j=m,k=n,m=x[i]-c,n=y[i]-r,x[i++];) b=j|k&&m|n?j*m>0|k|n?k*n<0?(jk|mn?j+k|m+n?j|m?b:'|':'/':'\\'):b:'-':'+'; putchar(b); } } 

英特尔汇编

组装大小:506字节

来源:2252字节(嘿,这不是一个微不足道的问题)

组装:使用A86运行:使用WinXP DOS框进行testing。 调用jtd.com < input > output

  mov ax,3 int 10h mov ax,0b800h mov es,ax mov ah,0bh int 21h mov bx,255 cmp al,bl mov dh,bh mov si,offset a12 push offset a24 je a1 mov si,offset a14 a1: inc bl a2: mov dl,255 call si cmp al,10 jb a4 a3: cmp al,10-48 jne a1 inc bh mov bl,dh jmp a2 a4: mov dl,al call si cmp al,10 jae a5 mov ah,dl aad mov dl,al a5: mov di,dx mov ch,al shl di,2 mov [di+a32],bx cmp bl,[offset a30] jb a6 mov [offset a30],bl a6: cmp bh,[offset a31] jb a7 mov [offset a31],bh a7: push offset a19 mov al,80 mul bh add al,bl adc ah,0 add ax,ax lea di,[di+2+a32] mov [di],ax add di,2 cmp di,[a22-3] jbe a8 mov [a22-3],di mov [a25-3],di a8: mov di,ax mov al,dl aam cmp ah,0 je a10 a9: add ah,48 mov es:[di],ah add di,2 a10:add al,48 mov es:[di],al mov al,ch inc bl jmp a3 a11:jmp si a12:mov ah,0bh int 21h cmp al,255 jne a15 mov ah,8 int 21h a13:cmp al,13 je a11 sub al,48 ret a14:mov ah,1 int 21h cmp al,26 jne a13 mov si,offset a15 ret a15:cmp dl,255 je a16 mov al,32 ret a16:mov si,offset a32 + 4 lodsw mov cx,ax mov dx,ax lodsw mov di,ax mov b es:[di],1 mov bp,0f000h call a26 add sp,6 mov bx,[a22-3] mov ax,[offset a31] inc ax a17:mov bp,[offset a30] a18:mov b[bx],32 inc bx dec bp jnz a18 mov w[bx],0a0dh add bx,2 dec ax jnz a17 mov b[bx],'$' add w[a30],2 a19:lodsw xchg ax,dx cmp ah,dh lahf mov bl,ah cmp al,dl lahf shr bl,6 shr ah,4 and ah,12 or bl,ah mov bh,0 shl bx,3 a20:mov b es:[di],43 a21:mov al,b[a30] mul ch add al,cl adc ah,0 mov bp,ax mov b[bp+100h],43 a22:add di,[bx + a29] add cl,[bx + a29 + 4] add ch,[bx + a29 + 6] mov b es:[di],1 mov al,[bx + a29 + 2] mov [a21-1],al mov [a22-1],al mov bp,01000h call a26 cmp di,[si] jne a20 mov al,es:[di+2] sub al,48 cmp al,10 jae a23 mov b es:[di+2],0 a23:mov b[a21-1],43 mov b[a22-1],43 mov b es:[di],43 lodsw ret a24:mov al,b[a30] mul ch add al,cl adc ah,0 mov bp,ax mov b[bp+100h],43 a25:mov dx,[a22-3] mov ah,9 int 21h ret a26:pusha a27:mov cx,0ffffh a28:loop a28 dec bp jnz a27 popa ret a29:dw -162,92,-1,-1,-2,45,-1,0,158,47,-1,1,0,0,0,0,-160,124,0,-1 a30:dw 0 a31:dw 0,0,0,160,124,0,1,0,0,0,0,-158,47,1,-1,2,45,1,0,162,92,1,1 a32: 

有趣的function:自我修改代码,animation输出(第二个例子工作,但太大,不能显示),滥用'ret'来实现循环计数器,确定线/移动方向的有趣方式。

F#,725个字符

 open System let mutable h,s,l=0,Set.empty,Console.ReadLine() while l<>null do l.Split([|' '|],StringSplitOptions.RemoveEmptyEntries) |>Seq.iter(fun t->s<-s.Add(int t,h,(" "+l+" ").IndexOf(" "+t+" "))) h<-h+1;l<-Console.ReadLine() let w=Seq.map(fun(k,h,x)->x)s|>Seq.max let o=Array2D.create h (w+1)' ' Seq.sort s|>Seq.pairwise|>Seq.iter(fun((_,b,a),(_,y,x))-> let a,b,x,y=if b>y then x,y,a,b else a,b,x,y o.[b,a]<-'+' o.[y,x]<-'+' if b=y then for x in(min ax)+1..(max ax)-1 do o.[y,x]<-'-' elif a=x then for h in b+1..y-1 do o.[h,x]<-'|' elif a<x then for i in 1..yb-1 do o.[b+i,a+i]<-'\\' else for i in 1..yb-1 do o.[b+i,ai]<-'/') for h in 0..h-1 do for x in 0..w do printf"%c"o.[h,x] printfn"" 

传说:

 h = height s = set l = curLine w = (one less than) width o = output array of chars 

第1-6行:我保留了一组(number,lineNum,xCoord)元组; 正如我在input的每一行中所看到的,我find所有的数字并将它们添加到集合中。

7-8行:然后我创build一个输出字符数组,初始化为所有空格。

第9行:sorting集(按“编号”),然后取每个相邻的对…

第10-16行:…sorting所以(a,b)是两点中的“最高”,(x,y)是另一个点。 把'+'的符号,然后如果水平,绘制,否则如果垂直,绘制,否则绘制正确的对angular线。 如果input不是“有效的”,那么谁知道发生了什么事情(在我把它打高尔夫球之前,这个代码里充满了“断言”)。

第17-19行:打印结果

电源shell, 328 304个字符

 $i=$l=0;$k=@{} $s=@($input|%{[regex]::matches($_,"\d+")|%{$k[1*$_.Value]=@{y=$l x=$_.Index}};$l++;""}) while($a=$k[++$i]){ if($i-eq1){$x=$ax;$y=$ay} do{$d=$axCompareTo($x);$e=$ayCompareTo($y) $s[$y]=$s[($y+=$e)].PadRight($x+1).Remove($x,1).Insert(($x+=$d), "\-/|+|/-\"[4+$d*3+$e])}while($d-or$e)}$s 

这里有一个漂亮的印刷版本:

 # Usage: gc testfile.txt | dots.ps1 $l=$i=0 # line, dot index (used below) $k=@{} # hashtable that maps dot index to coordinates # Apply regular expression to each line of the input $s=@( $input | foreach{ [regex]::matches($_,"\d+") | foreach{ # Store each match in the hashtable $k[ 1*$_.Value ] = @{ y = $l; x = $_.Index } } $l++; # Next line "" # For each line return an empty string. # The strings are added to the array $s which # is used to produce the final output } ) # Connect the dots! while( $a = $k[ ++$i ] ) { if( $i -eq 1 ) # First dot? { # Current position is ($x, $y) $x = $ax; $y = $ay } do { $d = $axCompareTo( $x ) # sign( $ax - $x ) $e = $ayCompareTo( $y ) # sign( $ay - $y ) $c = '\-/|+|/-\'[ 4 + $d * 3 + $e ] # character ' # Move $x += $d $y += $e # "Replace" the charcter at the current position # PadRight() ensures the string is long enough $s[ $y ]=$s[ $y ].PadRight( $x+1 ).Remove( $x, 1 ).Insert( $x, $c ) } while( $d -or $e ) # Until the next dot is reached } # Print the resulting string array $s 

Python – 381

 import re b=list(iter(raw_input,'')) c=sum((zip([i]*999,re.finditer('\\d+',x))for i,x in enumerate(b)),[]) d=sorted((int(m.group()),i,m.start())for i,m in c) e=[[' ']*max(map(len,b))for x in b] for(t,u,v),(x,y,z)in zip(d,d[1:]+d[-1:]): e[u][v]='+' while u!=y or v!=z:i,j=(u<y)-(u>y),(v<z)-(v>z);u+=i;v+=j;e[u][v]=['|','/\\-'[(i==j)+2*(i==0)]][j!=0] print'\n'.join(map(''.join,e)) 

C#,422个字符

758 754 641 627 584 546 532 486 457 454 443 440 422 chars(下次也许我不会那么快提交)

 using A=System.Console;class B{static int C,o,d,e,G,O=1,f,F,u,n;static void Main(){var s=A.In.ReadToEnd();A.Clear();while(++u<s.Length){f++;if (s[u]<32){u++;F++;f= 0;}if(s[u]>32){if(int.Parse(s[u]+""+s[++u])==O){o= e>f?1:f>e?-1:0;C=d>F?1:F>d?-1:0 ;G=e+o;n=d+C;if(O++>1)while(n!=F||G!=f) {A.SetCursorPosition(G-=o,n-=C);A.Write( "+/-|\\"[n==d&&G==e?0:n==F&&G ==f?0:C+o==0?1:C==0?2:o==0?3:4]);}e=f;d=F;F=0;f=u=-1 ;}f++;}}A.Read();}} 

用法:运行,粘贴(或input)input,确保最后一行被终止,按CTRL-Z或F6,按Enter键。

格式化,但仍然基本unintelligable版本:

 using A = System.Console; class B { // code golf fun! static int C, o, d, e, G, O = 1, f, F, u, n; static void Main() { // read the input into a string char by char until EOF var s = A.In.ReadToEnd(); A.Clear(); // clear console, ready to draw picture // O is the "dot" number we're looking for // f is current column // F is current row // loop over the field looking for numbers sequentially // until no more are found while (++u < s.Length) { f++; // any char <32 is expected to be a CR/LF // increment the current row and reset the current column if (s[u] < 32) { u++; // skip the other half of the CR/LF pair F++; // next row f = 0; // column reset } // any char >32 is expected to be a number if (s[u] > 32) { // parse the current + next char and see if it's // the number we want if (int.Parse(s[u] + "" + s[++u]) == O) { // set up coordinates, compare X1 with X2 // and Y1 with Y2 to figure out line direction // horizontal direction (same as o=e.CompareTo(f)) o = e > f ? 1 : f > e ? - 1 : 0; // vertical direction (same as C=d.CompareTo(F)) C = d > F ? 1 : F > d ? - 1 : 0; // initial offsets compensate for off-by-one G = e + o; n = d + C; // draw the line (except for the very first dot) if (O++ > 1) while (n != F || G != f) { // update coords and write desired char A.SetCursorPosition(G -= o, n -= C); // this lovely line decides which char to // print, and prints it A.Write( "+/-|\\"[n == d && G == e ? 0 : n == F && G == f ? 0 : C + o == 0 ? 1 : C == 0 ? 2 : o == 0 ? 3 : 4]); } // remember end point of this line, to use as start point // of next line e = f; d = F; // reset current row (F), column (f), field position (u) F = 0; f = u = -1; } // bump current column because we parse 2 chars when we // find a dot f++; } } A.Read(); // prevent command prompt from overwriting picture } } 

开始!

 #include <stdio.h> #include <stdlib.h> #include <string.h> int sign(int x) { if (x < 0) return -1; if (x > 0) return +1; return 0; } #define MAX_ROWS 100 #define MAX_COLS 100 #define MAX_DIGITS 100 int main(void) { // Read in the digits int number[MAX_DIGITS][2]; int rows = 0; int cols = 0; char row[MAX_COLS]; int maxvalue = 0; int i, j, value, x; for (i = 0; i < MAX_ROWS; i++) { if (row != fgets(row, MAX_COLS, stdin)) break; value = 0; for (j=0; row[j] != 0; j++) { if (row[j] >= '0' && row[j] <= '9') { x = j; value = 0; do { value = 10*value + (row[j]-'0'); j++; } while (row[j] >= '0' && row[j] <= '9'); number[value][0] = i; number[value][1] = x; if (maxvalue < value) maxvalue = value; if (rows < i+1) rows = i+1; if (cols < x+1) cols = x+1; } } } // Create an empty field char field[rows][cols]; memset(field, ' ', rows*cols); char lines[] = "\\|/-+-/|\\"; int dr,dc; // Draw the numbers and lines field[number[1][0]][number[1][1]] = '+'; for (i = 2; i <= maxvalue; ++i) { int r = number[i-1][0]; int c = number[i-1][1]; int rt = number[i][0]; int ct = number[i][1]; dr = sign(rt-r); dc = sign(ct-c); char line = lines[(dr+1)*3+dc+1]; while (r != rt || c != ct) { r += dr; c += dc; field[r][c] = line; } field[r][c] = '+'; } for (i = 0; i < rows; ++i) { for (j = 0; j < cols; ++j) putchar(field[i][j]); putchar('\n'); } return 0; } 

C#, 638 chars

 using System; using System.Linq; using System.Text.RegularExpressions; class C { static void Main() { int i=0,j; var p = Console.In.ReadToEnd() .Split('\n') .SelectMany( r => { i++; j =0; return Regex.Matches(r, "\\s+(\\d+)").Cast<Match>() .Select(m => { j += m.Length; return new { X = j, Y = i-1, N = int.Parse(m.Groups[1].Value) }; }); } ).OrderBy(a=>aN).ToList(); var W = p.Max(a => aX)+1; var k = new char[W*i+W]; i = 0; while (i < p.Count) { var b = p[i > 0 ? i - 1 : 0]; var a = p[i]; int h = aY - bY, w = aX - bX; var s = "|-/\\"[h == 0 ? 1 : w == 0 ? 0 : h / w > 0 ? 3 : 2]; while ((h | w) != 0) { k[bX + w + W * (bY + h)] = s; h -= h.CompareTo(0); w -= w.CompareTo(0); } k[aX + aY * W] = '+'; k[W * ++i] = '\n'; } Console.Write(k); } } 

I cannot do multi-line in a comment, so I will demonstrate here. In the following examples, distance(x1,x2) == distance(y1,y2):

 + |\ +-+ + |\ | \ +--+ + |\ | \ | \ +---+ 

With the rules as explained, distance(x1,x2) == distance(y1,y2)+2:

 +\ | \ +--\+ +\ | \ | \ +---\+ +\ | \ | \ | \ +----\+ 

C++ 637

 #include <iostream> #include <string> #include <vector> #define S(x)((x)<0?-1:x>0?1:0) using namespace std;enum{R=100,C=100,D=100};int main(){string s; int N[D][2],M=0,q=0,p=0,i,j,V,L,a,b;for(i=0;j=0,(i<R)&&getline(cin,s);i++) while((j=s.find_first_not_of(" ",j))<=s.size()){L=sscanf(&s[j],"%d",&V); N[V][0]=i;N[V][1]=j;if(M<V)M=V;if(q<=i)q=i+1;if(p<=j)p=j+1;j+=L+1;} string F(q*p,' '),l="\\|/-+-/|\\";F[p*N[1][0]+N[1][1]]='+';for(i=2;i<=M;++i){ int r=N[i-1][0],c=N[i-1][1],d=N[i][0],e=N[i][1];for(a=S(dr),b=S(ec);r!=d||c!=e;) r+=a,c+=b,F[p*r+c]=l[(a+1)*3+b+1];F[p*r+c]='+';}for(i=0;i<q;i++) cout<<string(&F[i*p],p)+"\n";} 

Indented, and with a few slightly more meaningful names, that looks like:

 #include <iostream> #include <string> #include <vector> #define S(x)((x)<0?-1:x>0?1:0) using namespace std; enum{R=100,C=100,D=100}; int main(){ string s; int N[D][2],M=0,rs=0,cs=0,i,j,V,L,dr,dc; for(i=0;j=0,(i<R)&&getline(cin,s);i++) while((j=s.find_first_not_of(" ",j))<=s.size()){ L=sscanf(&s[j],"%d",&V); N[V][0]=i; N[V][1]=j; if(M<V)M=V; if(rs<=i)rs=i+1; if(cs<=j)cs=j+1; j+=L+1; } string F(rs*cs,' '),lines="\\|/-+-/|\\"; F[cs*N[1][0]+N[1][1]]='+'; for(i=2;i<=M;++i){ int r=N[i-1][0],c=N[i-1][1],rt=N[i][0],ct=N[i][1]; for(dr=S(rt-r),dc=S(ct-c);r!=rt||c!=ct;) r+=dr,c+=dc,F[cs*r+c]=lines[(dr+1)*3+dc+1]; F[cs*r+c]='+'; } for(i=0;i<rs;i++) cout<<string(&F[i*cs],cs)+"\n"; } 

Despite superficial differences, it's a blatant theft of morotspaj's code.