シュレーディンガーのレーザー


24

うんざり小さな家畜に実験し、ノーベル賞を受賞したエルヴィン・シュレーディンガーは、最寄りのレーザーを見つけて、その代わりのもので、それを撮影することを決定しました。なぜなら...科学!

説明

次の2つのレーザーが通過する点や、レーザビームの大きさが与えられます、そしてあなたは、レーザービームがどこかを決定しなければならない必要があり、行っている可能性が行っている、とができませんでした行っています。

レーザービームは、水平、垂直、または斜めにすることができます。サイズ1のレーザービームの場合、それぞれ次のようになります。

       #  #
       #   #
#####  #    #
       #     #
       #      #

斜めのレーザービームも反転できます。サイズ2のレーザービームは次のようになります。

       ###  ##
#####  ###  ###
#####  ###   ###
#####  ###    ###
       ###     ##

一般に、サイズ(n)のレーザービームを取得するには、サイズ(n-1)のレーザービームを取得し、両側にサイズ(1)のレーザービームを追加します。最後の例として、サイズ3のすべての可能なレーザービームを同じ「ボード」上に示します。

###.....#####.....##
####....#####....###
#####...#####...####
.#####..#####..#####
..#####.#####.#####.
...###############..
....#############...
.....###########....
####################
####################
####################
####################
####################
.....###########....
....#############...
...###############..
..#####.#####.#####.
.#####..#####..#####
#####...#####...####
####....#####....###

この「ボード」の寸法は常に20x20(文字数)です。

入力

プログラムには、入力として5つの整数が与えられます。それらは、順番に、x 1、y 1、x 2、y 2、およびレーザービームのサイズです。彼らは正確にその順序で撮影する必要があります。必要に応じて、配列(タプル、リスト)、または2つの値を格納するその他の組み込みデータ型として、順序付けられた(x、y)ペアを使用できます。

入力として与えられた2つのポイントは両方ともボード内にあり、それらは異なることが保証されています(つまり、2つのポイントが同じになることはありません)。レーザービームのサイズはにバインドされてい1 ≤ size < 20ます。両方のポイントを通過する少なくとも1つの可能なレーザービームが常に存在します。

出力

プログラムは、次の文字の20x20グリッドを出力する必要があります。

  • # 2つのポイントを通過するすべての可能なレーザービームがこのポイントも通過する場合。
  • . 2点とこの点を通過するレーザービームがない場合。
  • ? 可能性のあるレーザービームのすべてではなく一部がこのポイントを通過する場合。
  • Xこれが2つの元の入力ポイントのいずれかである場合(これはをオーバーライドします#)。

テストケース

7、7、11、3、1

..............#.....
.............#......
............#.......
...........X........
..........#.........
.........#..........
........#...........
.......X............
......#.............
.....#..............
....#...............
...#................
..#.................
.#..................
#...................
....................
....................
....................
....................
....................

18、18、1、1、2

#??.................
?X??................
??#??...............
.??#??..............
..??#??.............
...??#??............
....??#??...........
.....??#??..........
......??#??.........
.......??#??........
........??#??.......
.........??#??......
..........??#??.....
...........??#??....
............??#??...
.............??#??..
..............??#??.
...............??#??
................??X?
.................??#

10、10、11、10、3

?????..????????..???
??????.????????.????
????????????????????
????????????????????
.???????????????????
..??????????????????
????????????????????
????????????????????
????????????????????
????????????????????
??????????XX????????
????????????????????
????????????????????
????????????????????
????????????????????
..??????????????????
.???????????????????
????????????????????
????????????????????
??????.????????.????

3、3、8、10、4

??????????..........
??????????..........
??????????..........
???X??????..........
???##?????..........
???###????..........
????###????.........
.????###????........
..????###????.......
..?????##?????......
..??????X??????.....
..??????????????....
..???????????????...
..????????????????..
..?????????????????.
..??????????????????
..??????????????????
..????????.?????????
..????????..????????
..????????...???????

テストケースは、垂直方向のスペースを節約するために、スタックスニペット内にある次のRubyスクリプトを使用して生成されました。

ルール

  • プログラムは、30秒未満で(妥当なマシンで)各テストケースを解決できる必要があります。私のテストRubyプログラムは、ほぼ瞬時にすべてのテストケースを解決したので、これはより健全なチェックです。

  • これはであるため、最短のソリューションが優先されます。


2
ここで使用されている用語は、最初私をつまずかせました。レーザーは通常レーザービームを生成するデバイスを指すと思います。ここであなたが表現しているのは、まさにビームです。これは、実際のレーザーを表すものではなく、ビームを生成するデバイスでしょうか?
レトコラディ

2
最後のテストケースは間違っているようです。サイズ4のレーザーの幅は9ピクセルにする必要があります。垂直トラックは少なくともその幅である必要がありますが、実際はより狭くなります。
レベルリバーセント

1
@steveverrillサイズ4は7ピクセル幅です。ピクセル単位の幅は2 * size - 1です。サイズ1は1ピクセル、サイズ2は3ピクセル、サイズ3は5ピクセル(上記の例を参照)、サイズ4は7ピクセルです。
レトコラディ

2
シュレーディンガーがこの課題にどのように関係しているかはわかりません。
user12205

1
@JonasDralle繰り返しますが、時間制限は主に健全性チェックに過ぎず、ほぼすべての提出がそれよりはるかに短い時間で完了することが期待されています。
ドアノブ

回答:


5

C、291の 280 277 265バイト

x,y,A,C,B,D,a,c,b,d,w,s,t;T(i){return abs(i)<2*w-1;}U(j,k){s+=T(j-k)*T(j)*T(k);t*=T(j-k)*j*k<1;}main(){for(scanf("%i%i%i%i%i",&a,&b,&c,&d,&w);y<20;y+=!x)s=0,t=1,U(A=a-x,C=c-x),U(B=b-y,D=d-y),U(A-B,C-D),U(A+B,C+D),putchar((x=++x%21)?".?#x"[!!s+t+(!A*!B+!C*!D)]:10);}

以下を使用してコンパイル/実行できます。

gcc laser.c -o laser && echo "10 10 11 10 3" | 。/レーザ

以下に、空白と説明コメントを含む同じコード:

// Integers...
x,y,A,C,B,D,a,c,b,d,w,s,t;

// Is true if i is in range (of something)
T(i){return abs(i)<2*w-1;}

// Tests if lasers (horizontal, vertical, diagonal, etc) can/must exist at this point
// T(j-k) == 0 iff the laser of this direction can exist
// s += 1 iff this laser direction can pass through this point
// t *= 1 iff this laser direction must pass through this point
U(j,k){
    s+=T(j-k)*T(j)*T(k);
    t*=T(j-k)*j*k<1;
}

main(){ 
    // Read input; p0=(a,b), p1=(c,d)
    for(scanf("%i%i%i%i%i",&a,&b,&c,&d,&w); y<20; y+=!x)

        // A, B, C and D represent delta-x and delta-y for each points
        // e.g.: if we're processing (2,3), and p0=(4,5), A=4-2, B=5-3
        // s != 0 iff (x,y) can have some laser through it
        // t == 1 iff all lasers pass through (x,y)
        // (!A*!B+!C*!D) == 1 iff (x,y) is either p0 or p1  
        s=0,t=1,U(A=a-x,C=c-x),U(B=b-y,D=d-y),U(A-B,C-D),U(A+B,C+D),
        putchar((x=++x%21)?".?#x"[!!s+t+(!A*!B+!C*!D)]:10);
}

1
U(int j,int k)-> U(j,k); '\n'-> 10
user12205

1
k<=0->k<1
user12205

良い点。できれば賛成です!
アンドレハーダー

4

C、302バイト

b[400],x,y,s,t,w,d,e,g,k;f(u,v){d=u*x+v*y;e=u*s+v*t;if(e<d)k=e,e=d,d=k;for(k=0;k<400&d+w>e;++k)g=k%20*u+k/20*v,b[k]|=g>e-w&g<d+w|(g<d|g>e)*2;}main(){scanf("%d%d%d%d%d",&x,&y,&s,&t,&w);w=2*w-1;f(1,0);f(0,1);f(1,1);f(1,-1);b[y*20+x]=4;b[t*20+s]=4;for(k=0;k<400;)putchar(".#.?X"[b[k]]),++k%20?0:puts("");}

入力はstdinから取得され、定義された順序で5つの数字を読み取ります。

最終的なサイズ縮小ステップの前:

#include <stdio.h>
#include <stdlib.h>

int b[400], x, y, s, t, w, d, e, g, k;

void f(int u, int v) {
  d = u * x + v * y;
  e = u * s + v * t;
  if (e < d) k = e, e = d, d = k;
  if (d + w > e) {
    for (k = 0; k < 400; ++k) {
      g = u * (k % 20) + v * (k / 20);
      if (g > e - w && g < d + w) b[k] |= 1;
      if (g < d || g > e) b[k] |= 2;
    }
  }
}

int main() {
  scanf("%d%d%d%d%d", &x, &y, &s, &t, &w);
  w = 2 * w - 1;
  f(1, 0); f(0, 1); f(1, 1); f(1, -1);
  b[y * 20 + x] = 4;
  b[t * 20 + s] = 4;
  for (k = 0; k < 400; ) {
     putchar(".#.?X"[b[k]]);
     ++k % 20 ? 0 : puts("");
  }
}

主な手順の説明:

  • 配列bは状態/結果を保持します。ビット0は、ビームが到達できるすべてのピクセルに設定されます。ビット1は、すべてのピクセルに設定されます、すべてのビームでカバーされいない
  • 関数 fは、4つの方向すべて(垂直、水平、両方の対角線)に対して呼び出されます。その引数は、方向の法線ベクトルを指定します。
  • 機能中 f
    • 方向に対する両方の入力ポイントの距離が計算されます(de渡された法線ベクトルとポイントのドット積としておよび)。
    • 必要に応じて距離が交換されるため、 d常に以下になりeます。
    • の違い dとは、eビームの幅よりも大きい、何ビームがこの方向に可能ではありません。
    • それ以外の場合は、すべてのピクセルをループします。ピクセルが任意のビームで到達可能な場合はビット0を設定し、すべてのビームでカバーされていない場合はビット1を設定します。
  • 2つの入力ポイントを値4でマークします。ビット0と1を使用して状態を追跡しているため、値0〜3になり、これは未使用の最小値です。
  • のピクセルをループ処理し、b0から4の範囲の値を対応する文字に変換して印刷します。

あなたはおそらくその中にインクリメンタへのコードの最後の行を置くことによって少しを保存することができますforループ
ないようにチャールズ・
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.