Code Golf: relier les points

vous vous souvenez peut-être de ces dessins de quand vous étiez un enfant, mais maintenant il est temps de laisser l'ordinateur les dessiner (en pleine splendeur ascii). Amusez-vous!

Description:

les entrées sont des lignes multiples (se terminant par une nouvelle ligne) qui décrivent un 'champ'. Il y a des "nombres" dispersés dans ce champ (séparés par des espaces). Toutes les lignes peuvent être considérés comme la même longueur (vous pouvez remplir les espaces à la fin).

  • les nombres commencent toujours par 1
  • ils suivent l'ordre des nombres naturels: chaque "numéro" est incrémentée de 1
  • chaque nombre est entouré (au moins) d'un espace à sa gauche et à sa droite

tâche:

Dessiner lignes entre ces nombres dans leur ordre naturel (1 -> 2 -> 3 -> ...N) (hypothèse N < = 99) avec les caractéristiques suivantes:

  1. remplacer un numéro par un" + "caractère
  2. pour les lignes horizontales: utiliser " -
  3. pour les lignes verticales: utiliser " |
  4. aller à gauche et en bas ou à droite et en haut: /
  5. aller à gauche et en haut ou à droite et en bas:

Notes Importantes:

  1. lorsque vous tracez des lignes de type 4 et 5, vous pouvez supposer (étant donné les points à relier avec les coordonnées x1, y1 et x2, y2) que distance(x1,x2) == distance(y1,y2) . Ou en d'autres termes (comme l'a commenté l'utilisateur jball): "les éléments consécutifs qui ne sont pas alignés horizontalement ou verticalement s'alignent toujours sur la pente de la barre oblique ou de la barre oblique inversée".

  2. il est important de suivre la ordre dans lequel les points sont reliés (les lignes plus récentes peuvent rayer les lignes plus anciennes).

-- échantillon d'entrée 1 --

                                  8 

                                  7  6 
                      10       9       

                                        5            

                                     3  4        
                 11 

                   12                       13    
          1                          2                     

-- sortie de L'échantillon 1 --

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

-- entrée de L'échantillon 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                       

-- sortie D'échantillon 2 -- ( unicorn référence )

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

vainqueur:

solution la plus courte (par le nombre de caractères codés). Les entrées peuvent être lues via les entrées standard.

49
demandé sur ChristopheD 2010-03-27 02:37:24

16 réponses

Perl, 222 char (211)

Perl, 384 365 276 273 253 225 222 218 211 jars (222 à la fin du concours). Les nouvelles lignes sont pour la "lisibilité" seulement et ne sont pas inclus dans le nombre de caractères.

Dernière édition: plus réécriture $" , et impression @S directement

    $_=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' |97 /96 -1'){/\D/;$S[$P]=$&until($Q-$P)%$'||$Q<=($P+=$')}
    $n++;$p=$q}s/\d/ /,print for@S

explication:

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

cette tâche sera plus facile si toutes les lignes sont de la même longueur (par exemple 97 caractères). Cette instruction prend chaque ligne d'entrée, remplace le caractère de fin de ligne par 96 espaces, puis pousse les 96 premiers caractères plus une nouvelle ligne dans le tableau @S . Notez que nous paramétrons aussi $n=1 , comme 1 est le premier nombre que nous allons rechercher dans entrée. L'instruction join crée une chaîne simple à partir du tableau @S . Il est plus pratique d'utiliser la variable scalaire $_ pour l'appariement des motifs, et plus pratique d'utiliser le tableau @S pour faire des mises à jour de l'image.

while(/\b$n /){

cherche le numéro $n dans la variable $_ . L'évaluation des expressions régulières en Perl a plusieurs effets secondaires. L'un est de définir la variable spéciale $-[0] avec la position du début du motif apparié dans la chaîne appariée. Cela nous donne la position du nombre $n dans la chaîne de caractères $_ et aussi le tableau @S .

bien sûr, la boucle se terminera quand $n sera assez haut pour qu'on ne puisse pas le trouver dans l'entrée.

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

Let $q la position de le nombre $n dans la chaîne $_ et le tableau @S , et d'attribuer le caractère '+' à cette position.

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

la première fois dans la boucle, mettez $p à $q . Après l' la première fois, $p tiendra la précédent valeur de $q (qui référence à la position de l'entrée du numéro précédent). Attribuer $P et $Q de telle sorte que $P = min ( $p , $q ), $Q = max ( $p , $q )

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

par construction, les nombres consécutifs sont soit

  • connectés par une ligne verticale. Puisque l'entrée est construite pour avoir 97 caractères sur chaque ligne, ce cas, signifie que $p-$q est divisible par 97.

  • "aligné sur la pente d'un backslash", ce qui ferait $p-$q divisible par 98

  • "aligné sur la pente d'une barre oblique avant", ce qui ferait $p-$q divisible par 96

  • sur la même ligne horizontale

les éléments de cette liste codent le nombre possible de positions entre les segments de ligne, et le caractère pour encoder ce segment.

        /\D/;

un Autre trivial regex évaluation. Comme effet secondaire, il définit le variable spéciale $& (la variable correspond à la variable ) pour le segment de ligne caractère ( \ | / ou - ) et $' (la variable POSTMATCH ) à le numéro (98 97 96 ou 1) encodé dans l'élément list.

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

cette déclaration dessine le segment de ligne entre deux nombres. Si $Q-$P est divisible par $' , alors continuez à augmenter $P par $' et attribuer le caractère $& à $S[$P] jusqu'à ce que $P atteigne $Q . Plus concrètement, par exemple, si $Q-$P est divisible par 97, incrément $P par 97 et mis $S[$P]='|' . Répéter jusqu'à $P>=$Q .

    $n++;$p=$q

préparez la prochaine itération de la boucle. Accroissement $n à la numéro suivant à rechercher dans l'entrée, et laisser $p tenir le position du numéro précédent.

s/\d/ /,print for@S

sortie le tableau, en convertissant n'importe quels chiffres restants (de double chiffres identifiants dans l'entrée où nous n'écrasait la première chiffre avec un"+") aux espaces que nous allons.

36
répondu mob 2011-08-16 23:41:42

Commodore 64 de BASE - 313 caractères

EDIT: Voir ci-dessous l'ont joué au golf version

un petit voyage dans la mémoire avec PET graphics, POKE s et PEEK s et tout :)

It fits in a single screen:)

le programme fonctionne directement dans la mémoire de l'écran, ainsi vous n'avez qu'à aller de l'avant, effacer l'écran, placer vos points, et taper RUN :

Input

Vous devez attendre une minute ou alors, s'il trouve les points et puis il commence à dessiner. Il n'est pas rapide - vous pouvez réellement voir les lignes dessinées, mais c'est la partie la plus fraîche :)

Output

version Golfée:

Commodore BASIC semble comme un grand langage pour le golf, parce qu'il ne nécessite pas de blancs espace :) vous pouvez également raccourcir la plupart des commandes en entrant une première lettre non changée suivie d'une deuxième lettre décalée. Par exemple, POKE peut être dactylographié comme P[SHIFT+O], qui apparaît comme P┌ sur l'écran:

Golfed version

58
répondu Danko Durbić 2012-02-15 15:05:48

de commandes MS-DOS (oui, vous avez bien lu!)

j'entends souvent (ou je lis) des gens dire que la fournée n'est pas très puissante et qu'on ne peut pas en faire beaucoup; Eh bien, je leur dis: voici, le pouvoir de la fournée!

Du script (script.chauve-souris):

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

et c'est comme ça qu'on l'appelle

echo off
setlocal ENABLEDELAYEDEXPANSION
call script.bat input.txt

où ".txt" est un fichier qui contient l'entrée pour programme."

P.S. ce n'est pas encore optimisé pour la longueur de ligne, j'ai déjà passé quelques heures pour arriver à ce point et maintenant j'ai besoin de dormir... Je vais voir si je peux améliorer ça demain (actuellement " le script.bat' se trouve à 2755 octets)

14
répondu Grant Peters 2010-03-31 14:21:59

Rebmu : 218 chars

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

je commence à être assez bon à lire et à éditer nativement dans sa forme pig-latin. (Bien que je ne l'utilisez des sauts de ligne!!):)

Mais voici comment le dialecte est transformé par l'interprète lorsque le truc de "mushing", insensible à la casse, est enlevé, et qu'on s'y habitue. Je vais ajouter quelques commentaires. (conseils: fi est trouver, fe est foreach, sp est un caractère d'espace, i? est l'indice de 151960920" est à la tête, ch est le changement, le sk est skip, pc , c'est de prendre, bk se briser", 1519110920" si, e est, ee est égale, ad nauseam)

; 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

la langue et l'échantillon sont tous deux nouveaux et en phase expérimentale. Par exemple, ad ne pouvait pas être utilisé pour additionner vecteurs et matrices avant que je le change pour aider avec cet échantillon. Mais je pense que c'est exactement le genre de chose qu'un langage spécialement conçu pour le golf codé doit avoir de toute façon. C'est une ligne subtile entre "langue" et "bibliothèque".

dernière source avec commentaires disponible sur GitHub

12
répondu HostileFork 2014-02-16 12:39:58

Haskell, 424 caractères

Actuel char comte: 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((&&)&(>' '))

cette version prend beaucoup d'inspiration de L'entrée originale de Haskell ci-dessous, mais fait quelques changements significatifs. Plus important encore, il représente des emplacements d'image avec un seul index, pas une paire de coordonnées.

Il y quelques changements:

  1. l'entrée doit maintenant avoir toutes les lignes matelassées à la même longueur (permise par les règles.)
  2. N'a plus besoin d'aucune extension linguistique

version originale:

(Besoins -XTupleSections , et peut-être -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

explication:

(1) d=... : divise l'entrée en espaces et en nombres, par exemple

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

(2) e=... : convertit d en une liste de (y, x) coordonnées pour chaque nombre.

   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)|...] est une planche vide. ( k renvoie un espace ou un \n en fonction de la coordonnée X.)
  • [((y,x),'+'))|...] sont les signes plus aux numéros.
  • (f j$zip e$tail e) sont les lignes reliant les numéros. ( j cartes une paire de coordonnées dans une liste de (coordonner, de caractère) qui représente une ligne.)

ces 3 composants sont concaténés et filtrés pour former la sortie réelle. Notez que l'ordre est important, de sorte que nubBy(...).g ne peut conserver le dernier caractère qu'au même endroit.

11
répondu KennyTM 2010-04-01 16:08:48

AWK - 296 317 321 324 334 340

pas un gagnant (encore), mais je suis satisfait de l'effort (ligne de pauses pour l'affichage). Cette nouvelle version utilise des séquences d'échappement VT-100. '^[' Est juste un caractère, d'Évasion!!! Couper et coller ne fonctionnera pas avec cette version, puisque la séquence" ^ ["doit être remplacée par le vrai caractère ESC. Pour rendre le forum convivial, ESC pourrait être spécifié comme "\0x1b", mais il faut aussi beaucoup d'espace...

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

l'ancienne version standard

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

Maintenant, un peu d'explication

# 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
    }
}
10
répondu Dan Andreatta 2010-03-31 14:55:46

C, 386

402 386 les caractères dans C. Newlines après le PREMIER sont seulement pour la lisibilité.

#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);
}
}
9
répondu Boojum 2010-03-27 09:48:02

Intel Assembleur

Assemblé taille: 506 octets

Source: 2252 octets (hé, c'est pas un problème trivial)

Pour L'Assemblage: Utiliser A86 À exécuter: Testé avec une boîte DOS WinXP. Invocation 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:

caractéristiques intéressantes: code Auto-modificateur, sortie animée (le second exemple fonctionne, mais est trop grand pour être affiché), abus de 'ret' pour implémenter une boucle compteur, façon intéressante de déterminer la direction de la ligne / du mouvement.

7
répondu Skizz 2010-03-31 22:55:34

F#, 725 caractères

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

légende:

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

lignes 1-6: je garde un ensemble de tuples (nombre, lineNum, xCoord); comme je lis dans chaque ligne d'entrée je trouve tous les nombres et les ajoute à l'ensemble.

ligne 7-8: ensuite je crée un tableau de caractères de sortie, initialisé à tous les espaces.

Ligne 9: Trier les ('nombre'), puis prendre chaque paire adjacente et ...

Lines 10-16: ... trier ainsi (a, b) est le "plus haut" des deux points et (x,y) est l'autre. Mettez les signes'+', et puis si horizontal, dessinez cela, sinon si vertical, dessinez cela, sinon dessinez la bonne diagonale. Si l'entrée n'est pas "valable", alors qui sait ce qui se passe (ce code a été jonché de "soutient" avant j'golf-isée).

lignes 17-19: imprimer le résultat

5
répondu Brian 2010-03-27 02:40:47

Powershell, 328 304 characters

$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

et voici une version joliment imprimée avec des commentaires:

# 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
5
répondu Danko Durbić 2010-03-28 21:34:42

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))
4
répondu Jimmy 2010-03-30 23:51:06

C#, 422 caractères

758 754 641 627 584 546 532 486 457 454 443 440 422 la prochaine fois, je ne me soumettrai peut-être pas si vite.)

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

utilisation: exécutez, collez (ou tapez) l'entrée, assurez-vous que la dernière ligne est terminée, appuyez sur CTRL-Z ou F6, appuyez sur Entrée.

formatée mais toujours essentiellement inintelligible version:

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
    }
}
3
répondu Igby Largeman 2012-02-24 22:09:31

C'est parti!

#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;
}
2
répondu morotspaj 2010-03-27 01:18:56

C#, 638 caractères

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);
    }
}
2
répondu Jeff Meatball Yang 2010-03-27 07:21:02

Je ne peux pas faire de multi-ligne dans un commentaire, donc je vais montrer ici. Dans les exemples suivants, distance (x1, x2) = = distance (y1,y2):

+
|\
+-+

+
|\
| \
+--+

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

avec les règles expliquées, distance (x1, x2) = = distance (y1, y2)+2:

+\
| \
+--\+

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

+\
| \
|  \
|   \
+----\+
1
répondu Jeff B 2010-03-27 00:03:50

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

indenté, et avec quelques noms légèrement plus significatifs, qui ressemble à:

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

malgré des différences superficielles, c'est un vol flagrant du code de morotspaj.

1
répondu Jerry Coffin 2010-03-27 05:55:44