Işın çarpacak mı?


31

Bir lazer, ile gösterilen dört ortogonal yönün birinde düz bir ışını vurur <>^v. ODikdörtgen bir ızgara üzerinde hedefe isabet edeceğini belirleyin .

Bunların her biri (Doğru) isabet edecektir:

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

>O.
...

v....
O....

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

Bunlar özleyecektir (Yanlış):

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

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


.O.
...
.v.

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

Giriş: Dikdörtgen bir ızgara. Tam olarak bir hedef Ove bir tane lazer olan , en az 2x2 büyüklüğünde<>^v . Satırlar, bir dize listesi, bir 2D dizi veya iç içe karakter listesi veya isteğe bağlı izleyen bir yeni satır içeren tek bir yeni satır ayrılmış dize olabilir.

Çıktı : Lazer ışını hedefe çarparsa tutarlı bir değer, ıskalarsa tutarlı bir sahte değer.

Düzenli ifadeler (veya yerleşik desen tabanlı dize eşleme) kullanmayan gönderimleri ayrı bir kategori olarak ele alacağım. (no regex)Dil isminin arkasına koyarsanız , cevabınız afiş üzerinde ayrı ayrı görünecektir.



6
Aynaları /ve ile eklemeyi umuyordum \ . Belki başka bir soru için ...
vsz

2
@Mego ... bu meydan okumayı çok daha basit hale getirir ve çok farklı yaklaşımlara izin verir.
Martin Ender

2
@Mego Ben katılmıyorum; Bu mantığa göre, merhaba dünyadaki en basit meydan okuma aynı zamanda düzinelerce başka mücadelenin kopyası. Her neyse, bana kod golf zorluklarını kapatmak / yeniden açmak zorunda olduğum gücü bildirdiğin için teşekkürler, bunun farkında değildim.
aditsu

5
@Mego Bu soru bir diğeri için özel bir durum olsa da, cevaplar tamamen farklı yaklaşımlar kullandığı için bir dupe olduğuna inanmıyorum. Bu soruda, hepsi ışın demetinin yolunu hesaplar. Portallar yolu herhangi bir yerden bir kısayol gibi görünmeyen herhangi bir yere götürebilir ve reflektörlerin kullanımı zor. Buradaki cevaplar çoğunlukla girdi dizesinin bazı özelliklerini kontrol eder veya eşler. Elbette, yolu takip eden bir cevabı diğer zorluklardan kopyalayabilir ve ekstra bitleri kaldırabilirsiniz, ancak bu yöntem fazla önemlidir ve gereksiz yere uzun bir çözüm sunar.
xnor

Yanıtlar:


27

Salyangoz , 19 bayt

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

Bunun için teknik özellik mümkün olduğu kadar uygulanabilir, düşünmeye gerek yoktur.


6
Bunun nasıl çalıştığına dair bir açıklama ekleyebilir misiniz?
Fon Monica'nın Davası

5
@QPaysTaxes Feersum etrafına gelene kadar, umarım bu yardımcı olacaktır: Salyangozlar 2B kalıp eşleştirme dilidir. udlrSalyangoz yönünü yukarı / aşağı / sola / sağa ayarlayın. |normal regex'te olduğu gibi çalışır ve )uygun bir parantez gerektirmez. Bu yüzden kod doğrudan doğrudan "Bir tanesini bul v<>^ve yönü uygun şekilde ayarla, sonra bu yönde bir O bulmaya çalış" anlamına gelir.
FryAmTheEggman

Evet, Eggman'ın söylediği. Diğer tek şey, regex ,gibi olmasıdır *.
feersum

13

Retina, 56 52 42 38 31 30 bayt

@ MartinBüttner sayesinde 1 bayt kaydedildi

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

Dikdörtgenlerin özelliklerini kötüye kullanır. Sonunda yeni bir satıra sahip olmak için giriş yapılması gerekir.

Çevrimiçi deneyin

açıklama

Bu üç bölümden oluşmaktadır:

  • Eşleştirme >
  • Eşleştirme <
  • Eşleşme ^ve vbunun nedeni, mantığın ^ve vgerçekten aynı olması, sadece karakterlerdir.

doğrulama <

Bu basit:

O.*<

Bu Oisteğe bağlı olarak yeni satır olmayan karakterlerin ardından gelen bir<

doğrulama >

Bu, tam tersi dışında bir önceki yöntemle aynı. Önce a >eşleştirilir, sonraO

Doğrulanıyor ^vev

Bu golf oynamak zordu ve girdilerin her zaman geçerli olmasını ilan ediyordu. Öncelikle, bu ister eşleşecek vbir veya O:

[vO]

Eğer bir ise ^, karşılaşılan ilk karakter a olmalıdır O. Böylece, bu eşleşen ilk karakterle eşleşir. Daha .sonra, onu newline kadar takip eden miktarları sayarız :

(.*\n)

Sonra, bu iki bölüme geçebilir, ilkini örteceğim:

İlk önce, aşağıdakine kadar aşağıdakileri Okullanarak eşleşiyoruz:

[^O]*O

Bu isteğe bağlı olarak , bir karşılaşana Okadar tüm karakter olmayan karakterlerle eşleşir O, eğer başarılı olursa, sonra devam eder ... değilse, sonra aşağıdakiler olur ...

Şimdi, ^kullanarak bulmaya çalışır :

[^^]*\^

^regex'te özel bir karakter olduğundan, kaçması gerekir. [^^]dışındaki tüm karakterlerle eşleşir ^, bu yukarıdakiyle aynı şekilde çalışır, eğer başarılı olursa, sonra şu olur ...

Şimdi, yukarıdakilerden biri başarılı bir şekilde eşleşti \1, önce yakalama grubunu kontrol eder ve görür (.*\n), bu yakalama grubunun .önceki vya da önceki sonrasında bulunan s miktarını Osaklarsa, şimdi \1sadece noktadaki noktaların miktarını kontrol eder. aynı.


Bunun yerine bir bayt kaydedebilirsiniz \n(Retina ISO 8859-1'deki kaynak kodunu kullanabilir.)
Martin Ender

@ MartinBüttner sadece değiştirmelerde olduğunu düşündü , bahşiş için teşekkürler!
Downgoat

hayır, kaynak kodun herhangi bir yerinde çalışır. Dosyayı satırlara böldükten sonra, Retina'nın yaptığı ilk şey , daha fazla ayrıştırma yapmadan önce her yeri değiştirmektir .
Martin Ender

9

Java (regex yok), 413 412 246 242 212 211 209 198 bayt

Java kullanarak golf mücadelesinde yarışmak, bisikletle Formula 1 yarışında yer almaktan daha az mantıklı, ama her zaman bir anlam ifade ettiğini düşünmüyorum.

İşte benim son derece uzun java çözümüm Golf sürümü

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

ve asılsız

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

Bütün konseptim yanlıştı gibi görünüyor, işte benim kısa çözümüm

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

ve asılsız versiyon

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

DÜZENLE 'O' için kod yazdım, şimdi tek döngü çok daha kısa ve ayrıca bazı karakterleri ascii değerleriyle değiştirmek için @Frozn önerisini kullandım.

Sonuç olarak, başka bir 30 bayt tozu ısırır.

@Frozn'dan bir öneri daha ve Python çözümüne yakın çift baytız.

Başka bir yeniden yazma bir döngü düşürür ve iki if ifadesini birleştirir


1
+1 Yine de, bir bayt kaydetmek için returnve arasındaki boşluğu kaldırabilirsiniz (. Dönüş değeriniz parantez içinde olduğunda (veya Dizeler için tırnak işaretleri) boşluk gerekmez. Java kodu golf ipuçları kaynak.
Kevin Cruijssen

@KevinCruijssen fazla tasarruf etmiyor, fakat teşekkürler :)
user902383

Her küçük parça (veya bayt demeliyim) sanırım yardımcı olur. ;) Ayrıca, Java'nın zaten bir kod golf mücadelesini kazanacağını da sanmıyorum. Yine de Java'da kod-golf mücadelesi yapmaktan hoşlanıyorum, özellikle şu anda işyerinde Java ile çalışıyorum.
Kevin Cruijssen

Onların ASCII değerine göre karakter değiştirebilirsiniz: 'O' = 79, '>' = 62, '<' = 60, '^' = 94. 'V' için 118'tir ancak bu kodu kısaltmaz.
Frozn

@Frozn'ın dediği gibi her bayt sayılır.
user902383

7

MATL (düzenli ifade yok), 26 25 24 22 bayt

'>v<^'XJymfX!tZpYswJm)

Çevrimiçi Deneyin!

Tüm test durumları için değiştirilmiş versiyon

açıklama

        % 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 Şimdi nasıl kurtulacağınıza karar vermek içinJ
Suever

MATL'yi tanımıyorum, bu yüzden aptalca bir soru olabilir, ama neden 0 asal?
Neil

3
@Neil Bu mektup 'O', sayı değil 0. Harfin ASCII kodu 'O'olan79
Luis Mendo

Ugh, sanırım bunun yerine tuhaf numaralar ararsanız hala kandırılmış olurdum.
Neil

5

CJam (regex yok), 25

Önceki sürümler yanlıştı, bunun şimdilik yapılması gerekiyor:

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

Çevrimiçi deneyin

Açıklama:

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

"İyi" ve "kötü" dizgileri birbirinden ayırmak için birkaç matematiksel formül denedim ve her formül türü için çeşitli sayıları girmeyi denedim. Ben HbI%yukarıdaki ile sona erdi .

orjinal ızgara için "iyi" karakter dizileri "> O" ve "O <" dir ve 17 sonucunu verirler.
"iyi" karakter dizisi "vO" ve "O ^" olurlar ve 15
"kötü" sonucunu verirler. Her iki ızgara için de dizeler şunlardır: ">", "<", "^", "v", "O", "", "O>", "Ov", "<O", "^ O" sonuçlar 8, 6, 4, 10, 7, 0, 1, 3, 1, 3


3

Python 3 (düzenli ifade yok), 184 bayt.

Eval hack için Yaşasın!

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) (düzenli ifade yok), 358 bayt

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)

Çevrimiçi sürümü çalıştırmaya zorlamak için bildirgede funky linechange kullanmak zorunda kaldı (girdi değişkenlerine değer atamak yine de uzunluk hesaplamasını etkilemiyor)

Çevrimiçi deneyin!



2

JavaScript (ES6), 78 bayt

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

Tabii ki regexp. Ruby cevabı prensip olarak benzer olduğu ortaya çıktı.


2

Ruby, 71 55 54 bayt

Regex çözümü, muhtemelen Retina veya Perl tarafından kolayca yenileceği anlamına geliyor.

Bir eşleşme varsa bir dizin numarası (truthy) verir.

Şimdi @Downgoat Retina cevabına benzer bir hile ile aynı anda aşağı ve yukarı kirişler için uygun.

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

2

JavaScript (ES6) (düzenli ifade yok), 126 bayt

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)

Nerede \nliteral satır karakteri temsil eder.


2

Clojure (düzenli ifade yok), 293 bayt

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

Harika hissetmiyor. Basit çözüm, karşılık gelen karakterlerin dizinini bulmak ve aynı satırda olup olmadıklarını hesaplamak.

Burada deneyebilirsiniz https://ideone.com/m4f2ra


2

Python (düzenli ifade yok), 105 bayt

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]

Doğru veya Yanlış döndürür

İlk önce '.' ve '\ n' uçlarından itibaren, ilgilenilen karakterler, '0 <> v ^', ilk ve son karakterlerdir.

'>O<vO^'.find(t[0]+t[-1])//3- karakterlerin potansiyel olarak geçerli bir düzenleme olup olmadığını kontrol eder. '> O' veya 'O <' için 0, 'vO' veya 'O ^' için 1, başka bir şey için -1 olarak değerlendirir.

'\n'in t- karakterlerin farklı satırlarda
len(t)%(s.find('\n')+1)!=1olup olmadığını kontrol eder , - farklı sütunlarda olup olmadığını kontrol eder ve
1- varsayılandır

notBöylece ters çevirir sonucu, listeden seçilen returnsentezleme eşdeğerdir:

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 (regex yok), 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)

Bir karakter dizisi üzerinde çalışan, döndürerek normalleştiren, aralık indeksleme yoluyla sadece noktalar içeren satırları ve sütunları kaldırarak ve son olarak, b'nin matris çarpımını kullanan bir sütun veya satır vektörü olup olmadığını göz önünde bulundurarak son olarak 'O' konumunu kontrol etmek.

Çevrimiçi deneyin


1

Python 2 (düzenli ifade yok), 268 bayt

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

İşlev tarafından döndürülen Truthy ve Falsy değerleri, sırasıyla 1 ve 0'dır.

Henüz golf oynama şansım olmadı. Açıkçası, bunun için fazla umutlu değilim ...

Herhangi bir öneri çok takdir edilecektir!


1

C # (Düzenli İfade Yok), 282 bayt

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

Java sürümü gibi çalışır ancak kopyalanır ve azaltılır

Genişletilmiş (Açıklama dahil):

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) (Düzenli giriş yok), 237 bayt

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

Sanırım burada Java veya C # uygulamalarıyla karşılaştırıldığında farklı bir yaklaşım benimsedim. 'O' ve ok ((c, d) ve (x, y)) koordinatlarını aldım ve ardından okun doğru yöne işaret edip etmediğini görmek için karşılaştırdım.

False olursa 0, true ise 1 döndürür


0

Grime v0.1 , 31 bayt

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

Çok ilginç bir çözüm değil. Baskılar 1truthy örnekleri, için ve 0falsy olanlar için. Çevrimiçi deneyin!

açıklama

Giriş dikdörtgeni, lazeri ve hedefi doğru sırayla içeren en az boyutlu (n × 1 veya 1 × n) bir kalıp için ararız. n`Bayrak tercüman her zaman en biri olacak olan maçların sayısını yazdırmak yapar. Çizginin geri kalanı, |karakterlerle ayrılmış dört desenden oluşur; bu, mantıksal bir OR anlamına gelir: desenlerden biriyle eşleşirse bir dikdörtgen eşleşir. Desenler şu şekilde çalışır:

\>.*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 "^"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.