Дійсні змії в літаку


23

Натхненний одним із відео Ві Харт (які є скарбницею, сповненою потенційних ідей)

Змія складається з сегментів однакової довжини, і з'єднання між кожним сегментом може бути прямим або робити поворот на 90 °.
Ми можемо кодувати таку змію (аж до обертання, що залежить від початкового напрямку), записавши шліц , напрямок поворотів (Прямий / Лівий / Правий), який він займає. Цей, починаючи вгорі ліворуч і вказуючи праворуч

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

Була б представлена ​​щілиною SRSLSSLRLRSSRSRSS

І звичайно, планарна змія не може перетинатися (як у SSSSLLLSS), що призведе до жахливої ​​нерівної гри.

Ваше завдання - визначити, чи дійсний шліфер чи ні (виходить принаймні один самоперехрест)

Введення
Рядок, зроблений з букв SLRіз 2 < length < 10000
виведенням
чогось правдоподібного, якщо це дійсний слайтер і щось Фальсі, якщо його немає.

Тестові справи

__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 = вірно ???
Еван

@Ewan umm, чи вважаємо ми, що 0 спочатку заповнюється і рахується?
Оптимізатор

1
Я думаю, що я трактую це як гру в змію, де ходи займають блоки простору. а деякі з вас, хлопці, інтерпретують це як нульову ширину
Еван

@Ewan Моє запитання дещо інше. Скажімо S, коли ми маємо один крок, це означає, що змія вже зайняла і (0,0), і (1,0)?
Оптимізатор

6

JavaScript (ES6), 84 89

Запустіть фрагмент у Firefox для тестування.

Деякі примітки:

  • змія рухається всередині масиву f. Невизначені клітини мають значення undefined. Під час першого відвідування оператор тильди змінює його на -1, що є правдою. Зрештою, під час другого відвідування значення змінюється на 0, яке є хибним іevery цикл припиняє повернення помилковим.
  • в 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

Подібно до методу орлпа, це створює перелік усіх точок у складній площині, яку відвідує змія, починаючи з початку. Якщо у списку немає повторюваних елементів, код повертає деяке позитивне значення. Зауважте, що в рядку з більш ніж 999 елементів калькулятор не зможе генерувати досить довгий список і помилиться.

EDIT: Збережені два байти ціною потворності, оскільки жодна точка решітки на складній площині не може знаходитися на однаковій відстані від e ^ i.


5

TI-BASIC, 60 58 байт

Edit: Ігнорувати все нижче: а ти-базисне рішення робочого знаходиться тут , на томас-кВА. Ідіть, підкресліть це!

- це [(-)]ключ, а Ans - це [2ND]->[(-)]. Запустіть його, додавши вказівки змії в лапки ( [ALPHA]->[+]), а потім двокрапка, а потім назва програми. Наприклад, якщо ви назвали програму "SNAKE", ви б запустили тестовий випадок в ОП як "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

Гольфскрипт 48 49 50

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

Очікує, що рядок існує в стеці і повертає або 0або 1.

Ви можете спробувати його в Інтернеті з тестами на дійсні та недійсні змії.

Це в основному та сама ідея, що і в моїй відповіді Рубі . Просто масив напрямків розглядається по-різному, тому що 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 знак, змінивши спосіб використання масиву "вказівки".

Редагувати:

врятував 1 знак, переміщуючи з кроком 10 замість 1, щоб використати ?(силовий) синтаксис.

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