Il raggio colpirà?


31

Un laser spara un raggio dritto in una delle quattro direzioni ortogonali, indicate da <>^v. Determina se colpirà il bersaglio Osu una griglia rettangolare.

Ognuno di questi colpirà (Vero):

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

>O.
...

v....
O....

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

Questi mancheranno (Falso):

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

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


.O.
...
.v.

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

Input: una griglia rettangolare di ., dimensioni almeno 2x2, con esattamente un bersaglio Oe un laser di cui è uno <>^v. Le righe possono essere un elenco di stringhe, un array 2D o un elenco nidificato di caratteri o una singola stringa separata da una nuova riga con una nuova riga finale facoltativa.

Output : un valore di verità costante se il raggio laser colpisce il bersaglio e un valore di falsa coerente se manca.

Prenderò in considerazione gli invii che non usano espressioni regolari (o la corrispondenza di stringhe basata su pattern incorporata) come categoria separata. Se si inserisce (no regex)il nome della lingua, la risposta verrà visualizzata separatamente nella classifica.



6
Speravo che includessi i mirror con /e \ . Forse per un'altra domanda ...
vsz

2
@Mego ... che rende questa sfida molto più semplice e consente approcci molto diversi.
Martin Ender,

2
@Mego non sono d'accordo; secondo questa logica, la semplice sfida del mondo ciao è un duplicato di dozzine di altre sfide allo stesso tempo. Comunque, grazie per avermi informato del potere che ora devo chiudere / riaprire le sfide del golf del codice, non ne ero a conoscenza.
aditsu,

5
@Mego Anche se questa domanda è un caso speciale dell'altra, non credo che sia un inganno perché le risposte usano approcci totalmente diversi. Su quella domanda, tutti calcolano il percorso che il raggio prende. I portali possono spostare il percorso da qualsiasi luogo a qualsiasi luogo che non sembra consentire una scorciatoia e i riflettori sono difficili da gestire. Le risposte qui invece controllano o corrispondono ad alcune proprietà della stringa di input. Certo, puoi copiare una risposta di tracciamento del percorso dall'altra sfida e rimuovere i bit extra, ma questo metodo è eccessivo e offre una soluzione inutilmente lunga.
xnor

Risposte:


27

Lumache , 19 byte

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

Le specifiche per questo possono essere implementate nel modo più letterale possibile, senza pensare.


6
Puoi aggiungere una spiegazione di come funziona?
Fondi Monica's Lawsuit

5
@QPaysTaxes Fino a quando feersum non vi si aggira, si spera che ciò possa aiutare: Snails è un linguaggio di abbinamento a motivi 2D. udlrimposta la direzione della lumaca su su / giù / sinistra / destra. |funziona come nella normale regex e )non necessita di una parentesi aperta corrispondente. Quindi il codice si traduce direttamente in "Trova uno di v<>^e imposta la direzione in modo appropriato, quindi prova a trovare una O in quella direzione".
FryAmTheEggman,

Sì, quello che ha detto Eggman. L'unica altra cosa è che ,è come il *regex.
feersum

13

Retina, 56 52 42 38 31 30 byte

Salvato 1 byte grazie a @ MartinBüttner

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

Abusa delle proprietà dei rettangoli. Richiede input per avere una nuova riga finale.

Provalo online

Spiegazione

Funziona in tre parti:

  • accoppiamento >
  • accoppiamento <
  • Abbinamento ^e vquesto è perché la logica ^e vsono davvero gli stessi, solo i personaggi.

Convalida <

Questo è semplice:

O.*<

Questo corrisponde a un O, facoltativamente seguito da caratteri non newline, quindi a<

Convalida >

Questo è molto simile al modo precedente, tranne il contrario. Prima >viene abbinata una, quindi laO

Convalida ^ev

Questo è stato difficile da golf e ha preso la pubblicità dell'input sempre valido. Innanzitutto, abbiniamo se è vo un O:

[vO]

Se è un ^, il primo personaggio che si incontra dovrebbe essere un O. Quindi, questo corrisponde al primo personaggio da abbinare. Quindi contiamo la quantità di .s che la seguono fino alla nuova riga:

(.*\n)

Successivamente, questo può andare in due parti, tratterò il primo:

Quindi, per prima cosa, abbiniamo fino a quanto segue O, usando:

[^O]*O

Questo facoltativamente corrisponde a tutti i non Ocaratteri fino a quando non Oviene rilevato un, se ciò ha esito positivo, quindi continua ... In caso contrario, si verifica quanto segue ...

Ora tenta di trovare l' ^utilizzo di:

[^^]*\^

^è un personaggio speciale in regex quindi deve essere evaso. [^^]corrisponde a tutti i caratteri tranne ^, funziona allo stesso modo sopra, se ciò ha esito positivo, si verifica quanto segue ...

Quindi ora uno dei precedenti ha funzionato correttamente, i \1controlli e vede se il gruppo di acquisizione di prima (.*\n), questo gruppo di acquisizione ha memorizzato la quantità di .s che c'erano dopo vo Oda prima, quindi ora \1controlla solo se la quantità di punti nel stesso.


Puoi salvare un byte usando invece di \n(Retina può gestire il codice sorgente in ISO 8859-1.)
Martin Ender,

@ MartinBüttner pensava che fosse solo \ n nelle sostituzioni, grazie per il suggerimento!
Downgoat,

no funziona ovunque nel codice sorgente. Dopo aver diviso il file in righe, la prima cosa che Retina fa è sostituire ovunque, prima di eseguire ulteriori analisi.
Martin Ender,

9

Java (no regex), 413 412 246 242 212 211 209 198 byte

Competere nelle sfide del golf usando java ha meno senso che prendere parte alla gara di Formula 1 in bicicletta, ma non faccio sempre pensieri che abbiano senso.

Ecco la mia soluzione java estremamente lunga Versione golf

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]);
}

Sembra che il mio intero concetto fosse sbagliato, ecco la mia soluzione più breve

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 versione ungolfed

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

EDIT Ho riscritto il codice per cercare 'O', ora contiene un singolo loop molto più breve e ho anche usato il suggerimento @Frozn per sostituire alcuni caratteri con i loro valori ASCII.

Di conseguenza, altri 30 byte mordono la polvere.

Un altro suggerimento di @Frozn, e siamo un paio di byte più vicini alla soluzione Python

Un'altra riscrittura rilascia un ciclo e combina due istruzioni if


1
+1 Tuttavia, è possibile rimuovere lo spazio tra returne (per salvare un byte. Lo spazio non è necessario quando il valore restituito è tra parentesi (o virgolette per stringhe). Fonte dei suggerimenti Java sul golf del codice.
Kevin Cruijssen,

@KevinCruijssen non risparmia molto, ma grazie :)
user902383

Ogni piccolo (o dovrei dire byte) aiuta a indovinare. ;) Inoltre, non credo che Java vincerà mai una sfida di code-golf. Mi piace comunque affrontare sfide di code-golf in Java, soprattutto perché attualmente sto lavorando con Java al lavoro.
Kevin Cruijssen,

È possibile sostituire i caratteri dal loro valore ASCII: 'O' = 79, '>' = 62, '<' = 60, '^' = 94. Per "v" è 118 ma ciò non accorcia il codice.
Frozn,

@Frozn come ha detto Kevin, in ogni byte conta.
user902383,

7

MATL (no regex), 26 25 24 22 byte

'>v<^'XJymfX!tZpYswJm)

Provalo online!

Versione modificata per tutti i casi di test

Spiegazione

        % 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

@LuisMendo Ora per capire come sbarazzarsi diJ
Suever,

Non conosco MATL, quindi questa potrebbe essere una domanda sciocca, ma perché 0 è primo?
Neil,

3
@Neil È lettera 'O', non numero 0. Il codice ASCII per la lettera 'O'è79
Luis Mendo,

Ugh, immagino che sarei stato ingannato se avessi cercato numeri dispari.
Neil,

5

CJam (no regex), 25

Le versioni precedenti erano sbagliate, questo per ora dovrà fare:

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

Provalo online

Spiegazione:

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

Ho provato alcune formule matematiche per distinguere tra stringhe "buone" e "cattive", e per ogni tipo di formula ho provato a collegare vari numeri. Ho finito con quanto HbI%sopra.

le stringhe "buone" per la griglia originale sono "> O" e "O <" e danno il risultato 17
stringhe "buone" per la griglia trasposta sono "vO" e "O ^" e danno il risultato 15
"cattivo" le stringhe per entrambe le griglie sono: ">", "<", "^", "v", "O", "", "O>", "Ov", "<O", "^ O" e danno i risultati 8, 6, 4, 10, 7, 0, 1, 3, 1, 3


3

Python 3 (no regex), 184 byte.

Evviva per l'hacking hacking!

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'><'])

3

TSQL (sqlserver 2012) (no regex), 358 byte

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)

Ho dovuto usare lo scambio funky nella dichiarazione per forzare l'esecuzione della versione online (l'assegnazione di valori alle variabili di input non influisce comunque sul calcolo della lunghezza)

Provalo online!



2

JavaScript (ES6), 78 byte

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

Regexp ovviamente. Si è rivelato essere in linea di principio simile alla risposta di Ruby.


2

Rubino, 71 55 54 byte

Soluzione Regex, il che significa che probabilmente sarà facilmente battuta da Retina o Perl.

Restituisce un numero indice (verità) se c'è una corrispondenza.

Ora con un trucco simile alla risposta @Downgoat Retina, abbinando contemporaneamente i raggi down e up.

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

2

JavaScript (ES6) (no regex), 126 byte

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)

Dove \nrappresenta il carattere letterale di newline.


2

Clojure (no regex), 293 byte

(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))))

Non mi sento benissimo. Soluzione semplice, trovare l'indice dei caratteri corrispondenti e calcolare se si trovano sulla stessa riga.

Puoi provarlo qui https://ideone.com/m4f2ra


2

Python (no regex), 105 byte

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]

restituisce True o False

Prima di tutto, spoglia "." e '\ n' dalle estremità in modo che i caratteri di interesse, '0 <> v ^', siano il primo e l'ultimo carattere.

'>O<vO^'.find(t[0]+t[-1])//3- controlla se i personaggi sono un accordo potenzialmente valido. Valuta a 0 per '> O' o 'O <', a 1 per 'vO' o 'O ^' e a -1 per qualsiasi altra cosa.

'\n'in t- controlla se i caratteri si trovano in righe diverse,
len(t)%(s.find('\n')+1)!=1- controlla se si trovano in colonne diverse e
1- è l'impostazione predefinita

I notinverte il risultato selezionato dalla lista, quindi l' returnespressione è 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

2

Julia (no 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)

Funzione operante su una matrice di caratteri, normalizzazione mediante rotazione, rimozione di righe e colonne contenenti solo punti mediante indicizzazione di intervallo e infine controllo della posizione di 'O' tenendo conto se il resto b è una colonna o un vettore di riga usando la moltiplicazione della matrice.

Provalo online


1

Python 2 (no regex), 268 byte

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

I valori Truthy e Falsy restituiti dalla funzione sono rispettivamente 1 e 0.

Non ho ancora avuto la possibilità di giocare a golf. Onestamente, non sono troppo fiducioso per questo ...

Ogni suggerimento sarà molto apprezzato!


1

C # (No Regex), 282 byte

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);}

Funziona come la versione java ma traspilata e ridotta

Espanso (spiegazione inclusa):

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);
}

0

C (ANSI) (No regex), 237 byte

#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;}

Allargato:

#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;
}

Penso di aver adottato un approccio decentemente diverso rispetto alle implementazioni Java o C #. Ho ottenuto le coordinate di 'O' e freccia ((c, d) e (x, y)) e poi le ho confrontate per vedere se la freccia stava puntando nella direzione corretta.

Restituisce 0 se falso e 1 se vero


0

Grime v0.1 , 31 byte

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

Non è una soluzione molto interessante. Stampe 1per casi veri e 0falsi. Provalo online!

Spiegazione

Cerchiamo semplicemente nel rettangolo di input un modello di dimensioni minime (n × 1 o 1 × n) che contenga il laser e il bersaglio nell'ordine corretto. La n`bandiera fa sì che l'interprete stampi il numero di corrispondenze, di cui ce ne sarà sempre al massimo una. Il resto della linea è costituito da quattro motivi separati da |caratteri, il che significa un OR logico: un rettangolo viene abbinato se corrisponde a uno dei motivi. I modelli funzionano come segue:

\>.*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 "^"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.