Tiêu diệt chúng bằng Lazers


21

Giới thiệu

Đấu trường là một vùng đất bằng phẳng với những tòa nhà chọc trời, mà kẻ thù của bạn sử dụng để che chắn. Bạn và kẻ thù của bạn bắn nhau bằng tia laser. Tất cả các bạn mang theo máy bay phản lực, cho phép bay.

Kẻ thù nào bạn có thể đánh bằng tia laser của mình và chúng đang ẩn nấp?

Vấn đề

Đầu tiên, kích thước của một đấu trường được cho bởi một số nguyên ntrên một dòng. Các ndòng sau chứa nsố nguyên trên mỗi dòng cách nhau bởi một khoảng trắng. Mỗi số nguyên biểu thị chiều cao của tòa nhà tại vị trí đó. Mỗi tòa nhà là một khối hình chữ nhật, 1 đơn vị 1 đơn vị tính theo đơn vị chiều cao.

Tiếp theo, vị trí của bạn được đưa ra trên một dòng duy nhất là ba số dấu chấm động x, y, z.

Cuối cùng, số lượng kẻ thù được cho bởi một số nguyên mtrên một dòng. Các mdòng sau chứa ba số dấu phẩy động trên mỗi dòng cách nhau bởi một khoảng trắng. Những đại diện x, yztọa độ của một kẻ thù. Hệ tọa độ được xác định như sau:

  • x được đo từ trái sang phải trong đầu vào thành phố
  • y được đo từ trên xuống dưới
  • z được đo từ mặt đất lên

Đối với mỗi kẻ thù, nếu một đường không bị cản trở có thể được rút ra từ bạn để kẻ thù đó, sản lượng một dương tính số nguyên. Mặt khác, xuất ra một số nguyên âm . Đầu ra riêng biệt với một dòng mới.

Đầu vào mẫu

Nhận xét, ký hiệu là '#', có mặt để giúp bạn nhanh chóng xem mỗi dòng làm gì. Họ sẽ không có mặt trong đầu vào thực tế.

5              # Size of the map
0 0 0 0 0      # Buildings
0 0 0 0 0      # Buildings
4 4 4 4 4      # Buildings
0 0 0 0 0      # Buildings
0 0 0 0 0      # Buildings
2.5 0.0 4.0    # Your location
3              # Number of enemies
2.5 5.0 0.1    # Enemy location
2.5 5.0 5.0    # Enemy location
0.0 2.7 4.5    # Enemy location

Sản lượng mẫu

Đối với đầu vào mẫu ở trên, chúng tôi xuất ra như sau:

-1
1
1

Giả định

  • 0 n<< 100
  • 0 m<< 100
  • 0 <= x<=n
  • 0 <= y<=n
  • 0 <= z<n
  • Người chơi sẽ không được đặt ở hoặc bên trong một góc, cạnh hoặc cạnh của tòa nhà
  • Tầm nhìn của bạn đến kẻ thù sẽ không bao giờ tiếp xúc với góc, cạnh hoặc cạnh của tòa nhà
  • Một người chơi không phải là một vật cản

Vui mừng khi thấy nó ra khỏi hộp cát :)
Timtech

7
Nếu tôi không thể tiêu diệt kẻ thù, tôi có thể tham gia cùng họ không?
John Dvorak

@ user80551 Xin lỗi, tôi phải quay lại chỉnh sửa của bạn để tiêu đề vì việc viết sai là cố ý. Google nó.
Rainbolt

@Rizer Ồ, xin lỗi, IDK đó
user80551

Câu trả lời:


5

Perl, 301 296 282

Chỉnh sửa 2: Trên thực tế, cạnh tranh hay không, không có lý do gì để không chơi golf thêm một chút. Kiểm tra nó trực tuyến .

Chỉnh sửa: Vài dấu ngoặc đơn biến mất, regex đơn giản hơn để kiểm tra số nguyên khác không.

Với dòng mới và thụt lề cho dễ đọc:

sub i{<>=~/\S+/g}
@b=map[i],@r=0..<>-1;
print.1<=>(map{
    @a[1,0,2,4,3]=@a;
    @b=map{$i=$_;[map$b[$_][$i],@r]}@r;
    grep$a[3]
        &&($k=(($x=$_)-$a[0])/$a[3])**2<=$k
        &&pop[sort map@{$b[$_]}[$x-!!$x,$x],
                   ($_=$a[1]+$k*$a[4]),$_-/^\d+$/]
           >=$a[2]+$k*$a[5]
    ,@R=@r
}@a=map$_-shift@v,i,@u=@v=@$_),$/for([i])x<>

Nó đòi hỏi 5.14vì đối số vô hướng (tham chiếu mảng) đến pop.


Bạn có thể giải thích giải pháp của bạn một chút? Tôi đã không kiểm tra nó và tôi vẫn chưa hiểu Perl, vì vậy một số ý kiến ​​sẽ rất hay.
WorldSEnder

@WorldSEnder, phác thảo của thuật toán như sau. Đường thẳng PEkết nối hai điểm trong không gian 3 chiều, "Người chơi" (X1Y1Z1) và "Kẻ thù" (X2Y2Z2). Chiếu của nó trên (XY)mặt phẳng cắt một số các lưới đường tức là số nguyên x = consthoặc y = constnhư X1 < x < X2hay Y1 < y < Y2(giả sử ở đây là ví dụ X1 < X2, nhưng nó không quan trọng). Tọa độ x ycủa các giao điểm này có thể dễ dàng được tìm thấy, và do đó ztọa độ của một điểm trên PEđường cũng vậy.
dùng2846289

(tiếp theo) Mặt khác, đối với bất kỳ x ytọa độ nào , chúng tôi đều biết chiều cao hcủa tòa nhà (thay vào đó, chiều cao tối đa lên tới 4 tòa nhà có chung x yđiểm). Kẻ thù có thể bị bắn nếu (và chỉ khi) h < zcho tất cả các "điểm giao nhau" được đề cập ở trên. Triển khai là một số môn học cơ bản, cũng như một số thủ thuật với Perl cho mục đích chơi gôn. Việc giải mã các chi tiết về cách tôi đã làm nó một tháng trước sẽ mất một thời gian ngay bây giờ :-).
dùng2846289

Argh, như tôi thấy có một lỗi trong lần sửa đổi (5) cuối cùng: các chỉ số cho các thành phần của @amảng trong grepbiểu thức sẽ xuất hiện theo thứ tự 0,3,0,4,1,5,2thay vì 3,0,3,1,4,2,5- xin lỗi.
dùng2846289

OK, muộn còn hơn không, và để kết thúc với tất cả, đây là phiên bản nhận xét.
dùng2846289

3

Python 2.7 - 429 420 308 308 ký tự

Tôi nghĩ rằng thách thức này giống như một vấn đề toán học hơn là một vấn đề về golf mã, vì vậy đừng quá khắc nghiệt với tôi nếu tôi bỏ lỡ một số tối ưu hóa rõ ràng. Dù sao, đây là mã:

b=lambda:raw_input().split()
m=map
d=range(input())
h=[m(int,b())for _ in d]
x,y,z=m(float,b())
for e,f,g in[m(float,b())for _ in[1]*input()]:o=lambda x,y,u,v,i,j:i<=x+u/v*(j+1-y)<=i+1<[]>z+(g-z)/v*(j+1-y)<=max(h[i][j:j+2])if v else 0;print 1-2*any(o(x,y,e-x,f-y,j,i)+o(y,x,f-y,e-x,i,j)for j in d for i in d)

Điều này sẽ làm việc cho các trường hợp cạnh và góc (chơi chữ ngoài ý muốn) và khá vững chắc. Ouput cho ví dụ được cung cấp:

-1
1
1

Và đây là một lời giải thích "ngắn":

fast_read = lambda : raw_input().split() # define a helper
# m = map another helper
grid_range = range(input())
houses = [map(int, fast_read()) for _ in grid_range]
# 'map(int,...)' is a shorter version of '[int(a) for a in ...]'
pos_x,pos_y,pos_z = map(float, fast_read()) # read the player position
# the following loops through all enemy coordinates
for ene_x, ene_y, ene_z in [map(float,fast_read()) for _ in[1]*input()]:
    vec_z = ene_z - pos_z
    # is_hit macro uses vector math to detemine whether we hit a specific wall
    # wallhit -> 1
    # no wallhit -> 0
    is_hit = lambda pos_x, pos_y, vec_x, vec_y, co_x, co_y:\
        (co_x <= pos_x + vec_x/vec_y * (co_y + 1 - pos_y) <= co_x + 1 # check if hit_x is good
        < [] > # an effective and
        pos_z + (ene_z - pos_z)/vec_y * (co_y + 1 - pos_y) <= max(houses[co_x][co_y:co_y + 2]) # check if hit_z is good
        if vec_y else 0) # if vec_y is 0 we can't hit the wall parallel to y
    print (.5 - # can hit -> 0.5 - 0 = 0.5, hit -> 0.5 - 1 = -0.5
            any( # if we hit any wall
                # we swap x and y-coordinate because we read them "incorrect"
                is_hit(pos_x, pos_y, ene_x-pos_x, ene_y-pos_y, cur_y, cur_x) # check for hit in x-direction
                + # effective 'or'
                is_hit(pos_y, pos_x, ene_y-pos_y, ene_x-pos_x, cur_x, cur_y) # check for hit in y-direction
                    for cur_y in grid_range # loop y
                for cur_x in grid_range)) # loop x

Tôi đoán đây là đầy sai sót. Btw Tôi đã lưu ký tự khi lồng nhau (cấp đầu tiên là một khoảng trắng, tab thứ hai, sau đó là một tab và khoảng trắng ...). Tôi hy vọng sau tất cả câu trả lời này có thể chỉ ra cách để làm điều đó.


Tôi mới nhận ra rằng đầu vào mẫu không hợp lệ vì một trong những kẻ thù nằm trực tiếp trên mặt đất, về mặt kỹ thuật là đỉnh của tòa nhà có chiều cao bằng không, điều mà tôi đã hứa sẽ không xảy ra. Nội dung gửi của bạn vượt qua trường hợp kiểm tra đã sửa, nhưng không thành công trong trường hợp này - ideone.com/8qn3sv . Bạn có thể kiểm tra trường hợp thử nghiệm của tôi? Tôi có thể thiếu một cái gì đó hoặc có thể hệ thống tọa độ của tôi không rõ ràng.
Rainbolt

Không, chỉ là vectơ đang đi qua các góc ... bây giờ tôi biết lý do tại sao bạn đã hứa Giả định 6 & 7 :)
WorldSEnder

btw, tôi tạo ra một số float âm nhưng có thể được sửa bằng 2 ký tự phụ ( print 1-2*...thay vì print.5-...) Vì vậy, đó không phải là sự khác biệt quá lớn tôi đoán
WorldSEnder

Bạn đã vượt qua một vài bài kiểm tra tôi nghĩ ra. Công việc tốt! Bạn vẫn nên tiếp tục và làm cho nó in các số nguyên để phù hợp với thông số kỹ thuật.
Rainbolt

1
Chấp nhận câu trả lời của bạn cho đến khi ai đó đưa ra một giải pháp tốt hơn. Tôi không nghĩ họ sẽ làm thế. Rất hiếm khi có ai xem lại những thách thức đã giải quyết cũ. Bạn nên chơi gôn nhiều hơn! Có vẻ như bạn biết công cụ của bạn. :)
Rainbolt

2

C - 2468

Không chơi gôn chút nào, nhưng hy vọng đó là điểm khởi đầu cho những triển khai thú vị hơn. Việc thực hiện intersectđược tài trợ rất nhiều từ Adrian Boeing . Mã giả của anh ta không đầy đủ, nhưng lời giải thích của anh ta về toán học là vô giá. Ý tưởng cơ bản là bạn lấy một đường từ người chơi đến mục tiêu và kẹp nó vào tất cả các bức tường của mỗi tòa nhà, cập nhật chiều dài cho mỗi bức tường. Chiều dài còn lại là phần bên trong tòa nhà, vì vậy nếu bằng không, không có giao lộ.

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

typedef struct
{
    float x;
    float y;
    float z;
} vec3;

float
dot(vec3 a, vec3 b)
{
    return a.x * b.x + a.y * b.y + a.z * b.z;
}

vec3
scale(float s, vec3 a)
{
    vec3 r;
    r.x = s * a.x;
    r.y = s * a.y;
    r.z = s * a.z;
    return r;
}

vec3
add(vec3 a, vec3 b)
{
    vec3 r;
    r.x = a.x + b.x;
    r.y = a.y + b.y;
    r.z = a.z + b.z;
    return r;
}

int
intersect(vec3 a, vec3 b, vec3 *normals, vec3 *points, int nnormals)
{
    vec3 ab = add(b, scale(-1, a));
    float tfirst = 0;
    float tlast = 1;
    int i;
    for(i = 0; i < nnormals; i++)
    {
        float d = dot(normals[i], points[i]);
        float denom = dot(normals[i], ab);
        float dist = d - dot(normals[i], a);
        float t = dist / denom;
        if(denom > 0 && t > tfirst)
        {
            tfirst = t;
        }
        else if(denom < 0 && t < tlast)
        {
            tlast = t;
        }
    }
    return tfirst < tlast ? 1 : 0;
}

const vec3 N = {0,-1,0};
const vec3 S = {0,1,0};
const vec3 W = {-1,0,0};
const vec3 E = {1,0,0};
const vec3 D = {0,0,-1};

int
main(void)
{
    vec3 normals[5];
    vec3 player;
    vec3 *targets;
    int i;
    int j;
    vec3 *buildings;
    vec3 *b;
    int nbuildings = 0;
    int n;
    int m;
    char line[300];
    normals[0] = N;
    normals[1] = S;
    normals[2] = W;
    normals[3] = E;
    normals[4] = D;
    fgets(line, 300, stdin);
    n = atoi(line);
    /*5 sides for each building*/
    buildings = calloc(n * n * 5, sizeof(*buildings));
    b = buildings;
    for(i = 0; i < n; i++)
    {
        char *z;
        fgets(line, 300, stdin);
        for(j = 0; j < n && (z = strtok(j ? NULL : line, " \n")) != NULL; j++)
        {
            vec3 bottom;
            vec3 top;
            if(z[0] == '0') continue;
            nbuildings++;
            bottom.x = j;
            bottom.y = i;
            bottom.z = 0;
            top.x = j + 1;
            top.y = i + 1;
            top.z = atoi(z);
            b[0] = top;
            b[1] = bottom;
            b[2] = top;
            b[3] = bottom;
            b[4] = top;
            b += 5;
        }
    }
    fgets(line, 300, stdin);
    player.x = atof(strtok(line, " "));
    player.y = atof(strtok(NULL, " "));
    player.z = atof(strtok(NULL, " \n"));
    fgets(line, 300, stdin);
    m = atoi(line);
    targets = calloc(m, sizeof(*targets));
    for(i = 0; i < m; i++)
    {
        int hit = 1;
        fgets(line, 300, stdin);
        targets[i].x = atof(strtok(line, " "));
        targets[i].y = atof(strtok(NULL, " "));
        targets[i].z = atof(strtok(NULL, " \n"));
        for(j = 0; j < nbuildings; j++)
        {
            b = &buildings[j * 5];
            if(intersect(player, targets[i], normals, b, 5) == 1)
            {
                hit = 0;
                break;
            }
        }
        printf("%d\n", hit ? 1 : -1);
    }
    free(buildings);
    free(targets);
    return 0;
}

Đã thử một vài trường hợp thử nghiệm và bạn đã vượt qua tất cả chúng. Đây là ideone mà bất kỳ ai khác có thể sử dụng để xác minh - ideone.com/MTXpzF
Rainbolt
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.