Cobras válidas em um avião

23

Inspirado em um dos vídeos de Vi Hart (que é um tesouro cheio de possíveis idéias para desafios)

Uma cobra é composta de segmentos do mesmo comprimento e a conexão entre cada segmento pode ser reta ou fazer uma curva de 90 °.
Podemos codificar uma cobra (até uma rotação, que depende da direção inicial), anotando um slither , a direção das curvas (Reta / Esquerda / Direita) necessárias. Este, começando no canto superior esquerdo e apontando para o direito

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

Seria representado pelo slither SRSLSSLRLRSSRSRSS

E é claro que uma cobra planar não pode se cruzar (como em SSSSLLLSS), isso resultaria em um Game Over horrível e pixelizado.

Sua tarefa é determinar se um slither é válido ou não (resulta em pelo menos uma interseção automática)

Entrada
Uma string feita de letras SLRcom 2 < length < 10000
Output
Something Truthy se for um slither válido e algo Falsey se não for.

Casos de teste

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

__Invalid__
SRRLSLLRRLLSLRRSRLLRSRRLLRRSRLLLLRSRRLLRRSRLLRSRRLSLLRRLLSLRR
SRRLSLLRRLLSLRRSRLLRSRRLLSRSSSRSSSSSSSRSRSSSSSSSRRLLRRSRLLRSRRLSLLRRLLSLRR
SRRSRSRSSRSSRSSSRSSSRSSSSSSSSSSRSSSSRSSSSSRSSSSSRSSSSSSRSSSSSSRSSSSSS
SSSSSSSSSSLSSSSSSSLSSSSSSSSLSSSSSLSSSSSSLSSSLLRRLRLRRLLSLSSSRRSSSSRSSSRSSSSSSRSSSSSRSSSSSSSSRSSSSSSSRSSSSSSSSS
LRSLLRLSRSLLSRLSLRSLSSSLRRSSLSRRLRSRLRLSLRLLRLRSSLSLRLRSRSSSSSLSRRLSLSSSRRLRLRLRLRRLLSSLSSSRRLRLRLRLRLSLSSSSSSSSSSSSSRLRLLRLRLRLRLRLRLRLSLSSSLSLSLLSLRLSLRSLRSLRSLSLSLRSRLSLRSLRLSRSLLLRLRLRRRRSLSLSSLLSLSLSLSSLLSLSLLRLRSLLRSRLSLSSLLLLSSSSSSSSSSSSSSSSSSSSRLRLLRRLRLRLLRLRLRLRLRLSSSSLSLRLLRLSLSSLSLSLSLSLRLLRLSLLLSRSSSSSSSSSSSSSSSRLRLRLLRLRLSLSRSRSSSLSRLRLRLRSLSLSLSRLLSRLSLSLSLSLSSLSLSLLSLSRLLRLRLRLRLRLRLRLRLRLRLSLSRLRLSLLRRLSLLSLSLSLSLSLLSLSLSLRLRLRLRLRLRLRLRLRLRRLRSLSLSLSLSLSLSLSSLSSSSSLSLSSSLSLSLSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS

Você pode desenhar os slithers aqui (R e L são invertidos, mas isso não afeta a validade)

DenDenDo
fonte
A entrada precisa ser feita no programa ou pode ser lida a partir de um arquivo?
MI Wright
1
SRRR deve ser verdadeiro ou falso? Ele se conecta, mas não se cruza.
orlp
cobras tocantes desafiam NSFW?
Ewan
3
se você desenhar SRRRem um papel de gráfico com um quadrado por segmento, em seguida, ele iria sobrepor-se e é, portanto, inválido, simplesmente RRRno entanto, ocuparia exatamente um quadrado de 2x2 sem sobreposições (assim como no jogo clássico)
DenDenDo
Semelhante, mas não duplicado (devido a diferentes objetivos e regras de construção diferentes).
trichoplax

Respostas:

20

Pitão, 22 20 bytes

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

Tente você mesmo ou execute o testinguite .

Observe os valores ASCII do SRL, respectivamente 83, 76, 82. Abuso do fato de que:

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

A partir daqui, apenas mantenho uma variável para a posição atual e a direção atual. Para cada caractere, multiplico a direção atual pelo número complexo acima e depois o adiciono à posição atual.

No final, verifico se todas as posições visitadas são únicas.

orlp
fonte
SRRR = verdadeiro ????
Ewan
@ Ewan Em uma inspeção mais detalhada - não tenho certeza se isso deve ser falso ou não. A cabeça e a cauda se conectam, mas não se cruzam.
Orlp
e o SRRRS?
Ewan
@ Ewan Mesma história - conexão, mas sem interseção. A questão não está clara sobre o que deve ser retornado para eles.
orlp
1
como você desenharia o SRRR?
Ewan
6

CJam, 30 bytes

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

Explicação a seguir em breve.

Experimente online aqui ou execute todo o conjunto .

Optimizer
fonte
Porra, isso foi rápido. Ainda nem pensei em um algoritmo para resolvê-lo.
DenDenDo 6/15/15
SRRRS = verdadeiro ???
Ewan
@ Ewan hum, estamos assumindo que 0 é inicialmente preenchido e conta?
Optimizer
1
Acho que estou interpretando como um jogo de cobra, onde movimentos ocupam blocos de espaço. e alguns de vocês estão interpretando-a como uma linha de largura de zero
Ewan
@ Ewan Minha pergunta é um pouco diferente. Quando temos um único movimento, digamos S, isso significa que a cobra já ocupou ambos (0,0) e (1,0)?
Optimizer
6

JavaScript (ES6), 84 89

Execute o snippet no Firefox para testar.

Algumas notas:

  • a cobra se move dentro da matriz f. Células não visitadas têm valor undefined. Na primeira visita, o operador til muda para -1, que é uma verdade. Eventualmente, em uma segunda visita, o valor muda para 0 que é falso e o everyloop termina retornando falso.
  • em JS, elementos de matriz com índices não canônicos (não numéricos ou negativos) são de alguma forma 'ocultos', mas existem. Aqui eu uso índices negativos sem nenhum problema.

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>

edc65
fonte
6

TI-BASIC, 49 56 53 51 bytes

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

Semelhante ao método do orlp, isso cria uma lista de todos os pontos no plano complexo visitado pela cobra, começando na origem. Se a lista não tiver elementos duplicados, o código retornará algum valor positivo. Observe que em uma sequência de mais de 999 elementos, a calculadora não conseguirá gerar uma lista suficientemente longa e ocorrerá um erro.

EDIT: Salva dois bytes à custa da feiura, pois não há dois pontos de treliça no plano complexo que podem estar à mesma distância de e ^ i.

lirtosiast
fonte
5

TI-BASIC, 60 58 bytes

Edit: Ignore tudo abaixo: uma solução ti-básica funcional está aqui , por thomas-kwa. Voto positivo!

é a [(-)]chave e Ans é [2ND]->[(-)]. Execute-o colocando as instruções da cobra entre aspas ( [ALPHA]->[+]), seguidas de dois pontos e o nome do programa. Por exemplo, se você nomear o programa "SNAKE", executaria o caso de teste no OP como "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

Editar: falha SRRLSLLRRRS. Eu tenho uma versão revisada em 61 bytes, mas ela falha no primeiro caso de teste inválido:

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

Vou tentar consertar amanhã.


Atualização: então o problema é que meu algoritmo está com defeito. Se eu tivesse usado um For (loop em oposição a seq ((para conseguir a mesma coisa)) (ambos os algoritmos acima, na verdade) poderia ser descrito como este:

  1. Inicialize a variável do contador para 1.
  2. Leia a string. Se o símbolo mudar, aumente a variável do contador. Se o símbolo se repetir, diminua-o.
  3. Se a variável do contador for maior que 0, exiba 1 (válido). Caso contrário, exiba 0 (inválido).

No entanto, isso falha em slithers inválidos como SRLRLRLRLRRRSS. Agora vou tentar criar um algoritmo melhor ... ou roubar outra resposta.


Tenho 90% de certeza de que isso pode ser substituído por um único seq(comando, na verdade, mas, por enquanto, é o menor possível. Se você pretende criar isso em um 8xp usando o Sourcecoder, em vez de realmente digitá-lo, observe que ele deve ser substituído por !=e o ⁻1+bit deve ser substituído por ~1+.

MI Wright
fonte
1

Ruby 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}

Teste online: http://ideone.com/pepeW2

Versão não destruída:

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
}
Cristian Lupascu
fonte
0

Golfscript 48 49 50

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

Espera que a string exista na pilha e retorne um 0ou1 .

Você pode experimentá-lo on-line com testes válidos e inválidos. cobras .

Esta é basicamente a mesma ideia que na minha resposta Ruby . Apenas a matriz de direção é tratada de maneira diferente, porque o AFAIK Golfscript não possui uma função de rotação arária. Nesse caso, eu construo uma matriz de direções suficientemente grande, multiplicando-a 10000 vezes e, em seguida, aparando desde o início 0, 1 ou 3 elementos, dependendo do comando atual (S, R ou L). A atual "direção" para a qual mover é sempre o primeiro item da matriz.

Aqui está com comentários:

# 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
..&=

Editar:

Economizou 1 caractere modificando como a matriz "direções" é consumida.

Editar:

salvou 1 caracter movendo incrementos de 10 em vez de 1 para usar a ?sintaxe (de potência).

Cristian Lupascu
fonte