Czy promień uderzy?

31

Laser strzela prostą wiązką w jednym z czterech ortogonalnych kierunków, oznaczonych symbolem <>^v. Ustal, czy trafi w cel Ona prostokątnej siatce.

Każdy z nich trafi (True):

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

>O.
...

v....
O....

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

Będą tęsknić (Fałsz):

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

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


.O.
...
.v.

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

Wejście: Prostokątna siatka o .wielkości co najmniej 2x2, z dokładnie jednym celem Oi jednym laserem <>^v. Linie mogą być listą ciągów, tablicą 2D lub zagnieżdżoną listą znaków lub pojedynczym ciągiem oddzielonym znakiem nowej linii z opcjonalnym końcowym znakiem nowego wiersza.

Wyjście : spójna wartość prawdy, jeśli promień lasera uderza w cel, i spójna wartość fałszu, jeśli nie trafi.

Rozważę zgłoszenia, które nie używają wyrażeń regularnych (lub wbudowanego dopasowywania ciągów opartych na wzorach) jako osobnej kategorii. Jeśli wstawisz (no regex)po nazwie języka, twoja odpowiedź pojawi się osobno w tabeli wyników.

xnor
źródło
8
Powiązane
VisualMelon
6
Miałem nadzieję, że dołączysz lustra z /i \ . Może na inne pytanie ...
vsz
2
@Mego ... co znacznie upraszcza to wyzwanie i pozwala na bardzo różne podejścia.
Martin Ender,
2
@Mego Nie zgadzam się; zgodnie z tą logiką zwykłe światowe wyzwanie jest kopią kilkudziesięciu innych wyzwań jednocześnie. W każdym razie, dzięki za powiadomienie mnie o mocy, którą teraz muszę zamykać / ponownie otwierać wyzwania związane z golfem, nie wiedziałem o tym.
aditsu
5
@Mego Chociaż to pytanie jest szczególnym przypadkiem drugiego, nie wierzę, że to oszustwo, ponieważ odpowiedzi wykorzystują zupełnie inne podejście. W tym pytaniu wszyscy obliczają ścieżkę, którą podąża wiązka. Portale mogą przenosić ścieżkę z dowolnego miejsca do dowolnego, co nie wydaje się pozwalać na skrót, a reflektory są trudne w obsłudze. Odpowiedzi tutaj zamiast tego najczęściej sprawdzają lub dopasowują niektóre właściwości ciągu wejściowego. Pewnie, możesz skopiować odpowiedź na śledzenie ścieżki z drugiego wyzwania i usunąć dodatkowe bity, ale ta metoda jest przesadna i daje niepotrzebnie długie rozwiązanie.
xnor

Odpowiedzi:

27

Ślimaki , 19 bajtów

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

Specyfikację tego można wdrożyć tak dosłownie, jak to możliwe, bez potrzeby myślenia.

feersum
źródło
6
Czy możesz dodać wyjaśnienie, jak to działa?
Pozew funduszu Moniki
5
@QPaysTaxes Dopóki feersum się nie zajmie, mam nadzieję, że to pomoże: Snails jest językiem dopasowanym do wzorca 2D. udlrustaw kierunek ślimaka w górę / dół / lewo / prawo. |działa jak w regularnym wyrażeniu regularnym i )nie potrzebuje pasującego otwartego nawiasu. Więc kod dość bezpośrednio tłumaczy się na „Znajdź jeden v<>^i odpowiednio ustaw kierunek, a następnie spróbuj znaleźć O w tym kierunku”.
FryAmTheEggman
Tak, co powiedział Eggman. Jedyne, co ,jest podobne do *wyrażenia regularnego.
feersum
13

Retina, 56 52 42 38 31 30 bajtów

Zapisano 1 bajt dzięki @ MartinBüttner

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

Nadużywa właściwości prostokątów. Wymaga wprowadzania, aby mieć końcowy znak nowej linii.

Wypróbuj online

Wyjaśnienie

Działa to w trzech częściach:

  • Pasujący >
  • Pasujący <
  • Dopasowywanie, ^a vto dlatego, że logika ^i vsą naprawdę takie same, tylko postacie.

Walidacja <

To jest proste:

O.*<

Odpowiada to Oznakom opcjonalnie poprzedzającym znaki nie-nowej linii, a następnie a<

Walidacja >

Jest to bardzo podobne do poprzedniego sposobu, z wyjątkiem sytuacji odwrotnej. Najpierw >dopasowywane jest a, a następnieO

Sprawdzanie poprawności ^iv

To było trudne do gry w golfa i wymagało od reklamy, aby zawsze były aktualne. Po pierwsze, czy to pasuje valbo O:

[vO]

Jeśli jest to ^, pierwszą napotkaną postacią powinna być O. To pasuje do pierwszego pasującego znaku. Następnie zliczamy liczbę .s następujących po nim do nowej linii:

(.*\n)

Następnie można podzielić na dwie części, omówię pierwszą:

Najpierw dopasowujemy do następujących O, używając:

[^O]*O

To opcjonalnie dopasowuje wszystkie Oznaki inne niż do Onapotkania an , jeśli to się powiedzie, to będzie kontynuowane ... jeśli nie, to dzieje się ...

Teraz próbuje znaleźć ^użycie:

[^^]*\^

^jest znakiem specjalnym w wyrażeniu regularnym, dlatego należy go uciec. [^^]pasuje do wszystkich znaków, z wyjątkiem ^tego, że działa tak samo jak powyżej, jeśli to się powiedzie, to dzieje się tak:

Więc teraz jeden z powyższych został pomyślnie dopasowany, \1sprawdza i sprawdza, czy grupa przechwytywania z poprzedniej (.*\n), ta grupa przechwytywania zapisała ilość .s po poprzedniej vlub Opoprzedniej, więc teraz \1po prostu sprawdza, czy ilość kropek w podobnie.

Downgoat
źródło
Możesz zapisać bajt, używając zamiast \n(Retina może obsługiwać kod źródłowy w ISO 8859-1.)
Martin Ender
@ MartinBüttner pomyślał, że \ n to tylko zamienniki, dzięki za wskazówkę!
Downgoat
nie, działa nigdzie w kodzie źródłowym. Po podzieleniu pliku na linie, pierwszą rzeczą, którą robi Retina, jest zamiana wszędzie, przed dalszym analizowaniem.
Martin Ender
9

Java (bez wyrażenia regularnego), 413 412 246 242 212 211 209 198 bajtów

Rywalizacja w golfa przy użyciu java ma mniej sensu niż udział w wyścigu Formuły 1 na rowerze, ale nie zawsze myślę, co ma jakiś sens.

Oto moje bardzo długie rozwiązanie Java Wersja w golfa

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

i nie golfił

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

Wygląda na to, że cała moja koncepcja była błędna, oto moje krótsze rozwiązanie

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

i wersja bez golfa

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

EDYCJA Przepisałem kod na szukanie „O”, teraz zawiera on jedną pętlę, jest znacznie krótszy, a także użyłem sugestii @Frozn, aby zastąpić niektóre znaki ich wartościami ascii.

W rezultacie kolejne 30 bajtów gryzie pył.

Kolejna sugestia @Frozn, a my jesteśmy kilka bajtów bliżej rozwiązania Python

Kolejne przepisanie upuść jedną pętlę i połącz dwie instrukcje if

użytkownik902383
źródło
1
+1 Możesz jednak usunąć odstęp między returni, (aby zapisać bajt. Spacja nie jest konieczna, gdy zwracana wartość znajduje się w nawiasie (lub cudzysłowach dla ciągów). Źródło ze wskazówek Java dotyczących gry w golfa.
Kevin Cruijssen
@KevinCruijssen niewiele oszczędza, ale dzięki :)
user902383
Chyba co najmniej (lub powinienem powiedzieć bajt) pomaga. ;) Poza tym nie sądzę, żeby Java kiedykolwiek wygrała wyzwanie w golfa. Nadal lubię robić wyzwania związane z golfem w Javie, zwłaszcza że obecnie pracuję z Javą w pracy.
Kevin Cruijssen
Można zastąpić znaki przez ich wartości ASCII: 'O' = 79, '>' = 62, '<' = 60, '^' = 94. Dla „v” jest to 118, ale to nie skraca kodu.
Frozn
@Frozn, jak powiedział Kevin, w każdym bajcie się liczy.
user902383
7

MATL (bez wyrażenia regularnego), 26 25 24 22 bajtów

'>v<^'XJymfX!tZpYswJm)

Wypróbuj online!

Zmodyfikowana wersja dla wszystkich przypadków testowych

Wyjaśnienie

        % 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
źródło
@LuisMendo Teraz, aby dowiedzieć się, jak się pozbyćJ
Suever
Nie znam MATL, więc może to być głupie pytanie, ale dlaczego 0 jest liczbą pierwszą?
Neil,
3
@Neil To litera 'O', a nie liczba 0. Kod ASCII dla listu 'O'to79
Luis Mendo,
Ugh, myślę, że nadal bym się nabrał, gdybyś zamiast tego szukał liczb nieparzystych.
Neil,
5

CJam (bez wyrażenia regularnego), 25

Wcześniejsze wersje były niepoprawne, na razie trzeba to zrobić:

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

Wypróbuj online

Wyjaśnienie:

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

Wypróbowałem kilka formuł matematycznych służących do rozróżnienia „dobrych” i „złych” ciągów i dla każdego rodzaju formuły próbowałem podłączyć różne liczby. Skończyło się na HbI%powyższym.

„dobre” ciągi dla oryginalnej siatki to „> O” i „O <” i dają wynik 17
„dobrych” ciągów dla transponowanej siatki to „vO” i „O ^” i dają wynik 15
„zły” ciągi dla obu siatek to: „>”, „<”, „^”, „v”, „O”, „”, „O>”, „Ov”, „<O”, „^ O” wyniki 8, 6, 4, 10, 7, 0, 1, 3, 1, 3

aditsu
źródło
3

Python 3 (bez wyrażenia regularnego), 184 bajty.

Brawo dla ewidentnego hakowania!

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
źródło
3

TSQL (sqlserver 2012) (bez wyrażenia regularnego), 358 bajtów

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)

Musiałem użyć funky zmiany linii w deklaracji, aby wymusić wykonanie wersji online (przypisanie wartości do zmiennych wejściowych i tak nie wpływa na obliczenie długości)

Wypróbuj online!

t-clausen.dk
źródło
2

JavaScript (ES6), 78 bajtów

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

Regexp oczywiście. Okazało się, że jest zasadniczo podobny do odpowiedzi Ruby.

Neil
źródło
2

Rubin, 71 55 54 bajtów

Rozwiązanie Regex, co oznacza, że ​​prawdopodobnie zostanie łatwo pobity przez Retinę lub Perla.

Zwraca numer indeksu (prawda), jeśli istnieje dopasowanie.

Teraz z podstępem podobnym do odpowiedzi @Downgoat Retina, dopasowując jednocześnie wiązki skierowane w dół i w górę.

->m{m=~/>\.*O|O\.*<|(?=[vO])(.{#{??+m=~/\n/}})+[O^]/m}
Wartość tuszu
źródło
2

JavaScript (ES6) (bez wyrażenia regularnego), 126 bajtów

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)

Gdzie \nreprezentuje dosłowny znak nowej linii.

Neil
źródło
2

Clojure (bez wyrażenia regularnego), 293 bajty

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

Nie czuje się świetnie. Proste rozwiązanie, znajdowanie indeksu odpowiednich znaków i obliczanie, czy są one w tej samej linii.

Możesz spróbować tutaj https://ideone.com/m4f2ra

Cliffroot
źródło
2

Python (bez wyrażenia regularnego), 105 bajtów

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]

zwraca True lub False

Najpierw paski ”. i „\ n” na końcach, tak aby interesujące znaki, „0 <> v ^”, były pierwszymi i ostatnimi znakami.

'>O<vO^'.find(t[0]+t[-1])//3- sprawdza, czy znaki są potencjalnie poprawnym układem. Zwraca wartość 0 dla „> O” lub „O <”, do 1 dla „vO” lub „O ^” i do -1 dla dowolnej innej wartości.

'\n'in t- sprawdza, czy znaki znajdują się w różnych wierszach,
len(t)%(s.find('\n')+1)!=1- sprawdza, czy są w różnych kolumnach, i
1- jest wartością domyślną

W notodwraca wynik wybrany z listy, więc returnwyrażenie jest równoważne:

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
źródło
2

Julia (bez wyrażenia regularnego), 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)

Funkcja działająca na tablicy znaków, normalizująca się przez obrót, usuwająca wiersze i kolumny zawierające tylko kropki przez indeksowanie zakresu i wreszcie sprawdzająca lokalizację „O”, biorąc pod uwagę, czy reszta b jest wektorem kolumny lub wiersza przy użyciu mnożenia macierzy.

Wypróbuj online

mschauer
źródło
1

Python 2 (bez wyrażenia regularnego), 268 bajtów

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

Wartości True i Falsy zwracane przez funkcję wynoszą odpowiednio 1 i 0.

Nie miałem jeszcze okazji grać w golfa. Szczerze mówiąc, nie mam nadziei na ten ...

Wszelkie sugestie będą mile widziane!

Daniel
źródło
1

C # (bez regexu), 282 bajty

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

Działa podobnie jak wersja Java, ale jest transpilowana i redukowana

Rozszerzony (w zestawie Objaśnienie):

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
źródło
0

C (ANSI) (bez wyrażenia regularnego), 237 bajtów

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

Rozszerzony:

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

Myślę, że podjąłem tutaj całkiem inne podejście w porównaniu do implementacji Java lub C #. Mam współrzędne „O” i strzałki ((c, d) i (x, y)), a następnie porównałem je, aby zobaczyć, czy strzałka wskazuje właściwy kierunek.

Zwraca 0, jeśli fałsz i 1, jeśli prawda

dj0wns
źródło
0

Grime v0.1 , 31 bajtów

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

Niezbyt interesujące rozwiązanie. Odbitki 1dla prawdziwych przypadków i 0dla fałszywych. Wypróbuj online!

Wyjaśnienie

Po prostu szukamy prostokąta wejściowego w poszukiwaniu wzoru o minimalnym rozmiarze (n × 1 lub 1 × n), który zawiera laser i cel we właściwej kolejności. n`Flag sprawia interpreter wydrukować liczbę meczów, z których nie zawsze będzie co najwyżej jeden. Reszta linii składa się z czterech wzorów oddzielonych |-znakami, co oznacza logiczne OR: prostokąt jest dopasowywany, jeśli pasuje do jednego ze wzorów. Wzory działają w następujący sposób:

\>.*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
źródło