pssssssssssssst

31

introduction

Celui-ci est assez simple. Nous allons dessiner un serpent en ascii. Cela a été inspiré par ce vieux jeu de serpent où vous devez récolter les fruits et vous grandissez en permanence.

Définition

Étant donné un entier positif N qui représente la longueur du serpent, dessinez un serpent de sorte qu'il ait un corps de n plus une tête et une queue.

Les pièces:

  • tête: <, >, ^, v
  • queue: @
  • verticale: |
  • horizonal: -

Tous les coins doivent être satisfaits par un \ou /respectivement. À moins que la tête ne se termine dans un coin, auquel cas la tête <, >, ^, vest prioritaire dans la direction où le serpent est enroulé. c'est-à-dire pour l'exemple de longueur 1, il est tourné dans le sens inverse des aiguilles d'une montre et la tête est ainsi tournée de cette façon. Pour une solution dans le sens horaire, ce serait vers la droite >.

Le serpent doit commencer au milieu avec sa queue mais il peut aller vers l'extérieur dans n'importe quelle direction que vous choisissez dans le sens horaire ou antihoraire. Il doit également s'enrouler étroitement autour de lui car il se développe vers l'extérieur de manière circulaire.

Exemple

/--\
|/\|
||@|
|\-/
\--->

Où le @ est la queue et la position de départ. Comme vu ci-dessus, la queue commence au milieu, monte vers la gauche dans un sens antihoraire vers l'extérieur.

Ici, la longueur est 19plus une queue et une tête.

Comme autre exemple, voici la longueur 1:

<\
 @

Gagnant

Il s'agit de code-golf, donc la réponse soumise avec le plus petit nombre d'octets l'emporte, avec du temps pour être utilisée comme briseur d'égalité.

S'amuser!

jacksonecac
la source
2
Ce n'est pas très clair que je ne suis pas seulement autorisé à dessiner un serpent droit comme @---->. Vous avez probablement l'intention de conditions plus strictes sur la forme du serpent.
Indiquez
1
"Le serpent doit commencer au milieu avec sa queue mais il peut aller vers l'extérieur dans la direction que vous choisissez et dans le sens horaire ou antihoraire"
jacksonecac
1
Donc je dis @est le milieu (ajoutez éventuellement des espaces pour le rendre ainsi), déclarez "à droite" pour être la direction et faites juste la tête pointée vers le bas et déclarez cela dans le sens des aiguilles d'une montre. Vos termes peuvent vous sembler clairs, mais ils sont en fait ambigus. Je me rends compte que vous voulez probablement dire un serpent enroulé aussi étroitement que possible, mais vous devriez le dire clairement
Ton Hospel
1
Ne t'inquiète pas. Celui-ci est beaucoup plus difficile en raison des compensations de ce défi.
Martin Ender
2
Joli premier défi! Bienvenue sur le site!
Luis Mendo

Réponses:

10

MATL , 85 83 octets

Et je pensais qu'avoir un spiralbuiltin ferait du code court ...

Oli2+XH:UQXItH:+XJh(YsXKoQ3I(4J(5l(H:)0HX^XkU(6H(3M1YL3X!P)'|-\/@' '<v>^'KHq))h0hw)

Essayez-le en ligne!

Explication

Soit N la valeur de l'entrée. Nous allons créer un vecteur de longueur ceil(sqrt(N+2))^2, c'est-à-dire le plus petit carré parfait égal ou supérieur à N +2. Ce vecteur sera rempli de valeurs numériques, roulé en spirale (c'est pourquoi sa longueur doit être un carré parfait), puis les valeurs numériques seront remplacées par des caractères.

Soit n chaque étape à partir de 1 au centre de la spirale. Les étapes où le serpent tourne sont données par n 2 +1 (c'est-à-dire: 2, 5, 10, ...) pour les \symboles et n 2 + n +1 (c'est-à-dire: 3, 7, 13, ...) pour /. Les étapes entre a \et a /devraient être -, et celles entre a /et a \devraient l'être |.

Le vecteur est créé de telle sorte qu'il contient 1aux points de virage (2,3,5,7,10,13 ...) et 0au repos. La parité de la somme cumulée indique si chaque entrée doit être a -ou a |. En ajoutant 1 à ce résultat, nous obtenons un vecteur contenant 1(pour |) ou 2(pour -). Mais cela fait que les tournants eux-mêmes deviennent1 ou2 aussi. Les points de virage, dont nous connaissons les positions, sont donc écrasés: les positions n 2 +1 sont remplies 3et les positions n 2 + n +1 sont remplies 4. La queue et la tête sont également des cas particuliers: le premier élément du vecteur (queue) est défini sur 5, et l'élément d'indice N+2 (tête) est réglé sur 6. Enfin, les éléments dont les indices dépassent N +2 sont définis sur 0.

En prenant l'exemple N = 19, nous avons maintenant un vecteur de longueur 25:

5 3 4 1 3 2 4 1 1 3 2 2 4 1 1 1 3 2 2 2 6 0 0 0 0

Nous devons rouler ce vecteur en spirale. Pour cela, nous utilisons une fonction intégrée qui génère une matrice en spirale, suivie d'une réflexion et d'une transposition pour produire:

13 12 11 10 25
14  3  2  9 24
15  4  1  8 23
16  5  6  7 22
17 18 19 20 21 

L'indexation du vecteur avec la matrice donne

4 2 2 3 0
1 4 3 1 0
1 1 5 1 0
1 3 2 4 0
3 2 2 2 6

0correspond à l'espace, 1correspond à |, 2à -, 3à \, 4à /, 5à @et 6à la tête.

Pour savoir lequel des quatre personnages ^, <, vou >la tête doit avoir, nous utilisons la somme cumulée des points de virage que nous avons précédemment calculé. Plus précisément, l'avant-dernière valeur de cette somme cumulée (c'est-à-dire le N + 1-ème valeur) modulo 4 nous indique quel caractère doit être utilisé pour la tête. Nous prenons la deuxième dernière valeur de la somme cumulée, pas la dernière, en raison de l'exigence « si les extrémités de la tête sur un coin de la tête <, >, ^, vest prioritaire dans la direction du serpent est enroulé ». Pour l' exemple N = 19, la tête est >.

Maintenant , nous pouvons construire une chaîne contenant tous les caractères de serpent, y compris le caractère approprié pour la tête à la sixième position: '|-\/@> '. Nous indexons ensuite cette chaîne avec la matrice ci-dessus (l'indexation est basée sur 1 et modulaire, donc l'espace va en dernier), ce qui donne

/--\ 
|/\| 
||@| 
|\-/ 
\--->
Luis Mendo
la source
1
emploi super! merci d'avoir participé!
jacksonecac
8

Python 2, 250 233 191 octets

n=input()
l=[''],
a=x=0
b='@'
while a<=n:x+=1;l+=b,;l=zip(*l[::-1]);m=x%2;b='\/'[m]+x/2*'-|'[m];k=len(b);a+=k
l+=b[:n-a]+'>v'[m]+' '*(k-n+a-1),
if m:l=zip(*l[::-1])
for i in l:print''.join(i)
  • 39 octets enregistrés grâce à @JonathanAllan

repl.it

Dessinez le serpent en tournant le serpent entier de 90 ° dans le sens des aiguilles d'une montre et en ajoutant le segment inférieur, de cette façon le serpent sera toujours dans le sens inverse des aiguilles d'une montre.
Le nouveau segment commencera toujours par \et aura -comme corps pour les côtés pairs et / -pour les côtés impairs. Les segments de tailles (sans coins) sont 0, 1, 1, 2, 2, 3... ce qui est floor(side/2).
Si le segment est le dernier, il supprime les caractères en excès, ajoute la tête et complète avec des espaces.

desired_size=input()
snake=[['']]
snake_size=side=0
new_segment='@'
while snake_size<=desired_size:
    side+=1
    snake+=[new_segment]
    snake=zip(*snake[::-1])
    odd_side=side%2
    new_segment='\/'[odd_side]+side/2*'-|'[odd_side]
    snake_size+=len(new_segment)
diff=desired_size-snake_size
snake+=[new_segment[:diff]+'>v'[odd_side]+' '*(len(new_segment)-diff-1)]
if odd_side:
    snake=zip(*snake[::-1])

for line in snake:print ''.join(line)
Barre
la source
Bon travail! vous avez la victoire en bris d'égalité. Permet de voir ce que les autres inventent.
jacksonecac
2
C'est sûrement le langage idéal pour résoudre ce défi.
Neil
+1. Le seul problème est que lorsque la tête est dans un coin, elle est destinée à pointer directement, pas autour du coin.
Jonathan Allan
1
Enregistrer 16 octets par indexation dans des chaînes comme ceci: '\/'[m], '-|'[m]et'>v'[m]
Jonathan Allan
1
Économisez 1 de plus en supprimant l'espace entre printet''.join
Jonathan Allan
7

JavaScript (ES6), 193 201 203 215 220 224

Edit sauvegardé 4 octets thx @Arnauld
Edit2 a changé de logique, ne stockant pas les incréments actuels pour x et y, il suffit de les récupérer dans la direction courante
Edit3 ayant enregistré quelques octets, j'ai décidé de les utiliser pour une meilleure gestion de l'espace vide
Edit4 8 octets enregistrés ne suivant pas exactement les exemples sur la direction de la tête - comme les autres réponses

La version actuelle fonctionne avec Chrome, Firefox et MS Edge

Cette réponse donne un espace de fin et de début (et des lignes vides).

n=>(t=>{for(x=y=-~Math.sqrt(++n)>>1,g=[i=t];(g[y]=g[y]||Array(x).fill` `)[x]='^<v>|-/\\@'[t?n?i-t?4+t%2:x-y?7:6:t%4:8],n--;i=i>1?i-2:++t)d=t&2,t&1?x+=d-1:y+=d-1})(0)||g.map(x=>x.join``).join`
`

Un peu moins golfé

n=>
{
  g = [],
  // to save a few bytes, change line below (adds a lot of spaces)
  // w = ++n,
  w = -~Math.sqrt(++n)
  x = y = w>>1,
  s=c=>(g[y] = g[y] || Array(x).fill(' '))[x] = c, // function to set char in position
  s('@'); // place tail
  for (
     i = t = 0; // t increases at each turn, t%4 is the current direction
     n--;
     i = i > 0 ? i - 2 : t++ // side length increases every 2 turns
  )
     d = t & 2,
     t & 1 ? x += d-1: y += d-1
     s(!n ? '^<v>' [t % 4] // head
          : '|-/\\' [i > 0 ? t % 2 : x-y ? 3 : 2]) // body
  return g.map(x=>x.join``).join`\n`
}

f=
n=>(t=>{for(x=y=-~Math.sqrt(++n)>>1,g=[i=t];(g[y]=g[y]||Array(x).fill` `)[x]='^<v>|-/\\@'[t?n?i-t?4+t%2:x-y?7:6:t%4:8],n--;i=i>1?i-2:++t)d=t&2,t&1?x+=d-1:y+=d-1})(0)||g.map(x=>x.join``).join`
`

function update() {
  O.textContent=f(+I.value);
}

update()
<input type=number id=I value=19 oninput='update()' 
 onkeyup='update() /* stupid MS browser, no oninput for up/down keys */'>
<pre id=O>

edc65
la source
Vous pouvez économiser quelques octets en remplaçant (' ')par ` ` et ('@')par`@`
Arnauld
@Arnauld Array (2) .fill` `==> [ Array[1], Array[1] ], while Array(2).fill(' ')==>[' ',' ']
usandfriends
@usandfriends - Vrai. Mais cela ne devrait pas faire de différence une fois rejoint.
Arnauld
@Arnauld au début, j'étais d'accord avec nous et nos amis, mais cela fonctionne effectivement. Merci
edc65
@TravisJ Cela ne fonctionne pas dans Chrome, mais Firefox semble fonctionner.
Adnan
3

JavaScript (ES7), 200 octets

(n,s=(n*4+1)**.5|0,i=+`1201`[s%4],d=i=>`-`.repeat(i))=>[...Array(s-2>>2)].reduce(s=>`/-${d(i)}\\
${s.replace(/^|$/gm,`|`)}
|\\${d(i,i+=2)}/`,[`/\\
|@`,`/-\\
|@/`,`@`,`/@`][s%4])+`
\\${d(n-(s*s>>2))}>`

Version ES6 pour faciliter les tests:

f=(n,s=Math.sqrt((n*4+1))|0,i=+`1201`[s%4],d=i=>`-`.repeat(i))=>[...Array(s-2>>2)].reduce(s=>`/-${d(i)}\\
${s.replace(/^|$/gm,`|`)}
|\\${d(i,i+=2)}/`,[`/\\
|@`,`/-\\
|@/`,`@`,`/@`][s%4])+`
\\${d(n-(s*s>>2))}>`;
<input type=number min=1 oninput=o.textContent=f(this.value)><pre id=o>

Neil
la source
Mise en œuvre intéressante. Je n'avais pas pensé à faire ça. Merci pour votre contribution et bon travail !!
jacksonecac
3

Perl, 111 110 octets

Inclut +1 pour -p

Donnez la taille sur STDIN

snake.pl:

#!/usr/bin/perl -p
s%> %->%+s%\^ %/>%||s/
/  
/g+s%.%!s/.$//mg<//&&join"",//g,$/%seg+s/ /^/+y%/\\|>-%\\/\-|%for($\="/
\@
")x$_}{
Ton Hospel
la source
Impressionnant! Bon travail! Merci d'avoir contribué!
jacksonecac
0

Lot, 563 octets

@echo off
if %1==1 echo /@&echo v&exit/b
set w=1
:l
set/ah=w,a=w*w+w
if %a% gtr %1 goto g
set/aw+=1,a=w*w
if %a% leq %1 goto l
:g
call:d
set r=/%r%\
set/ae=h%%2,w=%1-h*w+2
for /l %%i in (1,1,%h%)do call:r
call:d
echo \%r%^>
exit/b
:d
set r=
for /l %%i in (3,1,%w%)do call set r=%%r%%-
exit/b
:r
echo %r:!=^|%
if %e%==0 set r=%r:@!=\/%
set r=%r:@/=\/%
set r=%r:!\=\-%
set r=%r:/@=\/%
set r=%r:/!=-/%
set r=%r:@!=\/%
set r=%r:/\=!@%
set r=%r:/-=!/%
if %e%==1 set r=%r:/\=@!%
set r=%r:/\=@/%
set r=%r:-\=\!%
if %e%==1 set r=%r:/\=/@%

Explication: Cas particuliers 1 car le reste du code nécessite une largeur de serpent d'au moins deux. Ensuite, calcule le plus grand quart de carré (soit un carré exact soit un rectangle 1 plus large que haut) dont l'aire est inférieure à la longueur du serpent. Le serpent sera enroulé dans ce rectangle à partir du coin inférieur gauche et se terminant par la queue au milieu, et la longueur restante passera sous le bas du rectangle. Le rectangle est en fait généré à partir de simples remplacements de chaînes; la plupart du temps, chaque ligne est générée à partir de la ligne précédente en déplaçant les diagonales d'un pas, mais évidemment la queue doit également être traitée, et il y a de légères différences selon que la hauteur du rectangle est paire ou impaire.

Neil
la source
Impressionnant! Merci d'avoir contribué!
jacksonecac
-1

Python 2.7, A WHOPPING 1230 octets

Je suis nouveau au python et au golf de code mais j'ai senti que je devais répondre à ma propre question et bouder de honte après le fait. Beaucoup de plaisir à y travailler!

def s(n):
x = []
l = 0
if n % 2 == 1:
    l = n
else:
    l = n + 1
if l < 3:
    l = 3
y = []
matrix = [[' ' for x in range(l)] for y in range(l)] 
slash = '\\'
newx = l/2
newy = l/2
matrix[l/2][l/2] = '@'
newx = newx-1
matrix[newx][newy] = slash
#newx = newx-1
dir = 'West'

for i in range(0, n-1):    
    newx = xloc(newx, dir)
    newy = yloc(newy, dir)
    sdir = dir
    dir = cd(matrix, newx, newy, dir)
    edir = dir

    if (sdir == 'West' or sdir == 'East') and sdir != edir:
        matrix[newx][newy] = '/'
    else:
        if (sdir == 'North' or sdir == 'South') and sdir != edir:
            matrix[newx][newy] = '\\'
        else:
            if dir == 'East' or dir == 'West':
                matrix[newx][newy] = '-'
            else:
                matrix[newx][newy] = '|'
newx = xloc(newx, dir)
newy = yloc(newy, dir)
sdir = dir
dir = cd(matrix, newx, newy, dir)
edir = dir
print 'eDir: ' + dir
if dir == 'North':
    matrix[newx][newy] = '^'
if dir == 'South':
     matrix[newx][newy] = 'v'
if dir == 'East':
     matrix[newx][newy] = '>'
if dir == 'West':
     matrix[newx][newy] = '<'    


p(matrix, l)

def cd(matrix, x, y, dir):    
if dir == 'North':
    if matrix[x][y-1] == ' ':
        return 'West'
if dir == 'West':
    if matrix[x+1][y] == ' ':
        return 'South'
if dir == 'South':
    if matrix[x][y+1] == ' ':    
        return 'East'
if dir == 'East':
    if matrix[x-1][y] == ' ':        
        return 'North'
return dir

def p(a, n):
for i in range(0, n):
    for k in range(0, n):
        print a[i][k],
    print ' '

def xloc(x, dir):
if dir == 'North':
    return x -1
if dir == 'West':
    return x
if dir == 'East':
    return x 
if dir == 'South':
    return x + 1
 def yloc(y, dir):
if dir == 'North':
    return y
if dir == 'West':
    return y - 1
if dir == 'East':
    return y + 1
if dir == 'South':
    return y

s(25)

https://repl.it/Dpoy

jacksonecac
la source
5
Cela peut être considérablement réduit simplement en supprimant les espaces inutiles, les nouvelles lignes, les commentaires, les fonctions, etc.
Addison Crump