슈뢰딩거의 레이저


24

불만을 품고 작은 국내 동물 실험 , 노벨상을 수상한 에르빈 슈뢰딩거는 가장 가까운 레이저를 찾을 대신 사물을 촬영하기로 결정했다. 왜냐하면 ... 과학!

기술

당신은 두 개의 레이저가 통과한다는 점과 레이저 빔의 크기를 받게됩니다, 당신은 레이저 빔이 위치를 결정해야 한다 , 갈 갔다, 그리고 수 없었다 갔다.

레이저 빔은 수평, 수직 또는 대각선 일 수 있습니다. 크기 1 레이저 빔의 경우 각각 다음과 같습니다.

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

대각선 레이저 빔도 뒤집을 수 있습니다. 크기 2 레이저 빔은 다음과 같습니다.

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

일반적으로 크기 (n)의 레이저 빔을 얻으려면 크기 (n-1)의 레이저 빔을 가져 와서 양쪽에 크기 (1)의 레이저 빔을 추가하십시오. 마지막 예로 동일한 "보드"에 표시된 크기 3의 가능한 모든 레이저 빔이 있습니다.

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

이 "보드"의 크기는 항상 20x20 (문자)입니다.

입력

프로그램은 5 개의 정수를 입력으로받습니다. 이들은 순서대로 x 1 , y 1 , x 2 , y 2 및 레이저 빔의 크기입니다. 순서대로 정확하게 가져와야합니다. 원하는 경우 정렬 된 (x, y) 쌍을 배열, 튜플, 목록 또는 두 개의 값을 저장하는 기타 내장 데이터 형식으로 사용할 수 있습니다.

입력으로 주어진 두 지점은 모두 보드 내에 있으며, 서로 구별 될 수 있습니다 (즉, 두 지점은 동일하지 않음). 레이저 빔의 크기는에 구속됩니다 1 ≤ size < 20. 두 지점을 통과하는 레이저 빔은 항상 하나 이상 있어야합니다.

산출

프로그램은 다음 문자의 20x20 격자를 출력해야합니다.

  • # 두 지점을 통과하는 모든 가능한 레이저 빔도이 지점을 통과합니다.
  • . 두 점과이 점을 통과하는 레이저 빔이없는 경우
  • ? 가능한 레이저 빔 중 일부는이 지점을 통과합니다.
  • X이것이 두 개의 원래 입력 지점 중 하나 인 경우 (이를 재정의 함 #).

테스트 사례

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
여기서 사용 된 용어는 처음에 저를 트립했습니다. 나는 레이저가 일반적으로 레이저 빔 을 생산하는 장치를 의미 한다고 생각 합니다. 여기서 당신이 나타내는 것은 실제로 광선입니다. 이것은 빔을 생성하는 장치가 될 실제 레이저의 표현이 아닙니다.
Reto Koradi 2016 년

2
마지막 테스트 사례가 잘못 보입니다. 크기 4 레이저의 너비는 9 픽셀이어야합니다. 수직 트랙은 최소한 넓어야하지만 실제로는 더 좁습니다.
레벨 리버 St

1
@steveverrill 크기 4의 너비는 7 픽셀입니다. 픽셀 단위의 너비는 2 * size - 1입니다. 크기 1은 1 픽셀, 크기 2는 3 픽셀, 크기 3은 5 픽셀 (위 예 참조), 크기 4는 7 픽셀입니다.
Reto Koradi

2
나는 슈뢰딩거가이 도전과 어떤 관련이 있는지 모르겠다.
user12205

1
@JonasDralle 다시 말하지만, 시간 제한은 대부분 건전성 검사이며 거의 모든 제출이 그보다 훨씬 적은 시간 내에 완료 될 것으로 예상됩니다.
Doorknob

답변:


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

좋은 지적입니다. 내가 할 수 있다면 난 공짜 야!
André Harder

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

주요 단계에 대한 설명 :

  • Array b는 상태 / 결과를 유지합니다. 비트 0은 빔으로 도달 할 수있는 모든 픽셀에 대해 설정됩니다. 비트 1은 모든 빔으로 덮여 있지 않은 모든 픽셀에 대해 설정됩니다 .
  • f4 방향 (세로, 가로, 두 대각선) 모두에 대해 기능 이 호출됩니다. 인수는 방향의 법선 벡터를 지정합니다.
  • 기능에서 f:
    • 방향에 대한 두 입력 점의 거리는 법선 벡터가 전달 된 점의 내적으로 계산됩니다 ( de).
    • 필요한 경우 거리가 교환되어 d항상보다 작거나 같습니다 e.
    • 차이 경우 de상기 빔의 폭보다 큰 경우에는 빔이 방향 수 없다.
    • 그렇지 않으면 모든 픽셀을 반복합니다. 빔이 픽셀에 도달 할 수 있으면 비트 0을 설정하고 모든 빔에 의해 커버되지 않으면 비트 1을 설정하십시오.
  • 두 개의 입력 포인트를 값 4로 표시합니다. 비트 0과 1을 사용하여 상태를 추적하므로 값 0 ~ 3이 발생하므로 사용되지 않은 가장 작은 값입니다.
  • 의 픽셀을 반복하고 b0 ~ 4 범위의 값을 인쇄하는 동안 해당 문자로 변환합니다.

for루프 의 증 분기에 마지막 코드 줄을 넣어서 약간의 비용을 절약 할 수 있습니다
Charles
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.