Подтвердить что ты не робот

Code Golf: подключение точек

Вы можете помнить эти рисунки с того момента, когда вы были ребенком, но теперь пора позволить компьютеру нарисовать их (в полном блеске ascii). Получайте удовольствие!

Описание:

Ввод представляет собой несколько строк (завершенных новой строкой), которые описывают "поле". В этом поле есть "числа" (разделенные пробелами). Все строки можно считать одинаковой длиной (вы можете заполнить пробелы до конца).

  • числа всегда начинаются с 1
  • они следуют порядку натуральных чисел: каждое "следующее число" увеличивается с помощью 1
  • каждое число окружено (по крайней мере) одним пробелом слева и справа

Задача:

Нарисуйте линии между этими числами в натуральном порядке (1 -> 2 -> 3 -> ...N) (предположим, что N <= 99) со следующими характеристиками:

  • заменить номер символом '+'
  • для горизонтальных линий: используйте '-'
  • для вертикальных линий: используйте '|'
  • перемещение влево и вниз или вправо и вверх: /
  • перемещение влево и вверх или вправо и вниз: \

Важные замечания:

  • При рисовании строк типа 4 и 5 вы можете предположить (учитывая точки для соединения с координатами x1, y1 и x2, y2), что distance(x1,x2) == distance(y1,y2). Или, другими словами (как комментирует пользователь jball): "последовательные элементы, которые не выравниваются по горизонтали или по вертикали, всегда выровняются по наклону косой черты или обратной косой черты".

  • Важно следовать порядку подключения точек (новые строки могут удалять старые строки).

- Пример ввода 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 - (ссылка для единорога)

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

Победитель:

Кратчайшее решение (по количеству символов кода). Вход можно считывать с помощью стандартного ввода.

4b9b3361

Ответ 1

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 [email protected]

Пояснение:

$_=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= тах ($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, то increment $p на 97 и установите $S[$P]='|'. Повторяйте до $P>=$Q.

    $n++;$p=$q

Подготовьтесь к следующей итерации цикла. Приращение $n к следующий номер для поиска на входе, и пусть $p удерживает положение предыдущего номера.

s/\d/ /,print [email protected]

Вывести массив, преобразуя любые оставшиеся цифры (из double разрядных идентификаторов на входе, где мы только перезаписываем первый с пробелом "+" ) до пробелов.

Ответ 2

Commodore 64 BASIC - 313 символов

EDIT: см. ниже версию для игры в гольф

Небольшая поездка по полосе памяти с PET графика, POKE s и PEEK s и все:)

It fits in a single screen:)

Программа работает непосредственно в памяти экрана, поэтому вы просто продолжаете, очищаете экран, размещаете точки и набираете RUN:

Input

Вам нужно подождать минуту или около того, пока он найдет точки, а затем начнет рисовать. Это не быстро - вы можете увидеть линии, которые рисуются, но самая крутая часть:)

Output

Версия для гольфа:

Commodore BASIC кажется отличным языком для игры в гольф, потому что он не требует пробелов:). Вы также можете сократить большинство команд на вводя несмещенную первую букву, за которой следует сдвинутая вторая буква. Например, POKE может быть введен как P [SHIFT + O], который отображается как P┌ на экране:

Golfed version

Ответ 3

Пакет MS-DOS (да, вы правильно читаете!)

Я часто слышу (или читаю), что люди говорят, что партия не очень сильная, и вы не можете много сделать с ними, хорошо им я говорю, вот, сила BATCH!

Фактический script (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 байт)

Ответ 4

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 является голосом, ch является изменением, sk является пропуском, pc - это выбор, bk - разрыв, i есть, если, 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 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 current position and advances G (f+ = "first+")
; advance g 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

Ответ 5

Haskell, 424 символа

Current char count: 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 ниже, но вносит существенные изменения. Самое главное, он представляет местоположение изображения с одним индексом, а не с двумя координатами.

Есть некоторые изменения:

  • Теперь вход должен содержать все строки с одинаковой длиной (разрешенные правилами.)
  • Больше не требуется расширение языка

Оригинальная версия:

(Требуется -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 может содержать только последний символ в том же месте.

Ответ 6

AWK - 296 317 321 324 334 340

Не победитель приза (пока), но я доволен усилием (разрывы строк для отображения). В этой новой версии используются escape-последовательности 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
    }
}

Ответ 7

C, 386

402 386 символов в C. Новые строки после первого доступны только для чтения.

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

Ответ 8

Ассемблер Intel

Собранный размер: 506 байт

Источник: 2252 байта (эй, это не тривиальная проблема)

Собрать: использовать A86 Выполнение: Протестировано с помощью окна DOS WinXP. Вызов 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" для создания счетчика циклов, интересный способ определения направления линии/движения.

Ответ 9

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:... sort so (a, b) - это "самая высокая" из двух точек, а (x, y) - другая. Поместите знаки "+", а затем, если горизонтально, нарисуйте это, иначе, если вертикально, нарисуйте это, иначе нарисуйте правильную диагональ. Если вход не является "действительным", то кто знает, что происходит (этот код был завален "утверждениями" до того, как я включил его в гольф).

Строки 17-19: печать результата

Ответ 10

Powershell, 328 304 символа

$i=$l=0;[email protected]{}
[email protected]($input|%{[regex]::matches($_,"\d+")|%{$k[1*$_.Value][email protected]{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)
[email protected]{}             # hashtable that maps dot index to coordinates  

# Apply regular expression to each line of the input
[email protected]( $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

Ответ 11

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

Ответ 12

С#, 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 
                // 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
    }
}

Ответ 13

Вот так!

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

Ответ 14

С#, 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);
    }
}

Ответ 15

Я не могу делать многострочный комментарий, поэтому я продемонстрирую здесь. В следующих примерах расстояние (x1, x2) == distance (y1, y2):

+
|\
+-+

+
|\
| \
+--+

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

С правилами, как объяснено, расстояние (x1, x2) == расстояние (y1, y2) +2:

+\
| \
+--\+

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

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

Ответ 16

С++ 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.