Допустимые змеи на самолете


23

Вдохновлено одним из видео Vi Hart (которое является сокровищницей, полной потенциальных идей вызова)

Змея состоит из сегментов одинаковой длины, и соединение между каждым сегментом может быть прямым или поворачиваться на 90 °.
Мы можем закодировать такую ​​змею (с точностью до поворота, которая зависит от начального направления), записав ползунок , направление поворота (прямое / левое / правое), которое требуется. Этот, начинающийся в верхнем левом углу и указывающий направо

-+    +--+    SR    RSSR
 |  +-+  |     S  RSL  S
 +--+  --+     LSSL  SSR

Будет представлен слайд SRSLSSLRLRSSRSRSS

И, конечно же, плоская змея не может пересекать себя (как в SSSSLLLSS), что приведет к ужасной неровной игре.

Ваша задача состоит в том, чтобы определить, является ли скольжение действительным или нет (приводит по крайней мере к одному самопересечению)

Input
Строка, составленная из букв SLRс параметром 2 < length < 10000
Output
Something Truthy, если это допустимое скольжение, и что-то Falsey, если это не так.

Контрольные примеры

__Valid__
SSLSLSRSRSSRSSSLLSSSRRLRSLRLLSSS
SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR (A hilbert curve)
RLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRR
SRRSRSRSSRSSRSSSRSSSRSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS (Spiral)
SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS (bigger, squigglier spiral)
LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLL

__Invalid__
SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR
SRRLSLLRRLLSLRRSRLLRSRRLLSRSSSRSSSSSSSRSRSSSSSSSRRLLRRSRLLRSRRLSLLRRLLSLRR
SRRSRSRSSRSSRSSSRSSSRSSSSSSSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS
SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLRLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS
LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLLSLRLSLRSLRSLRSLSLSLRSRLSLRSLRLSRSLLLRLRLRRRRSLSLSSLLSLSLSLSSLLSLSLLRLRSLLRSRLSLSSLLLLSSSSSSSSSSSSSSSSSSSSRLRLLRRLRLRLLRLRLRLRLRLSSSSLSLRLLRLSLSSLSLSLSLSLRLLRLSLLLSRSSSSSSSSSSSSSSSRLRLRLLRLRLSLSRSRSSSLSRLRLRLRSLSLSLSRLLSRLSLSLSLSLSSLSLSLLSLSRLLRLRLRLRLRLRLRLRLRLRLSLSRLRLSLLRRLSLLSLSLSLSLSLLSLSLSLRLRLRLRLRLRLRLRLRLRRLRSLSLSLSLSLSLSLSSLSSSSSLSLSSSLSLSLSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS

Вы можете нарисовать ползунки здесь (R и L перевернуты, но это не влияет на достоверность)


Нужно ли вводить данные в программе или их можно прочитать из файла?
МИ Райт

1
Должна ли SRRR быть верной или ложной? Он соединяется, но не пересекается.
orlp

трогательные змеи бросают вызов NSFW?
Эван

3
если вы рисуете SRRRна миллиметровой бумаге один квадрат на сегмент, то он будет перекрываться и, следовательно, будет недействительным, просто RRRбудет занимать ровно квадрат 2х2 без перекрытий (как в классической игре)
DenDenDo

Аналогично, но не дубликат (из-за разных целей и разных правил построения).
трихоплакс

Ответы:


20

Pyth, 22 20 байт

ql{m+=Z*=T^.j)hCdzlz

Попробуйте сами или запустите тестовый пакет .

Обратите внимание на значения ASCII SRL соответственно 83, 76, 82. Я злоупотребляю тем фактом, что:

i 83 + 1 = 1
i 76 + 1 = i
i 82 + 1 = -i

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

В конце я проверяю, все ли посещенные позиции уникальны.


SRRR = правда ????
Эван

@Ewan При ближайшем рассмотрении - я не уверен, должно ли это быть ложным или нет. Голова и хвост соединяются, но не пересекаются.
orlp

как насчет SRRRS?
Эван

@Ewan Та же история - связь, но нет пересечения. Вопрос не ясен, что за них нужно вернуть.
orlp

1
как бы вы нарисовали SRRR?
Эван

6

CJam, 30 байтов

q{iF%U+:U[XWe4W1e4]=T+:T}%__&=

Объяснение, чтобы следовать скоро.

Попробуйте онлайн здесь или запустите весь пакет .


Черт, это было быстро. Я даже не думал об алгоритме, чтобы решить его сам.
DenDenDo

SRRRS = правда ???
Эван

@ Иван ммм, мы предполагаем, что 0 изначально заполнен и считается?
Оптимизатор

1
Я предполагаю, что я интерпретирую это как игру змеи, где движения занимают блоки пространства. и некоторые из вас, ребята, интерпретируют это как линию нулевой ширины
Ewan

@ Иван Хотя мой вопрос немного другой. Скажем S, если у нас есть один ход, значит ли это, что змея уже заняла (0,0) и (1,0)?
Оптимизатор

6

JavaScript (ES6), 84 89

Запустите сниппет в Firefox для проверки.

Некоторые заметки:

  • змея движется внутри массива f. Непосещенные ячейки имеют значение undefined. При первом посещении оператор тильды меняет его на -1, что правда. В конце концов, при втором посещении значение изменяется на 0, что ложно, и everyцикл прекращает возвращать false.
  • в JS элементы массива с неканоническими индексами (не числовыми или отрицательными) как-то «скрыты», но они существуют. Здесь я использую отрицательные показатели без проблем.

F=s=>[...s].every(c=>f[p+=[1,1e5,-1,-1e5][d=d+{R:1,L:3,S:0}[c]&3]]=~f[p],d=p=0,f=[])

//TEST
$('#S').on('keyup mouseup change', Draw);

function Draw(){
  var s = S.value.toUpperCase();
  if (!s) {
    C.width = C.height = 0;
    return
  }
  C.width = 600;
  C.height = 400;
  
  var ctx = C.getContext("2d");  
  var px, py, int=0;
  
  ctx.strokeStyle = '#008';
  ctx.lineWidth = 2;
  ctx.translate(300,200);
  ctx.beginPath();
  ctx.moveTo(0,0);
  
  [...s].forEach(c=>{
    (f[p+=[1,1e4,-1,-1e4][d=d+{R:1,L:3,S:0}[c]&3]]=~f[p])
    ? 1 
    : (++int)
    if (int==1) ctx.stroke(), ctx.strokeStyle = '#800', ctx.beginPath(), ctx.moveTo(10*px,10*py);
    
    py = (p / 1e4 | 0) - 5e3;
    px = (p % 1e4) -5e3
    ctx.lineTo(10*px, 10*py);
  }, d=0,p=50005000,f=[]);
  ctx.stroke();
  
}

valid=["SSLSLSRSRSSRSSSLLSSSRRLRSLRLLSSS",
"SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR",
"RLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRRSRLLRSRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLSSLLRSRRLLRR",
"SRRSRSRSSRSSRSSSRSSSRSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS",
"SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS",
"LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLL"];
invalid=["SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR",
"SRRLSLLRRLLSLRRSRLLRSRRLLSRSSSRSSSSSSSRSRSSSSSSSRRLLRRSRLLRSRRLSLLRRLLSLRR",
"SRRSRSRSSRSSRSSSRSSSRSSSSSSSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS",
"SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLRLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS",
"LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLLSLRLSLRSLRSLRSLSLSLRSRLSLRSLRLSRSLLLRLRLRRRRSLSLSSLLSLSLSLSSLLSLSLLRLRSLLRSRLSLSSLLLLSSSSSSSSSSSSSSSSSSSSRLRLLRRLRLRLLRLRLRLRLRLSSSSLSLRLLRLSLSSLSLSLSLSLRLLRLSLLLSRSSSSSSSSSSSSSSSRLRLRLLRLRLSLSRSRSSSLSRLRLRLRSLSLSLSRLLSRLSLSLSLSLSSLSLSLLSLSRLLRLRLRLRLRLRLRLRLRLRLSLSRLRLSLLRRLSLLSLSLSLSLSLLSLSLSLRLRLRLRLRLRLRLRLRLRRLRSLSLSLSLSLSLSLSSLSSSSSLSLSSSLSLSLSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"];

V.innerHTML=valid.map(s=>F(s)+' '+s).join('\n')
I.innerHTML=invalid.map(s=>F(s)+' '+s).join('\n')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Type to check and draw <input id=S>
(better full page)<br>
<canvas id=C width=1 height=1 ></canvas><br>
Valid<pre id=V></pre>
Invalid<pre id=I></pre>


6

TI-BASIC, 49 56 53 51 байт

abs(e^(i)-cumSum(i^cumSum(seq(inString("SL",sub(Ans,X,1))-1,X,1,length(Ans→X
SortA(∟X
min(ΔList(∟X

Подобно методу orlp, это создает список всех точек в комплексной плоскости, которые посетила змея, начиная с начала координат. Если в списке нет повторяющихся элементов, код возвращает некоторое положительное значение. Обратите внимание, что на строке из более чем 999 элементов калькулятор не сможет сгенерировать достаточно длинный список и выдаст ошибку.

РЕДАКТИРОВАТЬ: Сохранены два байта ценой уродства, поскольку никакие две точки решетки на комплексной плоскости не могут быть на одинаковом расстоянии от e ^ i.


5

TI-BASIC, 60 58 байт

Изменить: игнорировать все ниже: рабочее решение ti-basic здесь , Томас Ква. Иди, проголосуй за это!

это [(-)]ключ, а Анс есть [2ND]->[(-)]. Запустите его, заключив инструкции змеи в кавычки ( [ALPHA]->[+]), затем двоеточие и имя программы. Например, если вы назовете программу «SNAKE», вы запустите контрольный пример в OP как "SRSLSSLRLRSSRSRSS":prgmSNAKE.

seq(inString("SRL",sub("0"+Ans,I,1)),I,1,length(Ans
Disp 0<sum(⁻1+2seq(Ans(I)≠(Ans(I-1),I,2,dim(Ans

Изменить: не работает SRRLSLLRRRS. У меня есть пересмотренная версия на 61 байт, но она не проходит в первом неверном тестовом примере:

seq(inString("SRL",sub("0"+Ans,I,1)),I,1,length(Ans
cumSum(⁻1+2seq(Ans(I)≠(Ans(I-1),I,2,dim(Ans
Disp 0<Ans(dim(Ans

Я постараюсь исправить завтра.


Обновление: проблема в том, что мой алгоритм имеет недостатки. Если бы я использовал For (цикл в отличие от seq ((для достижения того же самого)), его (на самом деле оба алгоритма выше) можно было бы описать так:

  1. Инициализируйте переменную счетчика равной 1.
  2. Прочитайте строку. Если символ изменится, увеличьте значение переменной счетчика. Если символ повторяется, уменьшите его.
  3. Если переменная счетчика больше 0, отобразите 1 (действительный). В противном случае отображается 0 (недействительно).

Тем не менее, это не удается на недопустимых скольжения, как SRLRLRLRLRRRSS. Сейчас я попытаюсь придумать лучший алгоритм ... или украсть другой ответ.


Я на 90% уверен, что это можно заменить одной seq(командой, на самом деле, но пока это настолько мало, насколько я могу это понять. Если вы намереваетесь построить его на 8xp, используя Sourcecoder, а не печатать его, обратите внимание, что его следует заменить на, !=а ⁻1+бит - заменить ~1+.


1

Рубин 87 89

F=->s{d=[1,w=1e4,-1,-w]
v=[w]+s.chars.map{|c|w+=d.rotate!(c<?R?-1:c>?R?0:1)[0]}
v==v&v}

Онлайн тест: http://ideone.com/pepeW2

Безголовая версия:

F = -> input {
  # Coordinates are expressed using one number,
  # that is computed using the formula `y + x*max_x`.
  # Assume max horizontal field width (max_x) to be 10000,
  # since that's the max length of the input.
  position = max_x = 1e4

  # These are possible directions to move to (coordinate deltas).
  # The current direction is always the first in the array.
  directions = [1,max_x,-1,-max_x]

  visited = [position]

  visited += input.chars.map{|c|
    # adjust current direction...
    directions.rotate! case c
    when ?L
      -1
    when ?R
      1
    when ?S
      0
    end

    # ...and move there
    position += directions[0]
  }

  # Return `true` if `visited` only contains distinct elements, `false` otherwise
  visited == visited & visited
}

0

Golfscript 48 49 50

[10.4?:z-10z~)]z*z@{'R L S'?@>(@+.`n}%n/@;\;..&=

Ожидает, что строка существует в стеке и возвращает либо 0или 1.

Вы можете попробовать это онлайн с тестами на действительных и недействительных змей.

По сути, это та же идея, что и в моем ответе на Ruby . Просто с массивом направлений обрабатываются по-разному, потому что AFAIK Golfscript не имеет функции обычного поворота. В этом случае я создаю достаточно большой массив направлений, умножая его 10000 раз, а затем обрезая от его начальных 0, 1 или 3 элементов, в зависимости от текущей команды (S, R или L). Текущее «направление» для перемещения всегда является первым элементом в массиве.

Вот это с комментариями:

# Build the direction array and set current position
[1 10000:z-1z~)]z*z

@{
  # For each character in the input:

  # set current direction by cutting 0, 1 or 3 elements 
  # from the beginning of the directions array
  'SR L'?
  @>

  # move to current direction
  .0=@+.

  # format as number and addd newline
  `n
}%

# split by newlines
n/

# cleanup
@;\;

# return 1 if array contains distinct elements, 0 otherwise
..&=

Редактировать:

Сохранено 1 символ путем изменения способа использования массива "directions".

Редактировать:

сохранил 1 символ, переместив шаг 10 вместо 1, чтобы использовать ?синтаксис (power).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.