Wird der Strahl treffen?


31

Ein Laser schießt einen geraden Strahl in eine der vier orthogonalen Richtungen, angezeigt durch <>^v. Bestimmen Sie, ob es das Ziel Oauf einem rechteckigen Gitter trifft .

Jeder von diesen wird treffen (True):

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

>O.
...

v....
O....

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

Diese werden fehlen (Falsch):

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

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


.O.
...
.v.

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

Eingabe: Ein rechteckiges Gitter mit einer .Größe von mindestens 2x2, mit genau einem Ziel Ound einem Laser, von dem einer ist <>^v. Die Zeilen können eine Liste von Zeichenfolgen, ein 2D-Array oder eine verschachtelte Liste von Zeichen oder eine einzelne durch Zeilenumbrüche getrennte Zeichenfolge mit optionalem Zeilenumbruch sein.

Ausgabe : Ein konsistenter Wahrheitswert, wenn der Laserstrahl das Ziel trifft, und ein konsistenter falscher Wert, wenn er verfehlt.

Ich werde Übermittlungen, die keine regulären Ausdrücke (oder eingebauten musterbasierten Zeichenfolgenabstimmungen) verwenden, als separate Kategorie betrachten. Wenn Sie (no regex)nach dem Namen der Sprache setzen, wird Ihre Antwort in der Bestenliste separat angezeigt.



6
Ich hatte gehofft, Sie würden Spiegel mit /und einfügen \ . Vielleicht für eine andere Frage ...
vsz

2
@Mego ... was diese Herausforderung sehr viel einfacher macht und sehr unterschiedliche Ansätze zulässt.
Martin Ender

2
@ Mego Ich stimme nicht zu; Nach dieser Logik ist die einfache Hallo-Welt-Herausforderung ein Duplikat von Dutzenden anderen Herausforderungen zur gleichen Zeit. Wie auch immer, danke, dass du mich über die Macht informiert hast, die ich jetzt habe, um Code-Golf-Herausforderungen zu schließen / wieder zu öffnen. Das war mir nicht bewusst.
Aditsu

5
@Mego Obwohl es sich bei dieser Frage um einen Sonderfall handelt, halte ich es nicht für einen Betrüger, da die Antworten ganz andere Ansätze verwenden. Bei dieser Frage berechnen alle den Weg, den der Strahl nimmt. Portale können den Pfad von überall nach überall verschieben, ohne dass eine Verknüpfung möglich erscheint, und Reflektoren sind schwierig zu handhaben. Die Antworten hier überprüfen oder stimmen meistens mit einer Eigenschaft der Eingabezeichenfolge überein. Natürlich können Sie eine Pfadverfolgungsantwort von der anderen Herausforderung kopieren und die zusätzlichen Bits entfernen, aber diese Methode ist übertrieben und bietet eine unnötig lange Lösung.
21.

Antworten:


27

Schnecken , 19 Bytes

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

Die Spezifikation für diese kann so wörtlich wie möglich implementiert werden, kein Denken erforderlich.


6
Können Sie eine Erklärung hinzufügen, wie dies funktioniert?
Fund Monica Klage

5
@QPaysTaxes Hoffentlich hilft dies, bis Feersum es schafft: Snails ist eine 2D-Pattern-Matching-Sprache. udlrStellen Sie die Richtung der Schnecke auf hoch / runter / links / rechts. |Funktioniert wie bei regulären regulären Ausdrücken und )benötigt keine passende offene Klammer. Der Code übersetzt sich also ziemlich direkt in "Suchen Sie eine von v<>^und stellen Sie die Richtung entsprechend ein, und versuchen Sie dann, ein O in dieser Richtung zu finden."
FryAmTheEggman

Ja, was Eggman gesagt hat. Die einzige andere Sache ist ,die *von Regex.
Feersum

13

Retina, 56 52 42 38 31 30 Bytes

1 Byte gespart dank @ MartinBüttner

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

Missbraucht Eigenschaften von Rechtecken. Erfordert die Eingabe einer nachgestellten Zeile.

Probieren Sie es online aus

Erläuterung

Dies funktioniert in drei Teilen:

  • Passend >
  • Passend <
  • Matching ^und vdas liegt daran, dass die Logik für ^und vwirklich die gleichen ist, nur die Charaktere.

Validierung <

Das ist ganz einfach:

O.*<

Dies entspricht einem O, optional gefolgt von Nicht-Newline-Zeichen, dann einem<

Validierung >

Dies ist ähnlich wie beim vorherigen Weg, nur anders herum. Zuerst >wird a abgeglichen, dann derO

Validierung ^undv

Dies war schwierig zu golfen und es wurde dafür geworben, dass der Input immer gültig war. Erstens stimmen wir überein, ob es sich um Folgendes handelt voder um O:

[vO]

Wenn es ein ist ^, sollte das erste Zeichen, das angetroffen wird, ein sein O. Das stimmt also mit dem ersten Zeichen überein, das übereinstimmt. Als nächstes zählen wir die Anzahl von .s, die ihm bis zur Newline folgen:

(.*\n)

Als nächstes kann dies in zwei Teile gehen, ich werde das erste behandeln:

Also stimmen wir zuerst mit Folgendem überein O:

[^O]*O

Dies stimmt optional mit allen Nicht- OZeichen überein , bis ein gefunden Owird. Wenn dies erfolgreich ist, wird es fortgesetzt. Wenn nicht, passiert Folgendes.

Nun versucht es die ^Verwendung zu finden :

[^^]*\^

^ist ein Sonderzeichen in Regex, daher muss es maskiert werden. [^^]stimmt mit allen Zeichen überein, außer ^, dies funktioniert genauso wie oben, wenn dies erfolgreich ist, passiert Folgendes ...

So , jetzt eine der oben hat erfolgreich angepasst, um die \1Kontrollen und sieht , wenn die Capture - Gruppe aus der Zeit vor (.*\n), diese Capture - Gruppe die Menge der gespeicherten .s dort die nach entweder waren voder Oaus der Zeit vor, so dass jetzt \1nur überprüft , ob die Menge von Punkten in der gleich.


Sie können ein Byte speichern, indem Sie anstelle von \n(Retina kann Quellcode in ISO 8859-1 verarbeiten.)
Martin Ender

@ MartinBüttner dachte nur an Ersatz, danke für den Tipp!
Downgoat

Nein, es funktioniert überall im Quellcode. Nach dem Aufteilen der Datei in Zeilen ersetzt Retina als Erstes die gesamte Datei , bevor eine weitere Analyse durchgeführt wird.
Martin Ender

9

Java (kein regulärer Ausdruck), 413 412 246 242 212 211 209 198 Bytes

Mit Java an Golfherausforderungen teilzunehmen hat weniger Sinn als mit dem Fahrrad an einem Formel-1-Rennen teilzunehmen, aber ich denke nicht immer, was Sinn macht.

Hier ist meine extrem lange Java-Version der Golfed-Version

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

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

Anscheinend war mein gesamtes Konzept falsch, hier ist meine kürzere Lösung

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

und ungolfed version

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

BEARBEITEN Ich habe den Code für die Suche nach 'O' umgeschrieben, jetzt enthält er eine einzelne Schleife, die viel kürzer ist, und ich habe den @Frozn-Vorschlag verwendet, um einige Zeichen durch ihre ASCII-Werte zu ersetzen.

Weitere 30 Bytes beißen den Staub.

Ein weiterer Vorschlag von @Frozn, und wir sind ein paar Bytes näher an der Python-Lösung

Bei einem weiteren Umschreiben wird eine Schleife gelöscht und zwei if-Anweisungen kombiniert


1
+1 Sie können jedoch das Leerzeichen zwischen returnund entfernen (, um ein Byte zu speichern. Das Leerzeichen ist nicht erforderlich, wenn der Rückgabewert in Klammern (oder Anführungszeichen für Zeichenfolgen) steht. Quelle aus den Java-Code-Golftipps.
Kevin Cruijssen

@ KevinCruijssen nicht viel sparen, aber danke :)
user902383

Jedes bisschen (oder sollte ich byte sagen) hilft mir. ;) Außerdem glaube ich nicht, dass Java jemals eine Code-Golf-Herausforderung gewinnen wird. Ich mag es aber immer noch, Code-Golf-Herausforderungen in Java zu meistern, zumal ich gerade mit Java bei der Arbeit arbeite.
Kevin Cruijssen

Sie können die Zeichen durch ihre ASCII - Wert ersetzt werden : 'O' = 79, '>' = 62, '<' = 60, '^' = 94. Für 'v' ist es 118, aber das verkürzt den Code nicht.
Frozn

@Frozn wie Kevin sagte, zählt in jedem Byte.
user902383

7

MATL (kein regulärer Ausdruck), 26 25 24 22 Byte

'>v<^'XJymfX!tZpYswJm)

Probieren Sie es online!

Geänderte Version für alle Testfälle

Erläuterung

        % 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 Jetzt, um herauszufinden, wie man los wirdJ
Suever

Ich kenne MATL nicht, also ist das vielleicht eine dumme Frage, aber warum ist 0 Primzahl?
Neil

3
@Neil Es ist ein Buchstabe 'O', keine Zahl 0. Der ASCII-Code für den Buchstaben 'O'lautet79
Luis Mendo

Ugh, ich glaube, ich wäre immer noch getäuscht worden, wenn Sie stattdessen nach ungeraden Zahlen gesucht hätten.
Neil

5

CJam (kein regulärer Ausdruck), 25

Frühere Versionen waren falsch, dies muss vorerst tun:

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

Probieren Sie es online aus

Erläuterung:

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

Ich habe ein paar mathematische Formeln ausprobiert, um zwischen "guten" und "schlechten" Zeichenfolgen zu unterscheiden, und für jede Art von Formel habe ich versucht, verschiedene Zahlen einzugeben. Ich endete mit dem HbI%oben genannten.

"gute" Zeichenfolgen für das ursprüngliche Raster sind "> O" und "O <" und ergeben das Ergebnis 17
"gute" Zeichenfolgen für das transponierte Raster sind "vO" und "O ^" und ergeben das Ergebnis 15
"schlecht" Zeichenfolgen für beide Gitter sind: ">", "<", "^", "v", "O", "", "O>", "Ov", "<O", "^ O" und sie geben die Ergebnisse 8, 6, 4, 10, 7, 0, 1, 3, 1, 3


3

Python 3 (kein regulärer Ausdruck), 184 Byte.

Hurra für eval 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 (SQL Server 2012) (kein regulärer Ausdruck), 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)

Musste funky Linechange in der Deklaration verwenden, um die Ausführung der Online-Version zu erzwingen (das Zuweisen von Werten zu Eingabevariablen hat sowieso keinen Einfluss auf die Längenberechnung)

Probieren Sie es online!



2

JavaScript (ES6), 78 Byte

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

Regexp natürlich. Hat sich im Prinzip als ähnlich erwiesen wie die Ruby-Antwort.


2

Ruby, 71 55 54 Bytes

Regex-Lösung, was bedeutet, dass es wahrscheinlich leicht von Retina oder Perl geschlagen werden wird.

Gibt eine Indexnummer (wahr) zurück, wenn eine Übereinstimmung vorliegt.

Jetzt mit einem ähnlichen Trick wie @Downgoat Retina antworten und gleichzeitig für Down- und Up-Beams abgleichen.

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

2

JavaScript (ES6) (kein regulärer Ausdruck), 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)

Wobei \ndas wörtliche Zeilenumbruchzeichen darstellt.


2

Clojure (kein regulärer Ausdruck), 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))))

Fühlt sich nicht gut an. Einfache Lösung: Finden des Index der entsprechenden Zeichen und Berechnen, ob sie sich in derselben Zeile befinden.

Sie können es hier versuchen https://ideone.com/m4f2ra


2

Python (kein regulärer Ausdruck), 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]

gibt True oder False zurück

Zuerst Streifen '.' und '\ n' von den Enden, so dass die interessierenden Zeichen '0 <> v ^' das erste und letzte Zeichen sind.

'>O<vO^'.find(t[0]+t[-1])//3- prüft, ob die Zeichen eine möglicherweise gültige Anordnung sind. Wertet 0 für '> O' oder 'O <', 1 für 'vO' oder 'O ^' und -1 für alles andere aus.

'\n'in t- prüft, ob sich die Zeichen in verschiedenen Zeilen befinden,
len(t)%(s.find('\n')+1)!=1- prüft, ob sie sich in verschiedenen Spalten befinden, und
1- ist die Standardeinstellung

The not inverts the result selected from the list, so the return expression is equivalent to:

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)

Function operating on an array of chars, normalizing by rotation, removing rows and columns containing only dots by range indexing and finally checking for location of 'O' taking into account if the remainder b is a column or row vector using matrix multiplication.

Try it online


1

Python 2 (no 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

Truthy and Falsy values returned by the function are 1 and 0, respectively.

I haven't had a chance to golf yet. Honestly, I'm not too hopeful for this one...

Any suggestions would be greatly appreciated!


1

C# (No 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);}

Works like the java version but transpiled and reduced

Expanded (Explanation included):

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

Expanded:

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

I think I took a decently different approach here compared to the Java or C# implementations. I got coordinates of the 'O' and arrow ((c,d) and (x,y)) and then compared them to see if the arrow was pointing in the correct direction.

Returns 0 if false and 1 if true


0

Grime v0.1, 31 bytes

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

Not a very interesting solution. Prints 1 for truthy instances, and 0 for falsy ones. Try it online!

Explanation

We simply search the input rectangle for a minimal-size (n×1 or 1×n) pattern that contains the laser and target in the correct order. The n` flag makes the interpreter print the number of matches, of which there will always be at most one. The rest of the line consists of four patterns separated by |-characters, which means a logical OR: a rectangle is matched if it matches one of the patterns. The patterns work as follows:

\>.*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 "^"
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.