Code Golf:连接点

时间:2010-03-26 23:37:24

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

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

说明

输入是多行(由换行符终止),用于描述“字段”。这个领域散布着“数字”(由空格分隔)。所有行都可以被认为是相同的长度(你可以填充空格到最后)。

  • 数字始终从1
  • 开始
  • 他们遵循自然数字的顺序:每个“下一个数字”增加1
  • 每个数字左右都有(至少)一个空格

任务:

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

  1. 用“+”字符替换号码
  2. 表示水平线:使用“-
  3. 表示垂直线:使用“|
  4. 左右或上下:/
  5. 左右上下:\
  6. 重要说明:

    1. 当绘制类型为4和5的线时,您可以假设(给定与坐标x1,y1和x2,y2连接的点)distance(x1,x2) == distance(y1,y2)。或换句话说(如用户jball评论):“非水平或垂直对齐的连续元素始终与斜杠或反斜杠的斜率对齐”。

    2. 按照点连接的顺序非常重要(较新的线条可以删除较旧的线条)。

    3. - 示例输入1 -

                                        8 
      
                                        7  6 
                            10       9       
      
                                              5            
      
                                           3  4        
                       11 
      
                         12                       13    
                1                          2                     
      

      - 示例输出1 -

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

      - 示例输入2 -

                              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 - unicorn reference

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

      获胜者:

      最短解决方案(按代码字符计数)。输入可以通过标准输入读取。

16 个答案:

答案 0 :(得分:58)

Commodore 64 BASIC - 313 chars

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

使用 PET 图片, POKE PEEK 以及所有内容,在记忆通道上稍微停留一下:)

It fits in a single screen:)

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

Input

你必须等待一分钟左右,同时找到点,然后开始绘制。它并不快 - 你实际上可以看到正在绘制的线条,但这是最酷的部分:)

Output

高尔夫版本:

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

Golfed version

答案 1 :(得分:36)

Perl,222 char(211)

Perl, 384 365 276 273 253 225 < / strike> 222 218 211 chars(比赛结束时为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个字符),则此任务将更容易。 此语句接受每行输入,用行替换行尾字符 96个空格,然后将前96个字符加上换行符推入数组@S。 请注意,我们还设置了$n=1,因为1是我们要查找的第一个数字 输入。 join语句从数组@S创建一个字符串。 使用标量变量$_进行模式匹配更方便,使用数组@S更方便地对图片进行更新。

while(/\b$n /){

在变量$n中搜索$_个数字。评估Perl中的正则表达式 有几个副作用。一种是将特殊变量$-[0]设置为匹配字符串中匹配模式的起始位置。这为我们提供了字符串$n中数字$_以及数组@S的位置。

当然,当$n足够高以至于我们无法在输入中找到它时,循环将结束。

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

$q成为字符串$n和数组$_中数字@S的位置, 并在该位置指定字符“+”。

        $P=($p||=$q)+$q-($Q=$q>$p?$q:$p)
        ($P,$Q)=sort{$a-$b}$p||$q,$q;

第一次循环,将$p设置为$q。之后 第一次,$p将保留之前的$q(其中 将引用前一个数字输入中的位置)。 分配$P$Q$P = min($p$q), $Q = MAX($p$q

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

通过构造,连续数字是

  • 通过垂直线连接。由于输入是构造的 每行有97个字符,这种情况意味着 $p-$q可以被97整除。

  • “与反斜杠的斜率对齐”,这会产生 $p-$q可被98整除

  • “与正斜线的斜率对齐”,这将会产生 $p-$q可被96整除

  • 在同一水平线上

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

        /\D/;

另一个琐碎的正则表达式评估。作为副作用,它设定了 线段的特殊变量$&MATCH变量) 字符(\ | /-)和$'POSTMATCH变量)到 列表元素中编码的数字(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到 要在输入中搜索的下一个数字,然后让$p按住 前一个号码的位置。

s/\d/ /,print for@S

输出数组,转换任何剩余数字(来自double 输入中的数字标识符,我们只覆盖了第一个 我们去的地方有一个带“+”的数字。

答案 2 :(得分:14)

MS-DOS Batch (是的,你看对了!)

我经常听到(或读过)人们说批次不是很强大,你不能对它们做太多的事情,对我们说好,不料,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”是包含“程序”输入的文件。

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

答案 3 :(得分:12)

Rebmu: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

我很擅长以猪拉丁形式阅读和编辑它。 (虽然我确实使用换行!!):)

但是,当案例不敏感的“糊涂”伎俩被淘汰时,解释者如何改变方言,并且习惯了它。我会添加一些评论。 (提示:fi已找到,fe为foreach,sp为空格字符,i?为索引,hd为head,{{ 1}}是更改,ch是跳过,sk是选择,pc是中断,bk是if,i是,{{1} }是相等的,是偶然的)

e

语言和样本都是新的,处于试验阶段。例如,在更改向量和矩阵以帮助此示例之前,ee无法用于将向量和矩阵相加。但我认为这就是专门为代码高尔夫设计的语言无论如何都必须具备的东西。这是“语言”和“图书馆”之间的微妙界限。

评论available on GitHub

的最新来源

答案 4 :(得分:11)

Haskell,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]
l k p q|p>q=l k q p|True=head[[p,p+j..q]%c|m<-zip[k-1,k,k+1,1]"/|\\-",let (j,c)=m,mod(q-p)j==0]
w=map snd
q(k,m,x)z=w$sort$nubBy((==)&fst)$x%'+'++(concat$zipWith(l k)x$tail x)++z%'\n'++[1..m]%' '
r(z,m,x)=q(last z,m-1,w$sort x)z
u[(m,_)]n x=(-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)n x)
y&x=(.x).y.x
main=interact$r.foldl t([],1,[]).groupBy((&&)&(>' '))

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

有一些变化:

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

  3. 原始版本:

    (需要-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+b z)
    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).y.x
    y?x=f y.sort.x.concat
    r z=snd?(nubBy((==)&fst).g)$[((y,x),k x)|x<-[0..maximum$f b d],y<-[1..b d]]:[((y,x),'+')|[x,y]<-e]:(f j$zip e$tail e)where d=f(groupBy$(&&)&(>' '))$lines z;e=tail?f g$zipWith(f.(:))[1..]$f(fst.foldl a([],1))d
    main=interact r
    

    说明:

    (1) d=...:将输入拆分为空格和数字,例如

       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),k x)|...]是一个空板。 (k会返回一个空格或\n,具体取决于x坐标。)
    • [((y,x),'+'))|...]是数字上的加号。
    • (f j$zip e$tail e)是连接数字的线。 (j将一对坐标映射到表示一条线的(坐标,字符)列表中。)

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

答案 5 :(得分:10)

AWK - 296 317 321 324 334 340

不是奖品获得者(但是),但我很满意这些努力(显示的换行符)。这个新版本使用VT-100转义序列。 '^ ['只是一个角色,Escape !!!使用此版本剪切和粘贴将无效,因为序列“^ [”必须替换为真正的ESC字符。为了使论坛友好,可以将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,
# i.e. 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
    }
}

答案 6 :(得分:9)

C,386

402 C中的386个字符。第一个后面的新行只是为了便于阅读。

#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?(j-k|m-n?j+k|m+n?j|m?b:'|':'/':'\\'):b:'-':'+';
putchar(b);
}
}

答案 7 :(得分:7)

英特尔汇编程序

汇编大小:506字节

来源:2252字节(嘿,这不是一个小问题)

要组装:使用A86 运行:使用WinXP DOS框测试。调用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:

有趣的功能:自修改代码,动画输出(第二个示例有效,但太大而无法显示),滥用'ret'来实现循环计数器,这是确定线条/移动方向的有趣方式。

答案 8 :(得分:5)

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 a x)+1..(max a x)-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..y-b-1 do o.[b+i,a+i]<-'\\'
else for i in 1..y-b-1 do o.[b+i,a-i]<-'/')
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)元组;当我在每行输入中读到时,我会找到所有数字并将它们添加到集合中。

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

第9行:对集合进行排序(按'数字'),然后取出每个相邻的对并...

第10-16行:......排序所以(a,b)是两点中的“最高”,而(x,y)是另一点。放置'+'符号,然后如果是水平的,则绘制它,否则如果是垂直的,则绘制它,否则绘制正确的对角线。如果输入不是“有效”,那么谁知道发生了什么(在我高尔夫球化之前,这段代码充斥着'断言'。)

第17-19行:打印结果

答案 9 :(得分:5)

Powershell, 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=$a.x;$y=$a.y}
do{$d=$a.x.CompareTo($x);$e=$a.y.CompareTo($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 = $a.x;
        $y = $a.y
    }

    do
    {
        $d = $a.x.CompareTo( $x )           # sign( $a.x - $x )
        $e = $a.y.CompareTo( $y )           # sign( $a.y - $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

答案 10 :(得分:4)

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))

答案 11 :(得分:3)

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();}}

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

格式化但仍然基本上不可理解的版本:

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
    }
}

答案 12 :(得分:2)

到此为止!

#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;
}

答案 13 :(得分:2)

C#,638个字符

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=>a.N).ToList();

        var W = p.Max(a => a.X)+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 = a.Y - b.Y, w = a.X - b.X;
            var s = "|-/\\"[h == 0 ? 1 : w == 0 ? 0 : h / w > 0 ? 3 : 2];
            while ((h | w) != 0) { k[b.X + w + W * (b.Y + h)] = s; h -= h.CompareTo(0); w -= w.CompareTo(0); }
            k[a.X + a.Y * W] = '+';
            k[W * ++i] = '\n';
        }

        Console.Write(k);
    }
}

答案 14 :(得分:1)

我不能在评论中做多行,所以我将在这里演示。 在以下示例中,距离(x1,x2)==距离(y1,y2):

+
|\
+-+

+
|\
| \
+--+

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

根据所解释的规则,距离(x1,x2)==距离(y1,y2)+2:

+\
| \
+--\+

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

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

答案 15 :(得分:1)

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(d-r),b=S(e-c);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";}

缩进,并带有一些稍微有意义的名称,如下所示:

#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";
}

尽管存在肤浅的差异,但这是对morotspaj代码的公然盗窃。