49

您可能还记得小时候的这些图画,但现在是时候让计算机绘制它们了(完整的 ascii 辉煌)。玩得开心!

描述:

输入是描述“字段”的多行(以换行符结尾)。该字段中散布着“数字”(由空格分隔)。所有行都可以被认为是相同的长度(您可以将空格填充到末尾)。

  • 数字总是从 1 开始
  • 它们遵循自然数的顺序:每个“下一个数字”都以 1 递增
  • 每个数字都被(至少)左右一个空格包围

任务:

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

  1. 用 ' +' 字符替换数字
  2. 对于水平线:使用 ' -'
  3. 对于垂直线:使用' |'
  4. 向左和向下或向右和向上:/
  5. 向左和向上或向右和向下:\

重要笔记:

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

  2. 遵循点连接的顺序很重要(较新的线条可以剔除较旧的线条)。

-- 样本输入 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 --独角兽参考

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

优胜者:

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

4

16 回答 16

58
于 2010-03-29T22:25:53.543 回答
36

Perl,222 个字符 (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 个字符),这项任务会更容易。该语句接受每一行输入,用 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)=排序{$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整除$',则继续递增 并分配字符,直到达到。更具体地说,例如,如果可以被 97 整除,则增加97 并设置。重复直到。$P$'$&$S[$P]$P$Q$Q-$P$P$S[$P]='|'$P>=$Q

    $n++;$p=$q

为循环的下一次迭代做准备。递增$n到要在输入中搜索的下一个数字,并$p保持前一个数字的位置。

s/\d/ /,print for@S

输出数组,将任何剩余的数字(从输入中的两位数标识符,我们只用“+”覆盖第一个数字)转换为空格。

于 2010-03-27T05:55:51.770 回答
14

MS-DOS 批处理(是的,你没看错!)

我经常听到(或读到)人们说批处理不是很强大,你不能用它们做很多事情,我对他们说,看哪,批处理的力量!

实际脚本(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”是一个包含“程序”输入的文件。

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

于 2010-03-31T14:21:59.167 回答
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是 find,fe是 foreach,sp是空格字符,i?是 index,hd是 head,ch是 change,sk是 skip,pc是 pick,bk是 break,iis if,eis either,eeis either equal,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 a b]

; d finds you the iterator position of the first digit of a two digit
; number in the matrix
d: a| [fe s m [t: fi s rj [sp a sp] i t [++ 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 [x j y j]]

; 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: c b 

    ; 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 
    i f [
        ; k is the iterator position of the end of the stroke
        k: c f

        ; the (h)orizontal and (v)ertical offsets we'll step by (-1,0,1)
        h: q x k x j 
        v: q y k y j 

        u [
            ; 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 c b pc l ez v 1 [ez h 2 [ee h v 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 [h v] 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 j e fi l sc j {+} {+ }

    ; update from finish pair to be new begin pair for next loop iteration
    j: k
    b: f
] 

; write out m
w m

语言和样本都是新的,处于实验阶段。例如,ad在我更改它以帮助处理此示例之前,它不能用于将向量和矩阵相加。但我认为这正是专为代码高尔夫设计的语言必须具备的那种东西。这是“语言”和“图书馆”之间的微妙界限。

GitHub 上提供的带有评论的最新资源

于 2010-06-18T02:28:17.243 回答
11

Haskell,424 个字符

当前字符数:424430 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. 不再需要任何一种语言扩展

原始版本:

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

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

于 2010-03-27T09:05:39.843 回答
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
    }
}
于 2010-03-29T00:19:35.267 回答
9

C, 386

C 中的402 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);
}
}
于 2010-03-27T09:12:25.320 回答
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'来实现循环计数器,确定线/运动方向的有趣方式。

于 2010-03-31T22:55:34.710 回答
5

电源外壳,328304 个字符

$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
于 2010-03-28T19:57:46.987 回答
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 行:打印结果

于 2010-03-27T02:31:03.117 回答
4

蟒蛇 - 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))
于 2010-03-27T01:48:07.003 回答
3

C#,422 个字符

758 754 641 627 584 546 532 486 457 454 443 440 422 个字符(下次可能我不会这么快提交。)

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
    }
}
于 2010-03-28T20:34:54.550 回答
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);
    }
}
于 2010-03-27T07:21:02.517 回答
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;
}
于 2010-03-27T01:18:56.960 回答
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 代码的公然盗窃。

于 2010-03-27T05:55:44.810 回答
1

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

+
|\
+-+

+
|\
| \
+--+

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

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

+\
| \
+--\+

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

+\
| \
|  \
|   \
+----\+
于 2010-03-27T00:03:50.283 回答