O raio atingirá?

31

Um laser dispara um feixe reto em uma das quatro direções ortogonais, indicadas por <>^v. Determine se ele atingirá o alvo Oem uma grade retangular.

Cada um deles será exibido (True):

.....
...O.
.....
...^.
.....

>O.
...

v....
O....

...........
...........
O.........<
...........

Eles sentirão falta (Falso):

......
......
.^..O.

......
.....>
O.....
......
......


.O.
...
.v.

.....<.
..O....

Entrada: uma grade retangular de ., pelo menos, 2x2, com exatamente um alvo Oe um laser <>^v. As linhas podem ser uma lista de cadeias, uma matriz 2D ou uma lista aninhada de caracteres ou uma única cadeia separada por nova linha com uma nova linha à direita opcional.

Saída : um valor de verdade consistente, se o raio laser atingir o alvo, e um valor de falsidade consistente, se errar.

Considerarei os envios que não usam expressões regulares (ou correspondência de sequência interna baseada em padrões) como uma categoria separada. Se você colocar (no regex)o nome do idioma, sua resposta aparecerá separadamente no placar.

xnor
fonte
8
Relacionado
VisualMelon 19/16
6
Eu esperava que você incluísse espelhos com /e \ . Talvez para outra pergunta ...
vsz
2
@Mego ... o que torna esse desafio muito mais simples e permite abordagens muito diferentes.
Martin Ender
2
@Mego Eu discordo; por essa lógica, o simples desafio olá mundo é uma duplicata de dezenas de outros desafios ao mesmo tempo. De qualquer forma, obrigado por me notificar sobre o poder que agora tenho para fechar / reabrir os desafios do código de golfe, eu não estava ciente disso.
Aditsu 21/05
5
@Mego Embora essa questão seja um caso especial da outra, não acredito que seja uma bobagem, porque as respostas usam abordagens totalmente diferentes. Sobre essa questão, todos eles calculam o caminho que o feixe percorre. Os portais podem mover o caminho de qualquer lugar para qualquer lugar que não pareça permitir um atalho, e os refletores são difíceis de manusear. As respostas aqui, em sua maioria, conferem ou combinam alguma propriedade da sequência de entrada. Claro, você pode copiar uma resposta de rastreamento de caminho do outro desafio e remover os bits extras, mas esse método é um exagero e fornece uma solução desnecessariamente longa.
Xnor 21/05

Respostas:

27

Caracóis , 19 bytes

\>|\<l|\^u|\vd).,\O

As especificações para este podem ser implementadas o mais literalmente possível, sem necessidade de pensar.

feersum
fonte
6
Você pode adicionar uma explicação de como isso funciona?
Fund Monica's Lawsuit
5
@QPaysTaxes Até que o feersum resolva isso, espero que isso ajude: Snails é uma linguagem de correspondência de padrões 2D. udlrdefina a direção do caracol para cima / baixo / esquerda / direita. |funciona como no regex regular e )não precisa de um parêntese aberto correspondente. Portanto, o código se traduz diretamente em "Encontre um v<>^e defina a direção de forma apropriada e tente encontrar um O nessa direção".
FryAmTheEggman
Sim, o que Eggman disse. A única outra coisa é que ,é como o *do regex.
19416 feersum
13

Retina, 56 52 42 38 31 30 bytes

Guardado 1 byte graças a @ MartinBüttner

O.*<|>.*O|[vO](.*¶)[^O]*[O^]\1

Abusa das propriedades dos retângulos. Requer entrada para ter uma nova linha à direita.

Experimente online

Explicação

Isso funciona em três partes:

  • Coincidindo >
  • Coincidindo <
  • Correspondência ^e visso ocorre porque a lógica para ^e vé realmente a mesma, apenas os caracteres.

Validando <

Isto é simples:

O.*<

Corresponde a um O, opcionalmente seguido por caracteres que não são de nova linha, depois um<

Validando >

É o mesmo da maneira anterior, exceto o contrário. Primeiro a >é correspondido, então oO

Validando ^ev

Foi difícil jogar golfe e a publicidade da entrada sempre era válida. Primeiro, combinamos se é vou um O:

[vO]

Se for um ^, o primeiro caractere encontrado deve ser a O. Portanto, isso corresponde ao primeiro caractere a ser correspondido. Em seguida, contamos a quantidade de .s que segue até a nova linha:

(.*\n)

Em seguida, isso pode ser dividido em duas partes, abordarei a primeira:

Então, primeiro, correspondemos até o seguinte O, usando:

[^O]*O

Opcionalmente, isso corresponde a todos os Ocaracteres não até que um Oseja encontrado, se for bem-sucedido, continuará ... se não, o seguinte acontece ...

Agora, ele tenta encontrar o ^uso:

[^^]*\^

^é um caractere especial no regex, portanto, ele precisa ser escapado. [^^]corresponde a todos os caracteres ^, exceto , isso funciona da mesma forma que acima, se for bem-sucedido, acontece o seguinte ...

Portanto, agora, uma das opções acima correspondeu com êxito, \1verifica e verifica se o grupo de captura anterior (.*\n), esse grupo de captura armazenou a quantidade de .s que havia após o antes vou o Oanterior; agora, \1apenas verifica se a quantidade de pontos no mesmo.

Downgoat
fonte
Você pode salvar um byte usando em vez de \n(Retina pode lidar com código-fonte em ISO 8859-1.)
Martin Ender
@ MartinBüttner pensou que era apenas \ n em substituições, obrigado pela dica!
Downgoat
Não, ele funciona em qualquer lugar no código fonte. Depois de dividir o arquivo em linhas, a primeira coisa que o Retina faz é substituir todos os lugares, antes de fazer mais análises.
Martin Ender
9

Java (sem regex), 413 412 246 242 212 211 209 198 bytes

Competir em desafios de golfe usando java tem menos sentido do que participar da corrida de Fórmula 1 em bicicleta, mas nem sempre estou pensando o que faz algum sentido.

Aqui está minha solução java extremamente longa Versão Golfed

boolean l(char[][]w){int[]t={},l={};for(int y=0;y<w.length;y++)for(int x=0;x<w[0].length;x++){if(w[y][x]=='O')t=new int[]{x,y};if(w[y][x]=='<')l=new int[]{x,y,1};if(w[y][x]=='>')l=new int[]{x,y,2};if(w[y][x]=='v')l=new int[]{x,y,3};if(w[y][x]=='^')l=new int[]{x,y,4};};return(l[2]==1&&l[1]==t[1]&&l[0]>t[0])||(l[2]==2&&l[1]==t[1]&&l[0]<t[0])||(l[2]==3&&l[0]==t[0]&&l[1]<t[1])||(l[2]==4&&l[0]==t[0]&&l[1]>t[1]);}

e ungolfed

boolean l(char[][] w) {
    int[] t = {}, l = {};
    for (int y = 0; y < w.length; y++)
        for (int x = 0; x < w[0].length; x++) {
            if (w[y][x] == 'O')
                t = new int[] { x, y };
            if (w[y][x] == '<')
                l = new int[] { x, y, 1 };
            if (w[y][x] == '>')
                l = new int[] { x, y, 2 };
            if (w[y][x] == 'v')
                l = new int[] { x, y, 3 };
            if (w[y][x] == '^')
                l = new int[] { x, y, 4 };
        }
    ;
    return (l[2] == 1 && l[1] == t[1] && l[0] > t[0])
            || (l[2] == 2 && l[1] == t[1] && l[0] < t[0])
            || (l[2] == 3 && l[0] == t[0] && l[1] < t[1])
            || (l[2] == 4 && l[0] == t[0] && l[1] > t[1]);
}

Parece que todo o meu conceito estava errado, aqui está a minha solução mais curta

boolean z(char[][]w){int x=0,y=0,i=0,a=w.length,b=w[0].length;for(;w[y][x]!=79;)if(++y==a){y=0;x++;}for(;i<(a<b?b:a);)if(i<b&w[y][i]==(i<x?62:60)|i<a&w[i][x]==(i++<y?'v':94))return 1<2;return 1>2;}

e versão não destruída

oolean z(char[][] w) {
        int x = 0, y = 0, i = 0, a = w.length, b = w[0].length;
        for (; w[y][x] != 79;)
            if (++y == a) {
                y = 0;
                x++;
            }
        for (; i < (a < b ? b : a);)
            if (i < b & w[y][i] == (i < x ? 62 : 60) | i < a
                    & w[i][x] == (i++ < y ? 'v' : 94))
                return 1 < 2;
        return 1 > 2;
    }

EDITAR Eu reescrevi o código para procurar 'O', agora ele contém um loop único e é muito mais curto, e também usei a sugestão @Frozn para substituir alguns caracteres por seus valores ascii.

Como resultado, outros 30 bytes mordem a poeira.

Outra sugestão do @Frozn, e estamos alguns bytes mais próximos da solução Python

Outra reescrita solta um loop e combina duas instruções if

user902383
fonte
1
+1 Você pode remover o espaço entre returne (salvar um byte. O espaço não é necessário quando seu valor de retorno está entre parênteses (ou aspas para Strings). Fonte das dicas de golfe de código Java.
Kevin Cruijssen
@KevinCruijssen não economizando muito, mas graças :)
user902383
Cada pedacinho (ou devo dizer byte) ajuda, eu acho. ;) Além disso, acho que o Java nunca vencerá um desafio de código-golfe de qualquer maneira. Ainda gosto de fazer desafios de código-golfe em Java, especialmente porque atualmente estou trabalhando com Java no trabalho.
Kevin Cruijssen
Você pode substituir os caracteres pelo seu valor ASCII: 'O' = 79, '>' = 62, '<' = 60, '^' = 94. Para 'v' é 118, mas isso não reduz o código.
Frozn 26/05
@Frozn como Kevin disse, em cada byte conta.
User902383 26/05
7

MATL (sem regex), 26 25 24 22 bytes

'>v<^'XJymfX!tZpYswJm)

Experimente Online!

Versão modificada para todos os casos de teste

Explicação

        % Implicitly grab input
'>v<^'  % String literal indicating the direction chars
XJ      % Store in the J clipboard
y       % Copy the input from the bottom of the stack
m       % Check to see which of the direction chars is in the input. The
        % result is a 1 x 4 logical array with a 1 for the found direction char
f       % Get the 1-based index into '>v<^' of this character
X!      % Rotate the input board 90 degrees N times where N is the index. This
        % Way we rotate the board so that, regardless of the direction char,
        % the direction char should always be BELOW the target in the same column
t       % Duplicate
Zp      % Determine if any elements are prime ('O' is the only prime)
Ys      % Compute the cumulative sum of each column
w       % Flip the top two stack elements
J       % Grab '>v<^' from clipboard J
m       % Create a logical matrix the size of the input where it is 1 where
        % the direction char is and 0 otherwise
)       % Use this to index into the output of the cumulative sum. If the 
        % direction char is below 'O' in a column, this will yield a 1 and 0 otherwise
        % Implicitly display the result
Suever
fonte
@LuisMendo Agora, para descobrir como se livrar deJ
Suever
Eu não sei MATL, então isso pode ser uma pergunta boba, mas por que 0 é primo?
Neil
3
@ Neil É letra 'O', não número 0. O código ASCII para carta 'O'é79
Luis Mendo
Ugh, acho que ainda teria sido enganado se você estivesse procurando números ímpares.
Neil
5

CJam (sem regex), 25

Versões anteriores estavam erradas, isso terá que ser feito por enquanto:

q~_z]{'.-HbI%}f%[HF].&~+,

Experimente online

Explicação:

q~         read and evaluate the input (given as an array of strings)
_z         copy and transpose
]          put the original grid and transposed grid in an array
{…}f%      map the block to each grid (applying it to each string in each grid)
  '.-      remove all dots (obtaining a string of 0 to 2 chars)
  Hb       convert to base H=17, e.g. ">O" -> 62*17+79=1133
  I%       calculate modulo I=18
[HF]       make an array [17 15]
.&         set-intersect the first array (mapped grid) with 17 and 2nd one with 15
~+         dump and concatenate the results
,          get the array length

Tentei algumas fórmulas matemáticas para distinguir entre "boas" e "más" e, para cada tipo de fórmula, tentei inserir vários números. Acabei com o HbI%acima exposto.

cadeias "boas" para a grade original são "> O" e "O <" e fornecem o resultado 17
cadeias "boas" para a grade transposta são "vO" e "O ^" e dão o resultado 15 como
"ruins" seqüências de caracteres para ambas as grades são: ">", "<", "^", "v", "O", "", "O>", "Ov", "<O", "^ O" e fornecem os resultados 8, 6, 4, 10, 7, 0, 1, 3, 1, 3

aditsu
fonte
3

Python 3 (sem regex), 184 bytes.

Viva para hackers de avaliação!

def f(a,o=0,d={},q=''):
 for r in a:
  i=0
  for c in r:d[c]=o,i;i+=1;q=(c,q)[c in'O.']
  o+=1
 z,y=d['O'];e,j=d[q];return eval("z%se and y%sj"%(('><'[q<'v'],'=='),('==',q))[q in'><'])
Morgan Thrapp
fonte
3

TSQL (sqlserver 2012) (sem regex), 358 bytes

DECLARE @ varchar(1000)=
'......'+ CHAR(13)+CHAR(10)+
'......'+ CHAR(13)+CHAR(10)+
'...0..'+ CHAR(13)+CHAR(10)+
'...^..'+ CHAR(13)+CHAR(10)
;

WITH C as(SELECT
number n,SUBSTRING(@,number,1)a,1+min(IIF(SUBSTRING(@,number,1)=char(13),number,99))over()m
FROM master..spt_values
WHERE'P'=type and
SUBSTRING(@,number,1)in('>','<','^','v','0',char(13)))SELECT
IIF(c.n%c.m=d.n%c.m and c.a+d.a in('0^','v0')or
c.n/c.m=d.n/c.m and c.a+d.a in('>0','0<'),1,0)FROM c,c d
WHERE c.n<d.n and char(13)not in(c.a,d.a)

Teve que usar funky linechange na declaração para forçar a versão online a executá-la (atribuir valores às variáveis ​​de entrada não afeta o cálculo do comprimento)

Experimente online!

t-clausen.dk
fonte
2

JavaScript (ES6), 78 bytes

s=>s.match(`>.*O|O.*<|(?=v)([^]{${l=s.search`\n`+1}})+O|(?=O)([^]{${l}})+\\^`)

Regexp, é claro. Acabou sendo semelhante em princípio à resposta Ruby.

Neil
fonte
2

Ruby, 71 55 54 bytes

Solução Regex, o que significa que provavelmente será facilmente derrotado por Retina ou Perl.

Retorna um número de índice (verdade) se houver uma correspondência.

Agora, com um truque semelhante à resposta do @Downgoat Retina, correspondendo às vigas para baixo e para cima ao mesmo tempo.

->m{m=~/>\.*O|O\.*<|(?=[vO])(.{#{??+m=~/\n/}})+[O^]/m}
Value Ink
fonte
2

JavaScript (ES6) (sem regex), 126 bytes

s=>([n,o,l,r,u,d]=[..."\nO<>^"].map(c=>1+s.indexOf(c)),l>o&l-o<n&l%n>o%n||r&&r<o&o-r<n&r%n<o%n||u>o&u%n==o%n||d&&d<o&d%n==o%n)

Onde \nrepresenta o caractere literal de nova linha.

Neil
fonte
2

Clojure (sem regex), 293 bytes

(defn z[f](let[v(sort(keep-indexed(fn[i v](if(some #{v}[\v\>\<\^\O])[(if(= v\O)\& v)i]))f))l(+(.indexOf f"\n")1)d((nth v 1)0)q((nth v 1)1)p((nth v 0)1)r(=(quot p l)(quot q l))i(> q p)](cond(= d\^)(and i(=(mod(- q p)l)0))(= d\v)(and(not i)(=(mod(- p q)l)0))(= d\>)(and(not i)r):else(and i r))))

Não parece ótimo. Solução simples, localizando o índice dos caracteres correspondentes e calculando se eles estão na mesma linha.

Você pode experimentá-lo aqui https://ideone.com/m4f2ra

cliffroot
fonte
2

Python (sem regex), 105 bytes

def f(s):t=s.strip('.\n');return not['\n'in t,len(t)%(s.find('\n')+1)!=1,1]['>O<vO^'.find(t[0]+t[-1])//3]

retorna Verdadeiro ou Falso

Primeiro, retira '.' e '\ n' das extremidades, para que os caracteres de interesse, '0 <> v ^', sejam o primeiro e o último caracteres.

'>O<vO^'.find(t[0]+t[-1])//3- verifica se os caracteres são um arranjo potencialmente válido. Avalia como 0 para '> O' ou 'O <', para 1 para 'vO' ou 'O ^' e para -1 para qualquer outra coisa.

'\n'in t- verifica se os caracteres estão em linhas diferentes,
len(t)%(s.find('\n')+1)!=1- verifica se estão em colunas diferentes, e
1 - é o padrão

O notinverte o resultado selecionado da lista, portanto a returnexpressão é equivalente a:

t[0]+t[-1] in '>0<' and '\n' not in t or t[0]+t[-1] in 'vO^' and len(t)%(s.find('\n')+1)==1
RootTwo
fonte
2

Julia (sem regex), 98

a->(c=rotr90(a,findlast("i1Q/",sum(a-46)));
    f(n)=find(any(c.!='.',n));b=c[f(2),f(1)];
    (b'*b)[1]==97)

Função operando em uma matriz de caracteres, normalizando por rotação, removendo linhas e colunas contendo apenas pontos pela indexação de intervalo e, finalmente, verificando a localização de 'O' levando em consideração se o restante b é um vetor de coluna ou linha usando multiplicação de matrizes.

Experimente online

mschauer
fonte
1

Python 2 (sem regex), 268 bytes

import numpy
def q(i):
 s=numpy.asmatrix(i)
 for n in s:
  n=n.tolist()[0]
  try:
   a=n.index("0")
   if n.index(">")<a or n.index("<")>a:return 1
  except:0
 for n in range(len(i)):
  c=[x[0] for x in s[:,n].tolist()]
  try:
   a=c.index("0")
   if c.index("v")<a or c.index("^")>a:return 1
  except:0
 return 0

Os valores de Truthy e Falsy retornados pela função são 1 e 0, respectivamente.

Ainda não tive a chance de jogar golfe. Sinceramente, não tenho muita esperança deste ...

Todas as sugestões serão muito apreciadas!

Daniel
fonte
1

C # (sem regex), 282 bytes

bool F(char[,]b){int k=0,l=1,m=1,n=0,o=0;for(int x=0;x<b.GetLength(0);x++)for(int y=0;y<b.GetLength(1);y++){char i=b[x,y];if(i=='O'){k=x;l=y;}if(new[]{'<','>','^','v'}.Contains(i)){m=x;n=y;o=i;}}return(o==60&&k==m&&l<n)||(o==62&&k==m&&l>n)||(o==94&&l==n&&k<m)||(o==118&&l==n&&k>m);}

Funciona como a versão java, mas transpilada e reduzida

Expandido (explicação incluída):

bool F(char[,] b)
{
    // declare variables for goal x, goal y, laser x, laser y, and laser direction respectively (laser direction is char code for directions)
    int k = 0, l = 0, m = 0, n = 0, o = 0;
    // go through each cell
    for (int x = 0; x < b.GetLength(0); x++)
    {
        for (int y = 0; y < b.GetLength(1); y++)
        {
            // get cell contents
            char i = b[x, y];
            // set goal position if goal
            if (i == 'O')
            {
                k = x;
                l = y;
            }
            // set laser position and direction if laser
            if (new[]{ '<', '>', '^', 'v' }.Contains(i))
            {
                m = x;
                n = y;
                o = i;
            }
        }
    }
    // check everything is on the same line and in right direction
    return (o == 60 && k == m && l < n) ||
           (o == 62 && k == m && l > n) ||
           (o == 94 && l == n && k < m) ||
           (o == 118 && l == n && k > m);
}
RedLaser
fonte
0

C (ANSI) (sem regex), 237 bytes

#define l b[1][i]
main(i,b,c,d,x,y,z,p)char **b;{for(y=z=i=0,x=1;z<2&&(l==10?x=0,++y:1);i++,x++)if(l>46){if(l!=79)p=l;if(!z++)c=x,d=y;}i--;x--;z=(c==x)*((p=='v')*(l==79)+(p==94)*(l==p))+(d==y)*((p==60)*(l==p)+(p==62)*(l==79));return z;}

Expandido:

#define l b[1][i]
main(i,b,c,d,x,y,z,p)char **b;{
    for(y=z=i=0,x=1;z<2&&(l==10?x=0,++y:1);i++,x++)
        if(l>46){if(l!=79)p=l;if(!z++)c=x,d=y;}
    i--;x--;
    z=(c==x)*((p=='v')*(l==79)+(p==94)*(l==p))+(d==y)*((p==60)*(l==p)+(p==62)*(l==79));
    printf("%i\n",z);
    return z;
}

Acho que tomei uma abordagem decentemente diferente aqui em comparação com as implementações Java ou C #. Peguei coordenadas do 'O' e da flecha ((c, d) e (x, y)) e as comparei para ver se a flecha estava apontando na direção correta.

Retorna 0 se falso e 1 se verdadeiro

dj0wns
fonte
0

Grime v0.1 , 31 bytes

n`\>.*a|a.*\<|\v/./*/a|a/./*/\^

Não é uma solução muito interessante. Imprime 1para instâncias 0verdadeiras e falsas. Experimente online!

Explicação

Simplesmente procuramos no retângulo de entrada um padrão de tamanho mínimo (n × 1 ou 1 × n) que contenha o laser e o alvo na ordem correta. A n`bandeira faz com que o intérprete imprima o número de correspondências, das quais sempre haverá no máximo uma. O restante da linha consiste em quatro padrões separados por| -characters, o que significa um OR lógico: um retângulo é correspondido se corresponder a um dos padrões. Os padrões funcionam da seguinte maneira:

\>.*a    Literal ">", horizontal row of any chars, one alphabetic char
a.*\<    One alphabetic char, horizontal row of any chars, literal "<"
\v/./*/a Literal "v", on top of vertical column of any chars, on top of one alphabetic char
a/./*/\^ One alphabetic char, on top of vertical column of any chars, on top of literal "^"
Zgarb
fonte