Tulis fungsi yang mengembalikan objek yang dapat diulang dari semua titik yang valid berbatasan 4 arah (x, y)

17

Kebutuhan yang sangat umum dalam kelas algoritme dan ilmu komputer secara umum adalah untuk mengulangi 4 arah secara grid atau matriks (seperti dalam BFS atau DFS). Ini tampaknya sering menghasilkan banyak kode kikuk dan verbose dengan banyak aritmatika dan perbandingan dalam loop. Saya telah melihat banyak pendekatan berbeda dalam hal ini, tetapi saya tidak dapat menghilangkan perasaan bahwa ada cara yang lebih ringkas untuk melakukan ini.

Tantangannya adalah untuk menulis fungsi murni yang, mengingat lebar dan tinggi bidang hingga yang n, mberasal dari titik (0,0), dan koordinat (x,y)yang dapat mewakili titik yang valid di dalam bidang itu, mengembalikan objek yang dapat diubah dari semua titik di dalam pesawat yang arahnya 4 arah. berdekatan dengan(x,y) .

Tujuannya adalah untuk mendefinisikan fungsi itu dalam sesedikit mungkin byte.

Beberapa contoh untuk membantu menggambarkan input / output yang valid:

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)]

Dan inilah contoh (yang ini dengan Python) dari fungsi yang memenuhi persyaratan:

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

Contoh di atas mendefinisikan fungsi bernama, tetapi fungsi anonim juga dapat diterima.

Input n, m, x, yadalah semua bilangan bulat 32-bit yang tidak ditandatangani dalam rentang berikut:

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

Keluaran harus berbentuk iterable (namun bahasa pilihan Anda menentukan bahwa) dari (x, y) pasangan.

Klarifikasi tambahan:

Bilangan kompleks (dan representasi / serialisasi lainnya) boleh saja selama konsumen iterable dapat mengakses xdan ybilangan bulat hanya mengetahui lokasi mereka.

Indeks berbasis non-nol dapat diterima, tetapi hanya jika bahasa pilihan adalah bahasa non-nol-diindeks. Jika bahasa menggunakan campuran sistem penomoran, default ke sistem penomoran struktur data yang paling umum digunakan untuk mewakili sebuah matriks. Jika ini masih semua konsep asing dalam bahasa yang diberikan, indeks awal apa pun dapat diterima.

NightDriveDrones
sumber
6
Selamat datang di situs ini! Tantangan ini cukup bagus menurut standar kami, tetapi ada beberapa hal di sini yang bertentangan dengan gaya kami. Untuk satu, kami lebih suka tantangan yang tidak terbatas pada satu bahasa jika memungkinkan. Jauh lebih menyenangkan ketika semua orang bisa bersaing. Kami juga umumnya mencetak kode-golf dalam byte sebagai lawan dari karakter, mereka sama untuk sebagian besar tujuan tetapi ada beberapa hal yang dapat Anda lakukan jika jawaban diberi skor dalam karakter. Semoga Anda bersenang-senang di sini!
Post Rock Garf Hunter
Kami dijamin bahwa (x,y)itu sendiri di dalam kotak, kan?
xnor
4
Secara default, CGCC memungkinkan program lengkap dan juga berfungsi sebagai pengiriman. Ini membantu memungkinkan bahasa yang tidak harus memiliki konsep fungsi untuk bersaing juga
Jo King
3
Outputnya adalah STDOUT, bukan objek kode. Ini umumnya dapat berupa keluaran apa pun dengan pembatas yang jelas sehingga tidak ambigu dan mengikuti format keluaran
Jo King
2
Apakah boleh mewakili koordinat sebagai bilangan kompleks daripada tupel bilangan bulat?
Joel

Jawaban:

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]

Cobalah online!

Sebutkan keempat tetangga, kemudian gunakan slicing daftar untuk menghapus yang out-of-bounds.


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]

Cobalah online!

Alih-alih memeriksa yang mana dari empat tetangga yang terikat, kami melakukannya dengan cara yang lebih lambat untuk memeriksa semua poin yang terikat untuk yang bertetangga, yang memiliki jarak Euclidian tepat 1 dari (x,y) . Kami juga menggunakan trik div-mod klasik untuk beralih di atas kisi , menghemat kebutuhan untuk menulis dua loop sepertifor i in range(m)for j in range(n) .

Saya mencoba menggunakan aritmatika kompleks untuk menulis kondisi jarak, tetapi ternyata lebih lama untuk menulis 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]

Cobalah online!

Tidak
sumber
11
Selamat atas 100k!
Arnauld
4

Oktaf , 90 byte

Ini menggunakan pendekatan geometris: Pertama kita membuat matriks nol dengan ukuran yang diinginkan, dan mengatur a 1ke lokasi yang diinginkan. Lalu kami berbelit-belit dengan kernel

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

yang menghasilkan matriks baru dengan ukuran yang sama dengan yang ada di 4-tetangga dari titik aslinya. Kemudian kita find()indeks entri bukan nol dari matriks baru ini.

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

Cobalah online!

konvolusi adalah kunci kesuksesan.

cacat
sumber
4
Memang itu, tidak peduli seberapa kecil font
Luis Mendo
3

JavaScript (ES6), 74 byte

Pendekatan membosankan.

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

Cobalah online!


JavaScript (Node.js) , 74 byte

Kurang membosankan tapi sama panjangnya. Mengambil input sebagai ([h,w,x,y]).

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

Cobalah online!


JavaScript (V8) , 67 byte

Jika semua metode keluaran standar diizinkan, kami bisa mencetak koordinat yang valid dengan:

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

Cobalah online!

Arnauld
sumber
2

Jelly ,  13  12 byte

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

Tautan diad menerima daftar dua (0-indeks) bilangan bulat di sebelah kiri [row, column],, dan dua bilangan bulat di sebelah kanan [height, width],, yang menghasilkan daftar daftar bilangan bulat [[adjacent_row_1, adjacent_column_1], ...],.

Cobalah online!

Bagaimana?

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]]
Jonathan Allan
sumber
Anda bisa menggantinya ḶṚƬdengan Ṭ€. 2ḶṚƬNƬẎkembali [[0, 1], [1, 0], [0, -1], [-1, 0]], sementara 2Ṭ€NƬẎkembali [[1], [0, 1], [-1], [0, -1]], dan, karena lajang dibungkus, +hanya vektorisasi dengan elemen pertama untuk mereka, sehingga mereka bertindak seolah-olah elemen kedua mereka 0(identitas aditif). Akibatnya, hanya urutan output yang dapat berubah.
Erik the Outgolfer
2

Perl 6 , 56 49 byte

-7 byte terima kasih kepada nwellnhof!

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

Cobalah online!

Menghapus elemen batas dengan memeriksa jika ketika dibagi dengan batas array itu adalah antara 0 dan 1. Membawa input dan output melalui bilangan kompleks di mana bagian nyata adalah xkoordinat dan imajiner adalah y. Anda dapat mengekstrak ini melalui.im.re fungsi dan .

Jo King
sumber
49 bytes
nwellnhof
@nwellnhof Sangat bagus! Saya akan membangun di atasnya untuk melakukan sesuatu seperti ini , tetapi divtampaknya tidak bekerja untuk Nums
Jo Raja
(*.reals>>.Int Zdiv@^b).noneatau (*.reals Z/@^b)>>.Int.noneakan bekerja tetapi pemain Int tampaknya terlalu mahal.
nwellnhof
1

J , 30 29 28 byte

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

Cobalah online!

Bagaimana:

  • Putar tangan kanan mx narg menjadi kisi-kisi bilangan kompleksj./&i./
  • Sama untuk arg kiri (poin kami) j./
  • Buat topeng yang menunjukkan di mana jarak antara titik kami dan kisi adalah tepat 1 1=|@-
  • Gunakan itu untuk menyaring kisi-kisi, setelah meratakan keduanya #~&,
  • Ubah hasilnya kembali menjadi poin nyata +.@
Jonah
sumber
0

Arang , 29 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Mengambil input dalam urutan x, y, lebar, tinggi. Penjelasan:

Jθη#

Cetak a #pada posisi yang disediakan.

FIζFIε«

Lingkari persegi panjang yang diberikan.

Jικ

Lompat ke posisi saat ini.

¿№KV#⊞υ⟦ικ⟧

Jika ada yang berdekatan #maka simpan posisinya.

»⎚Iυ

Keluarkan posisi yang ditemukan di akhir loop.

Jawaban membosankan:

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Bekerja dengan menemukan posisi yang berdekatan secara matematis.

Neil
sumber
0

Haskell, 62 byte

Menggunakan persamaan lingkaran

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

Cobalah online!

Pendekatan membosankan: 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)]
mb21
sumber