Laser của Schrödinger


24

Chán nản với việc thử nghiệm trên những con vật nhỏ bé trong nhà , Erwin Schrödinger đã giành giải thưởng Nobel đã quyết định tìm ra tia laser gần nhất và bắn nó vào mọi thứ thay vào đó. Vì ... khoa học!

Sự miêu tả

Bạn sẽ được cung cấp hai điểm mà tia laser đi qua và kích thước của chùm tia laser, và bạn phải xác định nơi mà tia laser phải đi, có thể đã đi và không thể đi.

Các tia laser có thể là ngang, dọc hoặc chéo. Đối với chùm tia laser kích thước 1, chúng trông giống như thế này:

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

Các tia laser chéo cũng có thể được lật. Kích thước 2 chùm tia laser trông như thế này:

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

Nói chung, để có được chùm tia laser có kích thước (n), chỉ cần lấy chùm tia laser có kích thước (n-1) và thêm chùm tia laser có kích thước (1) ở cả hai bên. Như một ví dụ cuối cùng, đây là tất cả các chùm laser có thể có kích thước 3, được hiển thị trên cùng một "bảng":

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

"Bảng" này sẽ luôn có kích thước 20x20 (tính theo ký tự).

Đầu vào

Chương trình của bạn sẽ được cung cấp năm số nguyên làm đầu vào. Chúng, theo thứ tự, x 1 , y 1 , x 2 , y 2 và kích thước của chùm tia laser. Chúng phải được thực hiện chính xác theo thứ tự đó. Nếu bạn muốn, bạn có thể lấy các cặp (x, y) theo thứ tự làm một mảng, bộ dữ liệu, danh sách hoặc loại dữ liệu tích hợp khác lưu trữ hai giá trị.

Cả hai điểm được đưa ra làm đầu vào sẽ nằm trong bảng và chúng được đảm bảo là khác biệt (tức là hai điểm sẽ không bao giờ giống nhau). Kích thước của chùm tia laser được liên kết với 1 ≤ size < 20. Sẽ luôn có ít nhất một chùm tia laser có thể đi qua cả hai điểm.

Đầu ra

Chương trình của bạn phải xuất ra lưới 20x20 gồm các ký tự sau:

  • # nếu mọi chùm tia laser có thể đi qua hai điểm cũng đi qua điểm này.
  • . nếu không có chùm tia laser đi qua hai điểm và điểm này.
  • ? nếu một số, nhưng không phải tất cả, các chùm tia laser có thể đi qua điểm này.
  • Xnếu đây là một trong hai điểm đầu vào ban đầu (điều này sẽ ghi đè lên #).

Các trường hợp thử nghiệm

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??????.....
..??????????????....
..???????????????...
..????????????????..
..?????????????????.
..??????????????????
..??????????????????
..????????.?????????
..????????..????????
..????????...???????

Các trường hợp thử nghiệm được tạo bằng tập lệnh Ruby sau, nằm trong Stack Snippet để bảo tồn không gian dọc.

Quy tắc

  • Chương trình của bạn phải có khả năng giải quyết từng trường hợp thử nghiệm trong vòng dưới 30 giây (trên một máy hợp lý). Đây là một kiểm tra về sự tỉnh táo, vì chương trình Ruby thử nghiệm của tôi đã giải quyết tất cả các trường hợp kiểm tra gần như ngay lập tức.

  • Đây là , vì vậy giải pháp ngắn nhất sẽ thắng.


2
Thuật ngữ được sử dụng ở đây làm tôi vấp ngã ban đầu. Tôi tin rằng laser thường đề cập đến một thiết bị tạo ra chùm tia laser . Những gì bạn đại diện ở đây thực sự là chùm, phải không? Đây không phải là một đại diện của laser thực tế, mà sẽ là thiết bị tạo ra chùm tia?
Reto Koradi

2
Trường hợp thử nghiệm cuối cùng có vẻ sai. Một laser kích thước 4 nên rộng 9 pixel. Đường dọc nên ít nhất là rộng, nhưng thực tế là hẹp hơn.
Cấp sông St

1
@steveverrill Kích thước 4 rộng 7 pixel. Chiều rộng tính bằng pixel là 2 * size - 1. Kích thước 1 là 1 pixel, kích thước 2 là 3 pixel, kích thước 3 là 5 pixel (xem ví dụ ở trên), kích thước 4 là 7 pixel.
Reto Koradi

2
Tôi không thấy Schrodinger liên quan đến thử thách này như thế nào.
dùng12205

1
@JonasDralle Một lần nữa, giới hạn thời gian chủ yếu chỉ là kiểm tra độ tỉnh táo và hầu như mọi bài nộp dự kiến ​​sẽ hoàn thành trong thời gian ít hơn nhiều so với thời gian đó.
Doorknob

Câu trả lời:


5

C, 291 280 277 265 byte

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

Có thể được biên dịch / chạy bằng cách sử dụng:

gcc laser.c -o laser && echo "10 10 11 10 3" | ./laser

Dưới đây, cùng một mã với khoảng trắng và ý kiến ​​giải thích:

// 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.
dùng12205

1
k<=0->k<1
dùng12205

Điểm tốt. Tôi sẽ nâng cấp nếu tôi có thể!
André Harder

4

C, 302 byte

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

Đầu vào được lấy từ stdin, đọc 5 số theo thứ tự xác định.

Trước bước giảm kích thước cuối cùng:

#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("");
  }
}

Một số giải thích về các bước chính:

  • Mảng bgiữ trạng thái / kết quả. Bit 0 sẽ được đặt cho tất cả các pixel có thể đạt được bằng một chùm tia. Bit 1 sẽ được đặt cho tất cả các pixel không được bao phủ bởi tất cả các chùm.
  • Hàm fđược gọi cho cả 4 hướng (dọc, ngang, cả hai đường chéo). Đối số của nó chỉ định các vectơ bình thường của hướng.
  • Trong chức năng f:
    • Khoảng cách của cả hai điểm đầu vào so với hướng được tính ( de) là sản phẩm chấm của điểm có vectơ bình thường được truyền vào.
    • Khoảng cách được hoán đổi nếu cần thiết để dluôn luôn nhỏ hơn hoặc bằng e.
    • Nếu sự khác biệt giữa delớn hơn chiều rộng của chùm tia, không có chùm tia nào có thể theo hướng này.
    • Nếu không, lặp trên tất cả các pixel. Đặt bit 0 nếu pixel có thể tiếp cận được bởi bất kỳ chùm tia nào và bit 1 nếu nó không được bao phủ bởi tất cả các chùm.
  • Đánh dấu hai điểm đầu vào bằng giá trị 4. Vì chúng tôi đã sử dụng các bit 0 và 1 để theo dõi trạng thái, dẫn đến các giá trị 0 đến 3, đây là giá trị không sử dụng nhỏ nhất.
  • Lặp lại các pixel trong bvà chuyển đổi các giá trị trong phạm vi 0 thành 4 thành ký tự tương ứng của chúng trong khi in chúng ra.

bạn có thể có thể tiết kiệm một chút bằng cách đặt dòng mã cuối cùng vào bộ tăng trong forvòng lặp đó
Không phải là Charles
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.