ビームは当たるでしょうか?


31

レーザーは、で示される4つの直交方向のいずれかで直線ビームを照射します<>^vO長方形のグリッド上のターゲットにヒットするかどうかを判断します。

これらのそれぞれがヒットします(True):

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

>O.
...

v....
O....

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

これらは見逃します(False):

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

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


.O.
...
.v.

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

入力:.少なくとも2x2のサイズの長方形のグリッドで、ターゲットはO1つで、レーザーは1つのみです<>^v。行は、文字列のリスト、2D配列または文字のネストされたリスト、またはオプションの末尾改行を含む単一の改行で区切られた文字列です。

出力:レーザービームがターゲットに到達した場合は一貫した真実の値、見逃した場合は一貫した偽の値。

正規表現(または組み込みのパターンベースの文字列照合)を別のカテゴリとして使用しないサブミッションを検討します。(no regex)言語名の後に置くと、回答がリーダーボードに個別に表示されます。



6
とでミラーを含めることを望ん/でいました\ 。たぶん別の質問のために
...-vsz

2
@Mego ...これにより、この課題がはるかに簡単になり、非常に異なるアプローチが可能になります。
マーティンエンダー

2
@Mego私は同意しません。その論理により、単純な世界の課題は、同時に他の多数の課題の複製です。とにかく、コードチャレンジのコードを閉じたり再開したりする必要があることを教えてくれてありがとう、私はそれを知りませんでした。
aditsu

5
@Megoこの質問は他の質問の特殊なケースですが、答えがまったく異なるアプローチを使用しているため、私はそれがだましだとは思いません。その質問で、彼らはすべて、ビームがたどる経路を計算します。ポータルは、ショートカットを許可していないように見える場所にどこからでもパスを移動でき、リフレクターは扱いが難しいです。代わりに、ここでの回答は、入力文字列の一部のプロパティをほとんどチェックまたは一致させます。もちろん、他のチャレンジからパストレーシングの回答をコピーして余分なビットを削除することもできますが、この方法は過剰であり、不必要に長いソリューションを提供します。
xnor

回答:


27

カタツムリ、19バイト

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

この仕様は可能な限り文字通り実装でき、何も考える必要はありません。


6
これがどのように機能するかの説明を追加できますか?
ファンドモニカの訴訟

5
@QPaysTaxes feersumがそれに到達するまで、これが役立つことを願っています:Snailsは2Dパターンマッチング言語です。udlrカタツムリの方向を上/下/左/右に設定します。|通常の正規表現と同じように機能し)、対応する開き括弧は必要ありません。そのため、コードは「1つv<>^を見つけて適切に方向を設定し、その方向でOを見つけようとします」に直接変換されます。
FryAmTheEggman

ええ、エッグマンが言ったこと。唯一の他のことは、正規表現の,ようなものです*
feersum

13

網膜、56 52 42 38 31 30バイト

@MartinBüttnerのおかげで1バイト節約

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

長方形のプロパティを乱用します。入力に末尾の改行が必要です。

オンラインで試す

説明

これは3つの部分で機能します。

  • マッチング >
  • マッチング <
  • マッチング^vのロジックので、これは^とはv、本当にただの文字と同じです。

検証中 <

これは簡単です:

O.*<

これはO、に一致し、オプションで非改行文字が続き、次に<

検証中 >

これは、他の方法を除いて、以前の方法とほとんど同じです。最初にa >が一致し、次にO

検証^v

これはゴルフにとって困難であり、入力が常に有効であることを宣伝しました。まず、次のvいずれかで一致しOます:

[vO]

の場合^、最初に遭遇する文字はでなければなりませんO。したがって、これは一致する最初の文字に一致します。次に.、改行までのs の量をカウントします。

(.*\n)

次に、これは2つの部分に分けられます。最初の部分について説明します。

したがって、最初に、次Oを使用して一致します:

[^O]*O

これは、オプションでが検出さOれるまですべての非文字に一致し、O成功した場合は続行します。そうでない場合は、次のようになります...

今、それは^使用を見つけようとします:

[^^]*\^

^は正規表現の特殊文字なので、エスケープする必要があります。[^^]を除くすべての文字に一致します^。これは上記と同じように機能し、これが成功すると、次のようになります...

したがって、上記のいずれかが正常に一致し、\1beforeからのキャプチャグループがチェック(.*\n)され、このキャプチャグループ.が前vまたは後のs の量を保存しているかどうかが確認されるため、ドットの量が同じ。O\1


代わりに\n(RetinaはISO 8859-1のソースコードを処理できます。)
Martin Ender

@MartinBüttner は交換の\ nだけだと思っていました、ヒントをありがとう!
ダウンゴート

いいえ、ソースコードのどこでも機能します。ファイルを行に分割した後、Retinaが最初に行うことは、さらに解析を行う前に、どこでも置き換えます。
マーティンエンダー

9

Java(正規表現なし)、413 412 246 242 212 211 209 198バイト

javaを使用してゴルフチャレンジに参加することは、自転車でのF1レースに参加することよりも意味がありませんが、私は常に理にかなっているとは限りません。

これは私の非常に長いJavaソリューションのゴルフバージョンです

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

そして、未調理

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

私のコンセプト全体が間違っていたようです、ここに私の短い解決策があります

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

および非ゴルフバージョン

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

編集 'O'を探すためにコードを書き直しました。単一ループがはるかに短くなり、@ Froznの提案を使用して一部の文字をASCII値に置き換えました。

その結果、別の30バイトが塵をかみます。

@Froznからの別の提案。Pythonソリューションに数バイト近づいています。

別の書き換えでは、1つのループを削除し、2つのifステートメントを組み合わせます


1
+1 returnとの間のスペースを削除して(、バイトを節約することもできます。戻り値が括弧(または文字列の引用符)内にある場合、スペースは必要ありません。Javaコードゴルフのヒントからのソース。
ケビンCruijssen

@KevinCruijssenはあまり節約しませんが、ありがとう
ございます

少しずつ(または、バイトと言うべきです)推測に役立ちます。;)それに、とにかくJavaがコードゴルフの挑戦に勝つとは思わない。しかし、特に仕事でJavaを使用しているので、Javaでコードゴルフのチャレンジをするのは今でも好きです。
ケビンCruijssen

あなたはそれらのASCII値で文字を置き換えることができます'O' = 79'>' = 62'<' = 60'^' = 94。「v」の場合は118ですが、コードは短くなりません。
Frozn

ケビンが言ったように、@ Froznはすべてのバイト数で。
user902383

7

MATL(正規表現なし)、26 25 24 22バイト

'>v<^'XJymfX!tZpYswJm)

オンラインでお試しください!

すべてのテストケースの修正バージョン

説明

        % 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を取り除く方法を理解するためにJ
-Suever

私はMATLを知らないので、これはばかげた質問かもしれませんが、なぜ0素なのですか?
ニール

3
@Neil 'O'数字ではなく文字0です。手紙のASCIIコード'O'79
ルイスメンドー

代わりに、奇数を探していたら、私はまだだまされていただろうと思います。
ニール

5

CJam(正規表現なし)、25

以前のバージョンは間違っていました、今のところこれはやらなければなりません:

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

オンラインで試す

説明:

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

「良い」文字列と「悪い」文字列を区別するためにいくつかの数式を試してみました。また、数式の種類ごとにさまざまな数字を挿入してみました。私はHbI%上記で終わった。

元のグリッドの「良い」文字列は「> O」と「O <」であり
、転置されたグリッドの17の「良い」文字列は「vO」と「O ^」であり、結果は15
「悪い」です両方のグリッドの文字列は、「>」、「<」、「^」、「v」、「O」、「」、「O>」、「Ov」、「<O」、「^ O」であり、結果8、6、4、10、7、0、1、3、1、3


3

Python 3(正規表現なし)、184バイト。

評価ハッキングに感謝します!

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)(正規表現なし)、358バイト

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)

宣言でファンキーなlinechangeを使用して、オンラインバージョンで強制的に実行する必要がありました(入力変数に値を割り当てても長さの計算には影響しません)

オンラインでお試しください!



2

JavaScript(ES6)、78バイト

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

もちろん正規表現。原則としてRubyの回答に似ていることが判明しました。


2

ルビー、71 55 54バイト

正規表現ソリューション。これは、おそらくRetinaまたはPerlに簡単に破られることを意味します。

一致する場合、インデックス番号(真)を返します。

@Downgoat Retinaアンサーと同様のトリックを使用して、ダウンビームとアップビームを同時にマッチングします。

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

2

JavaScript(ES6)(正規表現なし)、126バイト

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)

where \nは、リテラルの改行文字を表します。


2

Clojure(正規表現なし)、293バイト

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

気分が良くない。対応する文字のインデックスを見つけ、それらが同じ行にあるかどうかを計算する簡単な解決策。

ここで試すことができますhttps://ideone.com/m4f2ra


2

Python(正規表現なし)、105バイト

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]

TrueまたはFalseを返します

最初に、「。」を削除します 対象の文字「0 <> v ^」が最初と最後の文字になるように、末尾から「\ n」。

'>O<vO^'.find(t[0]+t[-1])//3-文字が潜在的に有効な配置であるかどうかを確認します。「> O」または「O <」の場合は0、「vO」または「O ^」の場合は1、その他の場合は-1に評価されます。

'\n'in t-文字が異なる行にある
len(t)%(s.find('\n')+1)!=1かどうかを確認します-- 文字が異なる列にあるかどうかを確認します
1します-そしてデフォルトです

not結果はリストから選択反転は、そのreturn式は同等です:

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

ジュリア(正規表現なし)、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)

文字の配列を操作する関数、回転による正規化、範囲のインデックス付けによるドットのみを含む行と列の削除、および剰余bが行列乗算を使用する列または行ベクトルである場合を考慮した 'O'の位置の最終的なチェック

オンラインで試す


1

Python 2(正規表現なし)、268バイト

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およびFalsyの値は、それぞれ1および0です。

まだゴルフをする機会がありません。正直なところ、私はこれにあまり期待していません...

どんな提案でも大歓迎です!


1

C#(正規表現なし)、282バイト

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バージョンと同様に機能しますが、トランスコンパイルおよび削減

拡張(説明を含む):

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)(正規表現なし)、237バイト

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

拡張:

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

ここでは、JavaまたはC#の実装と比較して、かなり異なるアプローチを採用したと思います。「O」と矢印((c、d)と(x、y))の座標を取得し、それらを比較して、矢印が正しい方向を指しているかどうかを確認しました。

falseの場合は0、trueの場合は1を返します


0

グライムv0.1、31バイト

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

非常に興味深い解決策ではありません。プリント1truthyインスタンスの、および0falsyもののために。オンラインでお試しください!

説明

入力長方形を検索して、レーザーとターゲットを正しい順序で含む最小サイズ(n×1または1×n)のパターンを探します。このn`フラグにより​​、インタープリターは一致の数を印刷しますが、一致するのは常に最大1つです。行の残りの部分は、- |文字で区切られた4つのパターンで構成されます。これは論理ORを意味します。長方形は、パターンの1つと一致した場合に一致します。パターンは次のように機能します。

\>.*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 "^"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.