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:
- remplacer un numéro par un"
+
"caractère - pour les lignes horizontales: utiliser "
-
- pour les lignes verticales: utiliser "
|
- aller à gauche et en bas ou à droite et en haut:
/
- aller à gauche et en haut ou à droite et en bas:
Notes Importantes:
-
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". -
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.
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.
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 :)
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 :
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 :)
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:
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)
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
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:
- l'entrée doit maintenant avoir toutes les lignes matelassées à la même longueur (permise par les règles.)
- 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.
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
}
}
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);
}
}
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.
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
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
Python-381
import re
b=list(iter(raw_input,''))
c=sum((zip([i]*999,re.finditer('\d+',x))for i,x in enumerate(b)),[])
d=sorted((int(m.group()),i,m.start())for i,m in c)
e=[[' ']*max(map(len,b))for x in b]
for(t,u,v),(x,y,z)in zip(d,d[1:]+d[-1:]):
e[u][v]='+'
while u!=y or v!=z:i,j=(u<y)-(u>y),(v<z)-(v>z);u+=i;v+=j;e[u][v]=['|','/\-'[(i==j)+2*(i==0)]][j!=0]
print'\n'.join(map(''.join,e))
C#, 422 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
}
}
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;
}
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);
}
}
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:
+\
| \
+--\+
+\
| \
| \
+---\+
+\
| \
| \
| \
+----\+
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.