Viết hàm trả về một đối tượng có thể lặp lại của tất cả các điểm hợp lệ 4 liền kề với (x, y)


17

Một nhu cầu rất phổ biến trong các lớp thuật toán và khoa học máy tính nói chung là lặp 4 hướng trên một lưới hoặc ma trận (chẳng hạn như trong BFS hoặc DFS). Điều này dường như thường dẫn đến rất nhiều mã lộn xộn và dài dòng với rất nhiều số học và so sánh trong các vòng lặp. Tôi đã thấy nhiều cách tiếp cận khác nhau về vấn đề này, nhưng tôi không thể lay chuyển được cảm giác rằng có một cách ngắn gọn hơn để làm điều này.

Thách thức là viết một hàm thuần túy, với chiều rộng và chiều cao của mặt phẳng hữu hạn n, mcó nguồn gốc tại điểm (0,0)và tọa độ (x,y)có thể biểu thị bất kỳ điểm hợp lệ nào trong mặt phẳng đó, trả về một đối tượng có thể lặp lại của tất cả các điểm trong mặt phẳng 4 hướng Liền kề (x,y).

Mục tiêu là xác định hàm đó theo càng ít byte càng tốt.

Một số ví dụ để giúp minh họa đầu vào / đầu ra hợp lệ:

n = 5 (y-axis), m = 3 (x-axis) (zero-based)

matrix = [
    [A, B, C],
    [D, E, F],
    [G, H, I],
    [J, K, L],
    [M, N, O],
]

(x, y) => [valid iterable points]

E: (1, 1) => [(1, 0), (2, 1), (1, 2), (0, 1)]
A: (0, 0) => [(1, 0), (0, 1)]
L: (2, 3) => [(2, 2), (2, 4), (1, 3)]
N: (1, 4) => [(1, 3), (2, 4), (0, 4)]
n = 1 (y-axis), m = 1 (x-axis) (zero-based)

matrix = [
    [A],
]

(x, y) => [valid iterable points]

A: (0, 0) => []
n = 2 (y-axis), m = 1 (x-axis) (zero-based)

matrix = [
    [A],
    [B],
]

(x, y) => [valid iterable points]

A: (0, 0) => [(0, 1)]
B: (0, 1) => [(0, 0)]

Và đây là một ví dụ (ví dụ này trong Python) của một hàm thỏa mãn các điều kiện:

def four_directions(x, y, n, m):
    valid_coordinates = []
    for xd, yd in [(1, 0), (0, 1), (-1, 0), (0, -1)]:
        nx, ny = x + xd, y + yd
        if 0 <= nx < m and 0 <= ny < n:
            valid_coordinates.append((nx, ny))
    return valid_coordinates

Ví dụ trên đã định nghĩa một hàm được đặt tên, nhưng các hàm ẩn danh cũng được chấp nhận.

Các đầu vào n, m, x, ylà tất cả các số nguyên 32 bit không dấu trong các phạm vi sau:

n > 0
m > 0
0 <= x < m
0 <= y < n

Đầu ra phải có dạng lặp (tuy nhiên ngôn ngữ bạn chọn xác định) của các cặp (x, y).

Làm rõ thêm:

Các số phức (và các biểu diễn / tuần tự hóa khác) đều được miễn là người tiêu dùng của iterable có thể truy cập xynhư các số nguyên chỉ biết vị trí của chúng.

Các chỉ mục dựa trên không có thể được chấp nhận, nhưng chỉ khi ngôn ngữ được lựa chọn là ngôn ngữ có chỉ số khác không. Nếu ngôn ngữ sử dụng kết hợp các hệ thống đánh số, mặc định là hệ thống đánh số của cấu trúc dữ liệu được sử dụng phổ biến nhất để biểu diễn một ma trận. Nếu đây vẫn là tất cả các khái niệm nước ngoài trong ngôn ngữ nhất định, bất kỳ chỉ số bắt đầu nào cũng được chấp nhận.


6
Chào mừng đến với trang web! Thử thách này khá tốt theo tiêu chuẩn của chúng tôi, nhưng có một vài điều ở đây đi ngược lại phong cách của chúng tôi. Đối với một người, chúng tôi rất thích những thách thức không giới hạn trong một ngôn ngữ nếu có thể. Nó vui hơn nhiều khi mọi người đều có thể thi đấu. Chúng tôi cũng thường chấm điểm golf-code theo byte trái ngược với các ký tự, chúng giống nhau cho hầu hết các mục đích nhưng có một số điều gian lận bạn có thể làm nếu câu trả lời được ghi bằng ký tự. Hy vọng bạn có niềm vui ở đây!
Thuật sĩ lúa mì

Chúng tôi đảm bảo rằng (x,y)nó nằm trong hình chữ nhật, phải không?
xnor

4
Theo mặc định, CGCC cho phép các chương trình đầy đủ cũng như các chức năng như đệ trình. Điều này giúp cho phép các ngôn ngữ không nhất thiết phải có khái niệm về chức năng để cạnh tranh
Jo King

3
Một đầu ra sẽ là STDOUT, chứ không phải là một đối tượng mã. Đây thường có thể là bất kỳ đầu ra nào có các dấu phân cách rõ ràng để không rõ ràng và tuân theo các định dạng đầu ra Tiêu chuẩn
Jo King

2
Được phép biểu diễn tọa độ dưới dạng số phức chứ không phải số nguyên?
Joel

Câu trả lời:


12

Python 2 , 66 byte

lambda m,n,x,y:[(x-1,y),(x+1,y)][~x:m-x]+[(x,y-1),(x,y+1)][~y:n-y]

Hãy thử trực tuyến!

Liệt kê bốn hàng xóm, sau đó sử dụng danh sách cắt để loại bỏ những thứ nằm ngoài giới hạn.


Python 2 , 71 byte

lambda m,n,x,y:[(k/n,k%n)for k in range(m*n)if(k/n-x)**2+(k%n-y)**2==1]

Hãy thử trực tuyến!

Thay vì kiểm tra xem ai trong số bốn lân cận nằm trong giới hạn, chúng tôi thực hiện theo cách chậm hơn để kiểm tra tất cả các điểm trong giới hạn đối với những người lân cận, đó là khoảng cách Euclidian chính xác từ 1 (x,y). Chúng tôi cũng sử dụng thủ thuật div-mod cổ điển để lặp qua lưới , tiết kiệm nhu cầu viết hai vòng như thế nào for i in range(m)for j in range(n).

Tôi đã thử sử dụng số học phức tạp để viết điều kiện khoảng cách, nhưng hóa ra nó dài hơn để viết abs((k/n-x)*1j+k%n-y)==1.


Python 2 , 70 byte

lambda m,n,x,y:[(x+t/3,y+t%3-1)for t in-2,0,2,4if m>x+t/3>=0<y+t%3<=n]

Hãy thử trực tuyến!


11
Chúc mừng 100k!
Arnauld

4

Octave , 90 byte

Điều này sử dụng một cách tiếp cận hình học: Đầu tiên chúng ta tạo một ma trận các số không có kích thước mong muốn và đặt một 1vị trí mong muốn. Sau đó, chúng tôi kết hợp với kernel

[0, 1, 0]
[1, 0, 1]
[0, 1, 0]

tạo ra một ma trận mới có cùng kích thước với các ma trận tại 4 lân cận của điểm ban đầu. Sau đó, chúng tôi find()các chỉ số của các mục khác không của ma trận mới này.

function [i,j]=f(s,a,b);z=zeros(s);z(a,b)=1;[i,j]=find(conv2(z,(v=[1;-1;1])*v'<0,'same'));

Hãy thử trực tuyến!

tích chập là chìa khóa để thành công.


4
Thật vậy, cho dù phông chữ nhỏ đến mức nào
Luis Mendo


3

JavaScript (ES6), 74 byte

Cách tiếp cận nhàm chán.

(h,w,x,y)=>[x&&[x-1,y],~x+w&&[x+1,y],y&&[x,y-1],++y-h&&[x,y]].filter(_=>_)

Hãy thử trực tuyến!


JavaScript (Node.js) , 74 byte

Ít nhàm chán nhưng chỉ là dài. Đưa đầu vào là ([h,w,x,y]).

a=>a.flatMap((_,d,[h,w,x,y])=>~(x+=--d%2)*~(y+=--d%2)&&x<w&y<h?[[x,y]]:[])

Hãy thử trực tuyến!


JavaScript (V8) , 67 byte

Nếu tất cả các phương thức đầu ra tiêu chuẩn được cho phép, chúng ta có thể in tọa độ hợp lệ bằng:

(h,w,x,y)=>{for(;h--;)for(X=w;X--;)(x-X)**2+(y-h)**2^1||print(X,h)}

Hãy thử trực tuyến!


2

Thạch ,  13  12 byte

2ḶṚƬNƬẎ+⁸%ƑƇ

Liên kết dyadic chấp nhận danh sách hai số nguyên (0 chỉ mục) ở bên trái [row, column]và hai số nguyên ở bên phải [height, width], đưa ra danh sách danh sách các số nguyên , [[adjacent_row_1, adjacent_column_1], ...].

Hãy thử trực tuyến!

Làm sao?

2ḶṚƬNƬẎ+⁸%ƑƇ - Link: [row, column]; [height, width]   e.g. [3,2]; [5,3] (the "L" example)
2            - literal 2                                   2
 Ḷ           - lowered range                               [0,1]
   Ƭ         - collect up while distinct, applying:
  Ṛ          -   reverse                                   [[0,1],[1,0]]
     Ƭ       - collect up while distinct, applying:
    N        -   negate                                    [[[0,1],[1,0]],[[0,-1],[-1,0]]]
      Ẏ      - tighten                                     [[0,1],[1,0],[0,-1],[-1,0]]
        ⁸    - chain's left argument ([row, column])       [3,2]
       +     - add (vectorises)                            [[3,3],[4,2],[3,1],[2,2]]
           Ƈ - filter keep if:
          Ƒ  -   is invariant under:
         %   -     modulo ([height, width]) (vectorises)    [3,0] [4,2] [3,1] [2,2]
             - (...and [3,0] is not equal to [3,3] so ->)  [[4,2],[3,1],[2,2]]

Bạn có thể thay thế ḶṚƬbằng Ṭ€. 2ḶṚƬNƬẎtrả về [[0, 1], [1, 0], [0, -1], [-1, 0]], trong khi 2Ṭ€NƬẎtrả về [[1], [0, 1], [-1], [0, -1]]và, vì các singletons được gói, +chỉ vector hóa với phần tử đầu tiên của các phần tử đó, vì vậy chúng hoạt động như thể phần tử thứ hai của chúng là 0(danh tính phụ gia). Kết quả là, chỉ có thứ tự của đầu ra có thể thay đổi.
Erik the Outgolfer

2

Perl 6 , 56 49 byte

-7 byte nhờ nwellnhof!

{grep 1>(*.reals Z/@^b).all>=0,($^a X+1,-1,i,-i)}

Hãy thử trực tuyến!

Loại bỏ các phần tử giới hạn bằng cách kiểm tra xem khi chia cho giới hạn mảng có nằm trong khoảng từ 0 đến 1. Đưa đầu vào và đầu ra qua các số phức trong đó phần thực là xtọa độ và phần ảo là phần y. Bạn có thể trích xuất chúng thông qua .imvà các .rechức năng.



@nwellnhof Rất đẹp! Tôi đã xây dựng nó để làm một cái gì đó như thế này , nhưng divdường như không hoạt động cho Nums
Jo King

(*.reals>>.Int Zdiv@^b).nonehoặc (*.reals Z/@^b)>>.Int.nonesẽ làm việc nhưng các diễn viên Int-dường như quá tốn kém.
nwellnhof

1

J , 30 29 28 byte

(([+.@#~&,1=|@-)j./)~j./&i./

Hãy thử trực tuyến!

Làm sao:

  • Biến bàn tay phải mx narg thành một lưới các số phứcj./&i./
  • Tương tự cho trái arg (quan điểm của chúng tôi) j./
  • Tạo mặt nạ hiển thị khoảng cách giữa điểm của chúng tôi và lưới chính xác là 1 1=|@-
  • Sử dụng để lọc lưới, sau khi làm phẳng cả hai #~&,
  • Biến kết quả trở lại thành điểm thực +.@


0

Than , 29 byte

Jθη#FIζFIε«Jικ¿№KV#⊞υ⟦ικ⟧»⎚Iυ

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Lấy đầu vào theo thứ tự x, y, chiều rộng, chiều cao. Giải trình:

Jθη#

In một #tại vị trí được cung cấp.

FIζFIε«

Vòng qua hình chữ nhật đã cho.

Jικ

Nhảy đến vị trí hiện tại.

¿№KV#⊞υ⟦ικ⟧

Nếu có một liền kề #thì lưu vị trí.

»⎚Iυ

Xuất các vị trí được phát hiện ở cuối vòng lặp.

Nhàm chán trả lời:

FIζFIε¿⁼¹⁺↔⁻ιIθ↔⁻κIηI⟦ικ

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Hoạt động bằng cách tìm các vị trí liền kề về mặt toán học.


0

Haskell, 62 byte

Sử dụng phương trình vòng tròn

f m n a b = [(x,y)|x<-[0..m-1],y<-[0..n-1],(x-a)^2+(y-b)^2==1]

Hãy thử trực tuyến!

Cách tiếp cận nhàm chán: 81 byte

f m n x y=filter (\(x,y)->x>=0&&y>=0&&x<m&&y<n) [(x-1,y),(x+1,y),(x,y-1),(x,y+1)]
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.