pssssssssssssst


31

Вступ

Це одне досить просто. Ми будемо малювати змію в асці. На це надихнула та стара гра-змія, де вам потрібно збирати плід і ви постійно зростаєте.

Визначення

Давши додатне ціле число N, яке відображає довжину змії, намалюйте змію таким чином, щоб вона мала тіло n плюс голову та хвіст.

Частини:

  • голова: <, >, ^, v
  • хвіст: @
  • вертикальний: |
  • горизонт: -

Усі куточки повинні бути задоволені \або /відповідно. Якщо голова не закінчується на куті, в цьому випадку голова надає <, >, ^, vпріоритет у напрямку, як змія згорнулася. тобто для прикладу довжини 1, він повернутий проти годинникової стрілки, і голова повернута таким чином. Для рішення за годинниковою стрілкою це було б праворуч >.

Змія повинна починатися посередині хвостом, але вона може виходити назовні в будь-якому напрямку, обраному вами або проти годинникової стрілки. Він також повинен щільно обмотатися навколо себе, оскільки він розширюється назовні круговим способом.

Приклад

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

Де @- хвіст і вихідне положення. Як видно вище, хвіст починається посередині, піднімається ліворуч у напрямку обертання проти годинникової стрілки назовні.

Тут довжина 19плюс хвіст і голова.

Як інший приклад, ось довжина 1:

<\
 @

Перемога

Це кодовий гольф, тому відповідь, що подається з найменшою кількістю байтів, виграє, з часом використовуючись як переривник тайму.

Веселіться!


2
Не дуже зрозуміло, що мені не просто дозволено малювати прямо змію @---->. Ви, мабуть, маєте намір більш жорсткі умови щодо форми змії. Також
уточнюйте,

1
"Змія повинна починатися посередині хвостом, але вона може виходити назовні в будь-якому
обраному

1
Тому я кажу, що @це середина (можна додати пробіли, щоб зробити це так), оголосити "праворуч" як напрямок і зробити лише голову вниз і оголосити це за годинниковою стрілкою. Ваші умови можуть здатися вам зрозумілими, але насправді вони неоднозначні. Я усвідомлюю, що ви, мабуть, маєте на увазі якомога щільніше згорнуту змію, але вам слід це зрозуміти
Тон Євангелія

1
Не хвилюйся. Це набагато важче через компенсації в цьому виклику.
Мартін Ендер

2
Приємний перший виклик! Ласкаво просимо на сайт!
Луїс Мендо

Відповіді:


10

MATL , 85 83 байти

І я подумав, що наявність spiralвбудованого коду буде коротким кодом ...

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

Спробуйте в Інтернеті!

Пояснення

Нехай N позначає вхід. Ми створимо вектор довжини ceil(sqrt(N+2))^2, тобто найменший досконалий квадрат, який дорівнює або перевищує N +2. Цей вектор буде заповнений числовими значеннями, згортається в спіраль (тому його довжина повинна бути ідеальним квадратом), а потім числові значення будуть замінені символами.

Нехай n позначає кожен крок, починаючи з 1 в центрі спіралі. Етапи, на яких оберти змії задані n 2 +1 (тобто 2, 5, 10, ...) для \символів та n 2 + n +1 (тобто: 3, 7, 13, ...) для /. Кроки між a \і a /повинні бути -, а кроки між a /і a \повинні бути |.

Вектор створюється таким, що він міститься 1у точках повороту (2,3,5,7,10,13 ...) та 0в решті. Паритет сукупної суми вказує, чи має бути кожен запис а -чи a |. Додаючи до цього результату 1, отримуємо вектор, що містить 1(для |) або 2(для -). Але це робить самі поворотні точки ставати 1чи 2занадто. Тож точки повороту, позиції яких ми знаємо, переписуються: позиції n 2 +1 заповнюються, 3а позиції n 2 + n +1 заповнюються 4. Хвіст і голова - це також особливі випадки: перший елемент вектора (хвіст) встановлений на 5, а елемент з індексом N+2 (голова) встановлено на 6. Нарешті, встановлюються елементи з індексами, що перевищують N +2 0.

Взявши для прикладу вхід N = 19, тепер у нас є вектор довжиною 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

Нам потрібно згорнути цей вектор у спіраль. Для цього ми використовуємо вбудовану функцію, яка генерує спіральну матрицю з подальшим відбиттям і транспозицією для отримання:

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 

Індексація вектора за допомогою матриці дає

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

де 0відповідає простору, 1відповідає |, 2щоб -, 3щоб \, 4щоб /, 5щоб @, і 6до голови.

Щоб дізнатися , який з чотирьох символів ^, <, vабо >голова повинна мати, ми використовуємо накопичену суму в свою чергу вказує , що ми раніше обчисленого. Зокрема, друге-останнє значення цієї сукупної суми (тобто N + 1-е значення) за модулем 4 вказує нам, який символ слід використовувати для голови. Ми передостаннє значення накопиченої суми, не остання, з - за вимоги «якщо голова закінчується на вугіллі голова <, >, ^, vмає пріоритет в напрямку змія завитий». Для прикладу N = 19 голова >.

Тепер ми можемо побудувати рядок , що містить всі символи змії, в тому числі відповідного символу для голови на шостій позиції: '|-\/@> '. Потім індексуємо цей рядок вищевказаною матрицею (індексація заснована на 1 та модульній, тому простір залишається останнім), який дає

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

1
дивовижна робота! дякую за участь!
jacksonecac

8

Python 2, 250 233 191 байт

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 байт завдяки @JonathanAllan

repl.it

Намалюйте змію, обертаючи всю змію на 90 ° за годинниковою стрілкою і додавши нижній сегмент, таким чином змія завжди буде проти годинникової стрілки.
Новий сегмент завжди буде починатися з \і матиме -як корпус для парних, так і / -для непарних сторін. Розміри сегментів (без кутів) є 0, 1, 1, 2, 2, 3... якийfloor(side/2) .
Якщо сегмент останній, він видаляє зайві символи, додає голову та доповнює пробіли.

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)

Хороша робота! у вас є виграш тайбрейка. Давайте подивимось, що ще люди придумують.
jacksonecac

2
Звичайно, це ідеальна мова для вирішення цього завдання.
Ніл

+1. Тільки глюк полягає в тому, що коли голова знаходиться на куті, вона має на увазі прямо, а не за кутом.
Джонатан Аллан

1
Зберегти 16 байт по індексації в рядки , як так: '\/'[m], '-|'[m]і'>v'[m]
Джонатан Allan

1
Збережіть ще 1, видаливши пробіл між printі''.join
Джонатан Аллан

7

JavaScript (ES6), 193 201 203 215 220 224

Змінити збережені 4 байти thx @Arnauld
Edit2 змінив логіку, не зберігаючи поточні кроки для x та y, просто
дістаньте їх із поточного напрямку Edit3 , збереживши кілька байтів, я вирішив використовувати їх для кращого управління порожнім простором
Edit4 8 збережені байти, не дотримуючись точно прикладів щодо напрямку голови - як і інші відповіді

Поточна версія працює з Chrome, Firefox та MS Edge

Ця відповідь дає деякий кінцевий та провідний простір (та порожні рядки).

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

Трохи менше гольфу

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>


Ви можете заощадити кілька байт, замінюючи (' ')з ` ` і ('@')з`@`
Arnauld

@Arnauld Array (2) .fill `` ==> [ Array[1], Array[1] ], а Array(2).fill(' ')==>[' ',' ']
usandfriends

@usandfriends - Правда. Але це не повинно мати жодних змін, коли приєднаємось.
Арнольд

@Arnauld спочатку я погодився з usandriends, але це справді працює. Дякую
edc65

@TravisJ Це не працює в Chrome, але, здається, Firefox працює.
Аднан

3

JavaScript (ES7), 200 байт

(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 для зручності тестування:

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>


Цікава реалізація. Я не думав цього робити. Дякуємо за внесок у роботу та приємну роботу !!
jacksonecac

3

Перл, 111 110 байт

Включає +1 для -p

Надати розмір на STDIN

snake.pl:

#!/usr/bin/perl -p
s%> %->%+s%\^ %/>%||s/
/  
/g+s%.%!s/.$//mg<//&&join"",//g,$/%seg+s/ /^/+y%/\\|>-%\\/\-|%for($\="/
\@
")x$_}{

Дивовижно! Хороша робота! Дякуємо за ваш внесок!
jacksonecac

0

Пакетна, 563 байти

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

Пояснення: Особливі випадки 1, оскільки решта коду вимагає ширини змії не менше двох. Далі обчислюється найбільша чверть квадрата (точний квадрат або прямокутник на 1 ширший, ніж високий), площа якого менша за довжину змії. Змія буде згорнута в цей прямокутник, починаючи з нижнього лівого кута і закінчуючи хвостом посередині, а решта довжини буде проходити під нижньою частиною прямокутника. Прямокутник насправді генерується за допомогою простих замін рядків; більшу частину часу кожен рядок генерується з попереднього рядка, переміщуючи діагоналі на 1 крок, але очевидно, з хвостом також доводиться боротися, і є невеликі відмінності залежно від того, висота прямокутника парна чи непарна.


Дивовижно! Дякуємо за ваш внесок!
jacksonecac

-1

Python 2.7, налічує 1230 байт

Я новачок у пітоні та гольф-коді, але я відчув, що мені доведеться відповісти на власне запитання та соромно відмовитись від факту. Дуже весело, працюючи над цим, хоча!

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


5
Це можна масово зменшити, видаливши зайві пробіли, нові рядки, коментарі, функції тощо.
Addison Crump
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.