pssssssssssssst

31

Einführung

Dies ist eine ziemlich unkomplizierte. Wir werden eine Schlange in ASCII zeichnen. Dies wurde von dem alten Schlangenspiel inspiriert, bei dem man die Früchte einsammeln und kontinuierlich wachsen muss.

Definition

Zeichnen Sie bei einer positiven ganzen Zahl N, die die Länge der Schlange angibt, eine Schlange so, dass sie einen Körper von n sowie einen Kopf und einen Schwanz hat.

Teile:

  • Kopf: <, >, ^, v
  • Schwanz: @
  • Vertikale: |
  • horizontal: -

Alle Ecken sollten mit einem \bzw. zufrieden sein /. Es sei denn, der Kopf endet an einer Ecke. In diesem Fall hat der Kopf <, >, ^, vVorrang in der Richtung, in der sich die Schlange kräuselt. dh für das Beispiel mit der Länge 1 wird es gegen den Uhrzeigersinn gedreht und so wird der Kopf auf diese Weise gedreht. Für eine Lösung im Uhrzeigersinn wäre es rechts >.

Die Schlange muss in der Mitte mit ihrem Schwanz beginnen, kann aber in jede Richtung nach außen gehen, die Sie entweder im oder gegen den Uhrzeigersinn wählen. Es muss sich auch eng um sich selbst wickeln, da es sich kreisförmig nach außen ausdehnt.

Beispiel

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

Wo @ist der Schwanz und Startposition. Wie oben zu sehen, beginnt der Schwanz in der Mitte und steigt nach links gegen den Uhrzeigersinn nach außen.

Hier ist die Länge 19plus ein Schwanz und ein Kopf.

Als weiteres Beispiel ist hier die Länge 1:

<\
 @

Gewinnen

Dies ist Codegolf, daher gewinnt die Antwort mit der geringsten Anzahl von Bytes mit der Zeit, um als Bindungsunterbrecher verwendet zu werden.

Habe Spaß!

jacksonecac
quelle
2
Es ist nicht ganz klar, dass ich nicht nur eine gerade Schlange zeichnen darf @---->. Sie beabsichtigen wahrscheinlich strengere Bedingungen bezüglich der Schlangenform. Machen Sie auch deutlich, wie viel Leerzeichen zulässig sind oder nicht
Ton Hospel
1
"Die Schlange muss in der Mitte mit dem Schwanz beginnen, aber sie kann in jede beliebige Richtung nach außen gehen und entweder im oder gegen den Uhrzeigersinn"
jacksonecac
1
Also sage ich, @ist die Mitte (eventuell Leerzeichen hinzufügen, um es so zu machen), "rechts" als Richtung deklarieren und nur mit dem Kopf nach unten zeigen und dies im Uhrzeigersinn deklarieren. Ihre Begriffe mögen Ihnen klar erscheinen, aber sie sind tatsächlich mehrdeutig. Mir ist klar, dass Sie wahrscheinlich eine so eng wie möglich zusammengerollte Schlange meinen, aber das sollten Sie
klarstellen
1
Mach dir keine Sorgen. Das ist viel schwieriger aufgrund der Versätze in dieser Herausforderung.
Martin Ender
2
Schöne erste Herausforderung! Willkommen auf der Seite!
Luis Mendo

Antworten:

10

MATL , 85 83 Bytes

Und ich dachte, ein spiraleingebauter Code würde zu einem kurzen Code führen ...

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

Probieren Sie es online!

Erläuterung

Sei N bezeichnen die Eingabe. Wir werden einen Längenvektor erzeugen ceil(sqrt(N+2))^2, dh das kleinste perfekte Quadrat, das gleich oder größer als N +2 ist. Dieser Vektor wird mit numerischen Werten gefüllt, zu einer Spirale gerollt (daher muss seine Länge ein perfektes Quadrat sein), und dann werden die numerischen Werte durch Zeichen ersetzt.

Lassen n jeden Schritt von 1 bezeichnen in der Mitte der Spirale beginnt. Die Schritte, in denen sich die Schlange dreht, sind durch n 2 +1 (das heißt: 2, 5, 10, ...) für \Symbole und n 2 + n +1 (das heißt: 3, 7, 13, ...) gegeben. für /. Die Schritte zwischen a \und a /sollten sein -, und die zwischen a /und a\ sollten sein |.

Der Vektor wird so erstellt, dass er 1an den Wendepunkten (2,3,5,7,10,13 ...) und 0im Rest enthält. Die Parität der kumulativen Summe gibt an, ob jeder Eintrag ein -oder ein sein soll |. Addiert man 1 zu diesem Ergebnis, erhält man einen Vektor, der 1(für |) oder 2(für -) enthält. Aber das macht die Wendepunkte selbst zu 1oder 2zu. Die Wendepunkte, deren Positionen wir kennen, werden also überschrieben: Positionen n 2 +1 werden mit 3und Positionen n 2 + n +1 werden mit gefüllt 4. Der Schwanz und der Kopf sind ebenfalls Sonderfälle: Das erste Element des Vektors (Schwanz) wird auf +2 (Kopf) gesetzt5 und das Element mit dem Index N gesetzt6. Schließlich werden Elemente mit Indizes über N +2 auf gesetzt0 .

Am Beispiel der Eingabe N = 19 haben wir nun einen Vektor mit der Länge 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

Wir müssen diesen Vektor in eine Spirale rollen. Dazu verwenden wir eine eingebaute Funktion, die eine Spiralmatrix erzeugt, gefolgt von einer Reflexion und einer Transposition, um Folgendes zu erzeugen:

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 

Indizieren des Vektors mit der Matrix ergibt

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

wo 0entspricht Raum 1entspricht |, 2um -, 3um \, 4auf /, 5zu @, und6 auf den Kopf.

Um zu wissen , welche die vier Zeichen ^, <, v, oder >der Kopf haben sollte, verwenden wir die kumulative Summe von Wendepunkten , dass wir vorher berechnet. Insbesondere gibt der vorletzte Wert dieser kumulativen Summe (dh der N + 1-te Wert) Modulo 4 an, welches Zeichen für den Kopf verwendet werden soll. Wir nehmen den vorletzten Wert der kumulativen Summe, nicht das letzte Mal, wegen der Anforderung „ wenn die Kopfenden an einer Ecke der Kopf <, >, ^, vPriorität in Richtung nimmt die Schlange zusammengerollt“. Für das Beispiel N = 19 ist der Kopf >.

Jetzt können wir eine Zeichenfolge , die alle die Schlange Zeichen, einschließlich der entsprechenden Zeichen für den Kopf an der sechsten Position bauen: '|-\/@> '. Wir indizieren diese Zeichenfolge dann mit der obigen Matrix (die Indizierung basiert auf 1 und ist modular, damit der Platz an letzter Stelle bleibt), was ergibt

/--\ 
|/\| 
||@| 
|\-/ 
\--->
Luis Mendo
quelle
1
beeindruckende Arbeit! danke fürs mitmachen!
Jacksonecac
8

Python 2, 250 233 191 Bytes

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 Bytes dank @JonathanAllan eingespart

repl.it

Zeichnen Sie die Schlange, indem Sie die gesamte Schlange um 90 ° im Uhrzeigersinn drehen und das untere Segment hinzufügen. Auf diese Weise befindet sich die Schlange immer im Gegenuhrzeigersinn.
Das neue Segment beginnt immer mit \und hat -als Körper selbst für Seiten und / -für ungeradee Seiten. Die Segmente Größen (ohne Ecken) sind 0, 1, 1, 2, 2, 3... , die ist floor(side/2).
Wenn das Segment das letzte ist, werden die überschüssigen Zeichen entfernt, der Kopf hinzugefügt und Leerzeichen hinzugefügt.

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)
Stange
quelle
Gute Arbeit! Sie haben den Tiebreaker-Sieg. Mal sehen, was sich die Leute sonst noch einfallen lassen.
Jacksonecac
2
Dies ist sicherlich die ideale Sprache, um diese Herausforderung zu lösen.
Neil
+1. Der einzige Nachteil ist, dass der Kopf, wenn er sich in einer Ecke befindet, gerade und nicht um die Ecke zeigen soll.
Jonathan Allan
1
Speicher 16 Bytes , die durch die Indizierung in Strings in etwa so: '\/'[m], '-|'[m]und'>v'[m]
Jonathan Allan
1
Speichern Sie 1 weitere, indem Sie das Leerzeichen zwischen printund entfernen''.join
Jonathan Allan
7

JavaScript (ES6), 193 201 203 215 220 224

Bearbeiten gespeichert 4 thx @Arnauld Bytes
EDIT2 geändert Logik, nicht die aktuellen Schritten für x und y zu speichern, nur um sie von der aktuellen Richtung erhalten
Edit3 ein paar Bytes gespeichert zu haben, habe ich beschlossen , sie für eine bessere Verwaltung des leeren Raum zu verwenden
Edit4 8 Bytes gespart, die nicht genau den Beispielen zur Kopfrichtung folgen - wie andere Antworten

Die aktuelle Version funktioniert mit Chrome, Firefox und MS Edge

Diese Antwort gibt einige nachgestellte und führende Leerzeichen (und Leerzeilen).

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

Etwas weniger golfen

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
quelle
Sie können ein paar Bytes sparen, indem Sie (' ')mit ` ` und ('@')durch`@`
Arnauld
@ Arnauld Array (2) .fill `` ==> [ Array[1], Array[1] ], während Array(2).fill(' ')==>[' ',' ']
Usandfriends
@ usandfriends - Stimmt. Aber das sollte keinen Unterschied machen, wenn man erst einmal dabei ist.
Arnauld
@Arnauld Zuerst habe ich mit usandfriends abgestimmt, aber es funktioniert in der Tat. Danke
edc65
@ TravisJ Es funktioniert nicht in Chrome, aber Firefox scheint zu funktionieren.
Adnan
3

JavaScript (ES7), 200 Byte

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

ES6-Version für einfache 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
quelle
Interessante Umsetzung. Ich hatte nicht daran gedacht, das zu tun. Vielen Dank für Ihren Beitrag und gute Arbeit!
Jacksonecac
3

Perl, 111 - 110 Bytes

Beinhaltet +1 für -p

Gib die Größe auf STDIN an

snake.pl:

#!/usr/bin/perl -p
s%> %->%+s%\^ %/>%||s/
/  
/g+s%.%!s/.$//mg<//&&join"",//g,$/%seg+s/ /^/+y%/\\|>-%\\/\-|%for($\="/
\@
")x$_}{
Tonne Hospel
quelle
Genial! Gute Arbeit! Vielen Dank für Ihren Beitrag!
Jacksonecac
0

Batch, 563 Bytes

@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:/\=/@%

Erläuterung: Sonderfälle 1 wie der Rest des Codes erfordern eine Schlangenbreite von mindestens zwei. Berechnet als Nächstes das größte Viertelquadrat (entweder ein genaues Quadrat oder ein Rechteck 1, das breiter als hoch ist), dessen Fläche kleiner als die Länge der Schlange ist. Die Schlange wird in dieses Rechteck gewickelt, beginnend in der unteren linken Ecke und endend mit dem Schwanz in der Mitte, und die verbleibende Länge wird unter dem Boden des Rechtecks ​​verlaufen. Das Rechteck wird tatsächlich durch einfaches Ersetzen von Zeichenfolgen generiert. Die meiste Zeit wird jede Linie aus der vorherigen Linie erzeugt, indem die Diagonalen um einen Schritt verschoben werden. Natürlich muss auch der Schwanz behandelt werden, und es gibt leichte Unterschiede, je nachdem, ob die Höhe des Rechtecks ​​gerade oder ungerade ist.

Neil
quelle
Genial! Vielen Dank für Ihren Beitrag!
Jacksonecac
-1

Python 2.7, A WHOPPING 1230 Bytes

Ich bin neu im Python- und Codegolf, aber ich hatte das Gefühl, ich musste meine eigene Frage beantworten und mich schämen. Viel Spaß beim Arbeiten!

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
quelle
5
Dies kann massiv reduziert werden, indem unnötige Leerzeichen, Zeilenumbrüche, Kommentare, Funktionen usw. entfernt werden.
Addison Crump