pssssssssssssst


31

Введение

Это один довольно простой. Мы будем рисовать змею в ascii. Это было вдохновлено той старой игрой со змеями, где вы должны собирать фрукты и постоянно расти.

Определение

Учитывая положительное целое число N, которое представляет длину змеи, нарисуйте змею так, чтобы у нее было тело n плюс голова и хвост.

Части:

  • голова: <, >, ^, v
  • хвост: @
  • по вертикали: |
  • Horizonal: -

Все углы должны быть удовлетворены \или /соответственно. Если голова не заканчивается на углу, в этом случае голова <, >, ^, 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, ...) для /. Шаги между а \и а /должны быть -, а между а /и а \должны быть |.

Вектор создается так, что он содержит 1в точках поворота (2,3,5,7,10,13 ...) и 0в остальных. Соотношение совокупной суммы говорит, должна ли каждая запись быть -или |. Добавляя 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 сначала я согласился с нами и друзьями, но это действительно работает. Спасибо
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

Perl 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, WHOPPING 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.