Você pode fazer um loop sem bater?

14

Muitos de nós estão familiarizados com o jogo Tron. Você controla um "ciclo de luz" colocado em uma grade. O ciclo da luz sempre se move para a frente (embora você controle a direção) e deixa um rastro permanente atrás dele. Se você topar com uma trilha, você trava!

O objetivo aqui é determinar se um determinado caminho é um loop válido, ou seja, ele retorna ao seu ponto de partida sem "travar". Para fazer isso, assumimos que começamos no ponto (0,0). Uma entrada é fornecida no formulário N2E1S2W1, com uma série de direções cardinais ( Né north, Eé easte assim por diante), cada uma seguida pela distância para viajar nessa direção. Neste exemplo, você viajaria

N2 : North 2 to (0,2)
E1 : East 1  to (1,2)
S2 : South 2 to (1,0)
W1 : West 1  to (0,0)

Um caminho é considerado válido se terminar (0,0)sem visitar nenhuma outra coordenada mais de uma vez (ele visita (0,0)exatamente duas vezes. Uma vez no início e outra no final). Lembre-se do que no exemplo acima, para ir de (0,0)a (0,2), nós necessariamente visitamos (0,1)também.

Outros exemplos:

input        -> output
N1E1S1W1     -> true
N1E1N1E1S2W2 -> true
N1S1E1W1     -> false     // Visits (0,0) 3 times
N4E2S2W4S2E2 -> false     // Visits (0,2) twice
N3E2S3       -> false     // Does not return to (0,0)
N1S1         -> anything  //I don't care how you evaluate this case

Sua saída pode ser de qualquer forma, desde que ela seja igual para qualquer valor de verdade ou falsey.

A entrada pode ser tomada como uma string ou como uma lista de caracteres, no formato S1N2E3... ou SNNEEE... Também não há limite rígido no tamanho da grade, mas assuma que a entrada não excederá nada. Desde que o código seja fundamentalmente sólido, não é crucial lidar com casos como esse N99999999999999.

NOTA: Você pode avaliar os casos N1S1, E1W1, S1N1, e W1E1no entanto você gostaria. São caminhos tecnicamente válidos, mas vão contra o espírito "Tron" do desafio.

Pontuação

Isso é , então a resposta mais curta vence!

Lord Farquaad
fonte
N1S1deve ser verdade que seja consistente com suas definições, pois atinge (0, 0)duas e (0, 1)uma vez, o que é válido na sua definição.
21717 HyperNeutrino
Posso aceitar Ncomo 1j, Ecomo 1, Scomo -1je Wcomo -1?
Freira vazando
@LeakyNun Eu acho que estou bem com isso, já que todo mundo deveria estar mais ou menos fazendo algo assim dessa maneira. Apenas certifique-se de especificar isso em sua resposta.
Lord Farquaad
1
@HyperNeutrino, mas do ponto de vista de Tron, seu ciclo de luz passa (0, 0,5) duas vezes, mesmo que a entrada nunca o coloque nesse ponto. É por isso que eu acho que se tem saída flexível (embora para a maioria dos idiomas vai ser mais fácil para retornar true)
Valor Ink
1
@steenbergh (0,0) não está no canto, então você pode ir abaixo ou à esquerda dele; mesmo os dois se você estiver se sentindo louco Além disso, não há limite rígido para o tamanho da grade, mas apenas assuma que a entrada não excederá nada. Enquanto o código é fundamentalmente sólida, eu não me importo se ele não consegue lidar com entradas comoN99999999999999
Lord Farquaad

Respostas:

6

JavaScript, 247 200 bytes

n=s=>{r=s.match(/\w\d+/g)
x=y=z=0
e=""
for(d of r){a=d[0]
b=d.slice(1)
while(b--){
y+=a=="N"
y-=a=="S"
x+=a=="E"
x-=a=="W"
p=[x,y]+";"
if(~e.indexOf(p))if(!x&!y)z++
else return 0
e+=p}}return!x&!y&!z}

né uma função da sequência de entrada sque retorna 1para verdadeiro e 0para falso

Aqui está uma versão não destruída para referência / explicação:

function n(s)
{
    var dir = s.match(/\w\d+/g);
    var x = y = z = 0;
    var been = "";
    for (d of dir)
    {
        var a = d[0];
        var b = 1*d.substring(1);
        while(b-- > 0)
        {
            if (a == "N") y++;
            if (a == "S") y--;
            if (a == "E") x++;
            if (a == "W") x--;
            var pt = [x,y] + ";";
            if (~been.indexOf(pt))
                if (x==0 && y==0)
                    z++;
                else
                    return false;
            been += pt;
        }
    }
    return (x == 0 && y==0 && z == 0);
}

n=s=>{r=s.match(/\w\d+/g)
x=y=z=0
e=""
for(d of r){a=d[0]
b=d.slice(1)
while(b--){
y+=a=="N"
y-=a=="S"
x+=a=="E"
x-=a=="W"
p=[x,y]+";"
if(~e.indexOf(p))if(!x&!y)z++
else return 0
e+=p}}return!x&!y&!z}

console.log(n("N1E1S1W1"))
console.log(n("N1E1N1E1S2W2"))
console.log(n("N1S1E1W1"))
console.log(n("N4E2S2W4S2E2"))
console.log(n("N3E2S3"))

WaffleCohn
fonte
Remova algum espaço em branco
HyperNeutrino 17/17/17
não percebeu que, graças
WaffleCohn
Parece que containsnão é uma função em nenhum dialeto de javascript. Você poderia especificar o dialeto?
Leaky Nun
Eu estava apenas usando o console do Chrome para testar - ele funciona perfeitamente lá #
WaffleCohn 17/17/17
Na verdade, ele funciona no meu console cromado também ... mas talvez você considere transformá-lo em uma resposta mais universal?
Leaky Nun
5

Python 3 , 236 161 150 bytes

import re
p=0
a=[]
for i in''.join(s[0]*int(s[1:])for s in re.findall(r".\d+",input())):p+=1j**"NESW".find(i);a+=[p]
print(len({*a})-len(a)==0==a[-1])

Experimente online!

-75 bytes graças ao Leaky Nun
-11 bytes graças ao Leaky Nun Ou, se pudermos receber informações como uma lista de números complexos decodificados pelo comprimento da execução:

Python 2 , 85 73 bytes

c=0;k=[]
for i in input():c+=i;k+=[c]
print(k[-1]==0==len(set(k))-len(k))

Experimente online!

-12 bytes graças ao Sr. Xcoder / -9 bytes graças ao Leaky Nun (mesclado em uma edição)

Isso parece muito tempo para mim lol

HyperNeutrino
fonte
3
Contanto que seja menor que 10 vezes a solução Pyth, não é muito longo.
Leaky Nun
@LeakyNun lol okay: P
HyperNeutrino
161 bytes
Freira vazada
@LeakyNun oh snap nice. veja por muito tempo, como eu disse: P
HyperNeutrino
76 bytes
Freira vazada
3

Geléia , 14 12 bytes

Œṙ+\µQ⁼ȧṛ/¬$

Esta é a minha primeira vez jogando golfe em Jelly. Sugestões são bem vindas.

A entrada é como uma matriz de [direction, distance]pares, onde a direção é dada como um número complexo.

Explicação:

Œṙ+\µÇȧṛ/¬$   Main link. Argument: n     = [[i, 3], [1, 2], [-i, 3]]
Œṙ            Run-length decode          = [i, i, i, 1, 1, -i, -i, -i]
  +\          Cumulative sum             = [i, 2i, 3i, 3i+1, 3i+2, 2i+2, i+2, i]
    µ         Begin a new monadic chain
     Q        Remove duplicates          = [i, 2i, 3i, 3i+1, 3i+2, 2i+2, i+2]
      ⁼       Equal to original?         = 0
           $  Make a monadic link:
        ṛ/      Reduce by right argument   = i
                (Gets the last element)
          ¬     Logical NOT:               = 0
       ȧ      Logical AND the two values = 0
Esolanging Fruit
fonte
Deve falhar no último caso.
Leaky Nun
0

Retina , 86 bytes

\d+
$*
1(1*)
$1
+`(.)1
$1$1
.
 $`$&¶
%O`.
+`NS|E(.*)W
$1
M`\w$|(?m)(^.+$)(?s).+^\1$
^0

Experimente online! O link inclui casos de teste. Explicação:

\d+
$*

Converta os números para unários.

1(1*)
$1
+`(.)1
$1$1

Duração decodificar as letras. N111precisa se transformar NNN, então um é subtraído de cada número unário e, em seguida, cada 1 duplica a letra anterior.

.
 $`$&¶

Gere todos os prefixos (ou seja, pontos no caminho) como linhas separadas. Um espaço é prefixado para evitar problemas com linhas vazias.

%O`.
+`NS|E(.*)W
$1

Classifique todas as letras em cada linha em ordem e exclua os pares correspondentes. Acabamos com um código único para qualquer ponto da grade.

M`\w$|(?m)(^.+$)(?s).+^\1$

Verifique uma das duas coisas: a) o último ponto não termina em um espaço (ou seja, o loop não foi fechado) ou dois pontos duplicados no caminho. Se o caminho for válido, todas as verificações falharão e o resultado será zero.

^0

Inverta o resultado.

Neil
fonte
0

Perl, 140

Funciona com entrada de string. Talvez eu possa diminuir com a matriz, mas duvido. Feliz por qualquer ajuda adicional no golfe :)

sub w{$i=$_[0];%d=(E,[0],S,[1,-1],W,[0,-1]);$i=~s/(.)(.)/($d,$o)=(@{$d{$1}},1,1);for(1..$2){$s[$d]+=$o;$r+=$d{"@s"}++}/eg;!($s[0]+$s[1]+$r)}
bytepusher
fonte