Akankah berkas itu mengenai?

31

Laser menembakkan sinar lurus di salah satu dari empat arah ortogonal, ditunjukkan oleh <>^v. Tentukan apakah itu akan mengenai target Opada kotak persegi panjang.

Masing-masing akan menekan (Benar):

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

>O.
...

v....
O....

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

Ini akan kehilangan (Salah):

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

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


.O.
...
.v.

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

Input: Kisi persegi panjang ., berukuran setidaknya 2x2, dengan tepat satu target Odan satu laser salah satunya <>^v. Baris dapat berupa daftar string, array 2D atau daftar karakter bersarang, atau string yang dipisahkan baris baru dengan baris tambahan opsional.

Keluaran : Nilai kebenaran konsisten jika sinar laser mengenai target, dan nilai palsu konsisten jika meleset.

Saya akan mempertimbangkan kiriman yang tidak menggunakan ekspresi reguler (atau pencocokan string berbasis pola bawaan) sebagai kategori terpisah. Jika Anda menggunakan (no regex)nama bahasa, jawaban Anda akan muncul secara terpisah di leaderboard.

Tidak
sumber
8
Terkait
VisualMelon
6
Saya berharap Anda akan menyertakan cermin dengan /dan \ . Mungkin untuk pertanyaan lain ...
vsz
2
@Mego ... yang membuat tantangan ini lebih sederhana dan memungkinkan pendekatan yang sangat berbeda.
Martin Ender
2
@Mego saya tidak setuju; dengan logika itu, tantangan dunia haluan sederhana adalah duplikat dari puluhan tantangan lainnya pada saat yang sama. Bagaimanapun, terima kasih telah memberi tahu saya tentang kekuatan yang sekarang harus saya tutup / buka kembali kode tantangan golf, saya tidak menyadarinya.
aditsu
5
@Mego Meskipun pertanyaan ini adalah kasus khusus dari yang lain, saya tidak percaya itu merupakan penipuan karena jawaban menggunakan pendekatan yang sama sekali berbeda. Pada pertanyaan itu, mereka semua menghitung jalur yang diambil oleh balok. Portal dapat memindahkan jalur dari mana saja ke mana saja yang tampaknya tidak memungkinkan pintasan, dan reflektor sulit ditangani. Jawaban di sini sebagai gantinya sebagian besar memeriksa atau mencocokkan beberapa properti dari string input. Tentu, Anda dapat menyalin jawaban penelusuran jalur dari tantangan lain dan menghapus bit ekstra, tetapi metode ini berlebihan dan memberikan solusi panjang yang tidak perlu.
xnor

Jawaban:

27

Siput , 19 byte

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

Spesifikasi untuk yang satu ini dapat diimplementasikan sejelas mungkin, tanpa perlu pemikiran.

feersum
sumber
6
Bisakah Anda menambahkan penjelasan tentang cara kerjanya?
Dana Gugatan Monica
5
@QPaysTaxes Sampai feersum menyelesaikannya, mudah-mudahan ini akan membantu: Siput adalah bahasa pencocokan pola 2D. udlratur arah siput ke atas / bawah / kiri / kanan. |berfungsi seperti halnya di regex reguler, dan )tidak perlu tanda kurung terbuka yang cocok. Jadi, kode itu diterjemahkan secara langsung menjadi "Temukan salah satu v<>^dan atur arah dengan tepat, lalu coba cari O di arah itu."
FryAmTheEggman
Ya, apa yang dikatakan Eggman. Satu-satunya hal lain adalah itu ,seperti *regex.
feersum
13

Retina, 56 52 42 38 31 30 byte

Disimpan 1 byte berkat @ MartinBüttner

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

Menyalahgunakan properti persegi panjang. Membutuhkan input untuk memiliki baris baru tambahan.

Cobalah online

Penjelasan

Ini berfungsi dalam tiga bagian:

  • Sesuai >
  • Sesuai <
  • Cocok ^dan vini karena logika untuk ^dan vbenar-benar sama, hanya karakternya.

Memvalidasi <

Ini sederhana:

O.*<

Ini cocok dengan O, opsional diikuti oleh karakter non-baris baru, lalu a<

Memvalidasi >

Ini sama seperti cara sebelumnya kecuali sebaliknya. Pertama >dicocokkan, laluO

Memvalidasi ^danv

Ini sulit untuk golf dan mengambil iklan dari input selalu valid. Pertama, kami mencocokkan apakah itu vatau O:

[vO]

Jika itu adalah ^, karakter pertama yang ditemui harus a O. Jadi, ini cocok dengan karakter pertama yang cocok. Selanjutnya kita menghitung jumlah yang .mengikutinya hingga ke baris baru:

(.*\n)

Selanjutnya, ini bisa menjadi dua bagian, saya akan membahas yang pertama:

Jadi pertama, kami mencocokkan sampai yang berikut O, menggunakan:

[^O]*O

Ini secara opsional cocok dengan semua non- Okarakter sampai Oditemui, jika ini berhasil, maka itu berlanjut ... jika tidak, maka berikut ini terjadi ...

Sekarang, ia berusaha menemukan ^penggunaannya:

[^^]*\^

^adalah karakter khusus dalam regex sehingga perlu diloloskan. [^^]cocok dengan semua karakter kecuali ^, ini berfungsi sama seperti di atas, jika ini berhasil, maka berikut ini terjadi ...

Jadi sekarang, salah satu dari yang di atas telah cocok dengan sukses, \1memeriksa dan melihat apakah kelompok penangkap dari sebelumnya (.*\n), kelompok penangkap ini menyimpan jumlah .s setelah ada vatau Odari sebelumnya, jadi sekarang \1hanya memeriksa apakah jumlah titik dalam sama.

Downgoat
sumber
Anda dapat menyimpan byte dengan menggunakan alih-alih \n(Retina dapat menangani kode sumber dalam ISO 8859-1.)
Martin Ender
@ MartinBüttner pikir hanya pengganti, terima kasih atas tipnya!
Downgoat
tidak berfungsi di mana saja dalam kode sumber. Setelah memisahkan file menjadi beberapa baris, hal pertama yang dilakukan Retina adalah mengganti di mana - mana, sebelum melakukan penguraian lebih lanjut.
Martin Ender
9

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

Bersaing dalam tantangan golf menggunakan java kurang masuk akal daripada ikut serta dalam balap Formula 1 dengan sepeda, tapi saya tidak selalu melakukan pemikiran yang masuk akal.

Ini adalah solusi java saya yang sangat panjang versi 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]);}

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

Sepertinya seluruh konsep saya salah, ini solusi saya yang lebih pendek

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

dan versi yang tidak serigala

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 Saya menulis ulang kode untuk mencari 'O', sekarang ini berisi loop tunggal jauh lebih pendek, dan saya juga menggunakan saran @Frozn untuk mengganti beberapa karakter dengan nilai ascii mereka.

Hasilnya, 30 byte lainnya menggigit debu.

Saran lain dari @Frozn, dan kami beberapa byte lebih dekat ke solusi Python

Satu lagi tulis ulang satu putaran, dan gabungkan dua pernyataan if

pengguna902383
sumber
1
+1 Anda dapat menghapus ruang di antara returndan (untuk menghemat satu byte. Ruang tidak diperlukan ketika nilai pengembalian Anda ada di dalam tanda kurung (atau kutipan untuk Strings). Sumber dari tips golf-code Java.
Kevin Cruijssen
@KevinCruijssen tidak banyak menghemat, tapi terima kasih :)
user902383
Setiap bit (atau harus saya katakan byte) membantu saya kira. ;) Selain itu, saya tidak berpikir Java akan pernah memenangkan tantangan kode-golf. Saya masih suka melakukan tantangan kode-golf di Jawa, terutama karena saya saat ini bekerja dengan Java di tempat kerja.
Kevin Cruijssen
Anda dapat mengganti karakter dengan nilai ASCII mereka: 'O' = 79, '>' = 62, '<' = 60, '^' = 94. Untuk 'v' itu 118 tetapi itu tidak mempersingkat kodenya.
Frozn
@ Frezn seperti kata Kevin, dalam setiap byte penting.
user902383
7

MATL (tanpa regex), 26 25 24 22 byte

'>v<^'XJymfX!tZpYswJm)

Cobalah secara Online!

Versi modifikasi untuk semua kasus uji

Penjelasan

        % 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
sumber
@LuisMendo Sekarang untuk mencari tahu cara menyingkirkanJ
Suever
Saya tidak tahu MATL, jadi ini mungkin pertanyaan konyol, tapi mengapa 0 prima?
Neil
3
@Neil Ini surat 'O', bukan angka 0. Kode ASCII untuk surat 'O'adalah79
Luis Mendo
Ugh, kurasa aku masih akan dibodohi jika kamu mencari angka ganjil.
Neil
5

CJam (tanpa regex), 25

Versi sebelumnya salah, ini harus dilakukan untuk saat ini:

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

Cobalah online

Penjelasan:

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

Saya mencoba beberapa rumus matematika untuk membedakan antara string "baik" dan "buruk", dan untuk setiap jenis rumus saya mencoba memasukkan dalam berbagai angka. Saya berakhir dengan hal di HbI%atas.

string "baik" untuk grid asli adalah "> O" dan "O <" dan mereka memberikan hasil 17
string "baik" untuk grid yang dialihkan adalah "vO" dan "O ^" dan mereka memberikan hasil 15
"buruk" string untuk kedua kisi adalah: ">", "<", "^", "v", "O", "", "O>", "Ov", "<O", "<O" dan mereka memberikan hasil 8, 6, 4, 10, 7, 0, 1, 3, 1, 3

aditsu
sumber
3

Python 3 (tanpa regex), 184 byte.

Hore untuk 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'><'])
Morgan Thrapp
sumber
3

TSQL (sqlserver 2012) (tanpa 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)

Harus menggunakan linechange yang funky dalam deklarasi untuk memaksa versi online untuk mengeksekusinya (menetapkan nilai ke variabel input tidak memengaruhi perhitungan panjang)

Cobalah online!

t-clausen.dk
sumber
2

JavaScript (ES6), 78 byte

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

Regexp tentu saja. Ternyata pada prinsipnya mirip dengan jawaban Ruby.

Neil
sumber
2

Ruby, 71 55 54 byte

Solusi Regex, yang artinya mungkin akan mudah dikalahkan oleh Retina atau Perl.

Mengembalikan nomor indeks (benar) jika ada kecocokan.

Sekarang dengan trik yang mirip dengan @Downgoat Retina menjawab, cocok dengan balok turun dan naik pada saat yang sama.

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

JavaScript (ES6) (tanpa 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)

Dimana \nmewakili karakter baris baru literal.

Neil
sumber
2

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

Tidak terasa enak. Solusi langsung, menemukan indeks karakter yang sesuai dan menghitung jika mereka berada di baris yang sama.

Anda dapat mencobanya di sini https://ideone.com/m4f2ra

cliffroot
sumber
2

Python (tanpa 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]

mengembalikan Benar atau Salah

Pertama, strip '.' dan '\ n' dari ujung sehingga karakter yang menarik, '0 <> v ^', adalah karakter pertama dan terakhir.

'>O<vO^'.find(t[0]+t[-1])//3- memeriksa apakah karakter adalah pengaturan yang berpotensi valid. Mengevaluasi ke 0 untuk '> O' atau 'O <', ke 1 untuk 'vO' atau 'O ^', dan ke -1 untuk hal lain.

'\n'in t- memeriksa apakah karakter berada di baris yang berbeda,
len(t)%(s.find('\n')+1)!=1- memeriksa apakah mereka berada di kolom yang berbeda, dan
1- adalah default

The notmembalikkan hasil yang dipilih dari daftar, sehingga returnekspresi setara dengan:

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
sumber
2

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

Fungsi yang beroperasi pada larik karakter, dinormalisasi dengan rotasi, menghapus baris dan kolom yang hanya berisi titik-titik dengan pengindeksan rentang dan akhirnya memeriksa lokasi 'O' dengan mempertimbangkan jika sisanya b adalah vektor kolom atau baris menggunakan perkalian matriks.

Cobalah online

mschauer
sumber
1

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

Nilai Truthy dan Falsy yang dikembalikan oleh fungsi masing-masing adalah 1 dan 0.

Saya belum memiliki kesempatan untuk bermain golf. Jujur, saya tidak terlalu berharap untuk yang satu ini ...

Setiap saran akan sangat dihargai!

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

Bekerja seperti versi java tetapi diubah dan dikurangi

Diperluas (Penjelasan termasuk):

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
sumber
0

C (ANSI) (Tanpa 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;}

Diperluas:

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

Saya pikir saya mengambil pendekatan yang berbeda di sini dibandingkan dengan implementasi Java atau C #. Saya mendapatkan koordinat 'O' dan panah ((c, d) dan (x, y)) dan kemudian membandingkannya untuk melihat apakah panah menunjuk ke arah yang benar.

Mengembalikan 0 jika salah dan 1 jika benar

dj0wns
sumber
0

Grime v0.1 , 31 byte

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

Bukan solusi yang sangat menarik. Mencetak 1untuk contoh yang benar, dan 0untuk yang salah. Cobalah online!

Penjelasan

Kami hanya mencari persegi panjang input untuk pola ukuran minimal (n × 1 atau 1 × n) yang berisi laser dan target dalam urutan yang benar. The n`bendera membuat penafsir mencetak jumlah pertandingan, yang akan selalu ada paling banyak satu. Sisa garis terdiri dari empat pola yang dipisahkan oleh |-karakter, yang berarti logika OR: persegi panjang dicocokkan jika cocok dengan salah satu pola. Polanya bekerja sebagai berikut:

\>.*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
sumber