(X, y) 'e 4 yönlü bitişik tüm geçerli noktaların yinelenebilir bir nesnesini döndüren bir işlev yazın


17

Algoritma sınıflarında ve genel olarak bilgisayar bilimlerinde çok yaygın bir ihtiyaç, bir ızgara veya matris (BFS veya DFS gibi) üzerinde 4 yönlü olarak yinelemektir. Bu genellikle döngüler içinde çok sayıda aritmetik ve karşılaştırma ile çok fazla tıknaz ve ayrıntılı kodla sonuçlanır. Buna birçok farklı yaklaşım gördüm, ancak bunu yapmanın daha kısa bir yolu olduğu hissini sarsamıyorum.

Zorluk n, m, noktadan kaynaklanan sonlu bir düzlemin genişliği ve yüksekliği (0,0)ve (x,y)bu düzlemdeki herhangi bir geçerli noktayı temsil edebilen koordinatlar göz önüne alındığında, düzlem içindeki 4 yönlü olan tüm noktaların tekrarlanabilir bir nesnesini döndüren saf bir işlev yazmaktır. bitişik (x,y).

Amaç, bu işlevi olabildiğince az bayt olarak tanımlamaktır.

Geçerli girdi / çıktıyı göstermeye yardımcı olacak bazı örnekler:

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

Ve işte koşulları karşılayan bir fonksiyonun bir örneği (bu Python'da):

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

Yukarıdaki örnekte adlandırılmış bir işlev tanımlanmıştır, ancak anonim işlevler de kabul edilebilir.

Girişlerin n, m, x, ytümü, aşağıdaki aralıklardaki işaretsiz 32 bit tamsayılardır:

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

Çıktı, (x, y) çiftlerinin yinelenebilir (ancak seçtiğiniz dil bunu tanımlar) biçiminde olmalıdır.

Ek açıklamalar:

Karmaşık sayılar (ve diğer temsiller / serileştirmeler), yinelenebilir tüketicinin erişebildiği xvey yalnızca konumlarını bilen tamsayılar olarak uygundur.

Sıfır temelli olmayan dizinler kabul edilebilir, ancak yalnızca seçili dil sıfırlanmamış bir dilse. Dil, numaralandırma sistemlerinin bir karışımını kullanıyorsa, varsayılan olarak bir matrisi temsil etmek için en sık kullanılan veri yapısının numaralandırma sistemini kullanın. Bunların tümü hala verilen dilde yabancı kavramlarsa, herhangi bir başlangıç ​​dizini kabul edilebilir.


6
Siteye Hoşgeldiniz! Bu zorluk standartlarımıza göre oldukça iyi, ama burada tarzımıza aykırı birkaç şey var. Birincisi, mümkünse tek bir dil ile sınırlı olmayan zorlukları tercih ediyoruz. Herkesin yarışabilmesi çok daha eğlenceli. Ayrıca, kod golf oyununu karakterlerin aksine bayt cinsinden puanlarız , çoğu amaç için aynıdır, ancak cevaplar karakterlerde puanlanırsa yapabileceğiniz birkaç ucuz şey vardır. Umarım burada eğlenirsiniz!
Rock Garf Hunter Post

(x,y)Kendisinin dikdörtgenin içinde olduğunu garanti ediyoruz , değil mi?
xnor

4
Varsayılan olarak CGCC, tam programların yanı sıra gönderim işlevi de sağlar. Bu, mutlaka bir işlev kavramına sahip olmayan dillerin de rekabet etmesine izin verir
Jo King

3
Bir çıktı bir kod nesnesi yerine STDOUT olacaktır. Bu genellikle net sınırlayıcılara sahip herhangi bir çıktı olabilir, bu nedenle açıktır ve varsayılan Standart çıktı formatlarını
Jo King

2
Tamsayı tuples yerine koordinatları karmaşık sayılar olarak göstermesine izin veriliyor mu?
Joel

Yanıtlar:


12

Python 2 , 66 bayt

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

Çevrimiçi deneyin!

Dört komşuyu listeler, ardından sınır dışı olanları kaldırmak için liste dilimleme kullanır.


Python 2 , 71 bayt

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]

Çevrimiçi deneyin!

Dört komşunun hangisinin sınır içinde olduğunu kontrol etmek yerine, komşu olanlar için, yani tam olarak 1 Öklid mesafesine sahip olan tüm sınırlar içindeki noktaları kontrol etmenin daha yavaş bir yolunu yapıyoruz (x,y). Ayrıca bir ızgara üzerinde yineleme yapmak için klasik div-mod hile kullanırız ve iki döngü yazma ihtiyacını azaltırız.for i in range(m)for j in range(n) .

Mesafe durumunu yazmak için karmaşık aritmetik kullanmayı denedim, ama yazmak daha uzun çıktı abs((k/n-x)*1j+k%n-y)==1.


Python 2,70 bayt

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]

Çevrimiçi deneyin!


11
100 bin Tebrikler!
Arnauld

4

Oktav , 90 bayt

Bu, geometrik bir yaklaşım kullanır: İlk olarak, istenen büyüklükte sıfırlardan oluşan bir matris oluştururuz ve a'yı 1istenen konuma ayarlıyoruz . Sonra çekirdek ile kıvrık oluyoruz

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

orijinal noktanın 4 komşusu ile aynı boyutta yeni bir matris üretir. Sonra find()bu yeni matrisin sıfır olmayan girdilerinin endeksleri.

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

Çevrimiçi deneyin!

evrişim başarının anahtarıdır.


4
Gerçekten de, yazı tipi ne kadar küçük olursa olsun
Luis Mendo


3

JavaScript (ES6), 74 bayt

Sıkıcı yaklaşım.

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

Çevrimiçi deneyin!


JavaScript (Node.js) , 74 bayt

Daha az sıkıcı ama aynı derecede uzun. Girişi alır ([h,w,x,y]).

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

Çevrimiçi deneyin!


JavaScript (V8) , 67 bayt

Tüm standart çıktı yöntemlerine izin verildiyse, geçerli koordinatları şu şekilde yazdırabiliriz:

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

Çevrimiçi deneyin!


2

Jöle ,  13  12 bayt

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

Solda iki (0 dizinli) tamsayı [row, column]ve sağda iki tamsayı içeren bir ikili Bağlantı ,[height, width] tamsayılar listelerin bir listesini verir, [[adjacent_row_1, adjacent_column_1], ...].

Çevrimiçi deneyin!

Nasıl?

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

Sen yerini alabilir ḶṚƬile Ṭ€. 2ḶṚƬNƬẎdöndürür [[0, 1], [1, 0], [0, -1], [-1, 0]], 2Ṭ€NƬẎdöndürür [[1], [0, 1], [-1], [0, -1]]ve +tek tekler sarıldığından, yalnızca bunların ilk öğesiyle vektörleşir , bu nedenle ikinci öğeleri 0(ek kimlik) gibi davranırlar . Sonuç olarak, yalnızca çıkışın sırası değişebilir.
Outgolfer Erik

2

Perl 6 , 56 49 bayt

Nwellnhof sayesinde -7 bayt!

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

Çevrimiçi deneyin!

Dizi sınırlarına bölündüğünde 0 ile 1 arasında olup olmadığını kontrol ederek sınırların dışına çıkan öğeleri kaldırır. Gerçek parçanın xkoordinat ve hayali olduğu karmaşık sayılarla girdi ve çıktı alır y. Bunları .imve .reişlevlerinden çıkarabilirsiniz .



@nwellnhof Çok hoş! Ben böyle bir şey yapmak için üzerine inşa ediyorum bu , ama diviçin işe görünmüyor Nums
Jo Kral

(*.reals>>.Int Zdiv@^b).noneveya (*.reals Z/@^b)>>.Int.noneInt-cast çok maliyetli görünüyor.
nwellnhof

1

J , 30 29 28 bayt

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

Çevrimiçi deneyin!

Nasıl:

  • Sağ eli çevirin mxn arg öğesini karmaşık sayılar ızgarasınaj./&i./
  • Sol arg için de aynı şey (bizim amacımız) j./
  • Bizim nokta ve ızgara arasındaki mesafenin tam olarak nerede olduğunu gösteren bir maske oluşturun 1 1=|@-
  • Her ikisini de düzleştirdikten sonra ızgarayı filtrelemek için bunu kullanın #~&,
  • Sonucu tekrar gerçek noktalara çevirin +.@


0

Kömür , 29 bayt

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

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı versiyonudur. Girişleri x, y, genişlik, yükseklik sırasıyla alır. Açıklama:

Jθη#

#Verilen konumda a yazdırın .

FIζFIε«

Verilen dikdörtgenin üzerinden geçin.

Jικ

Geçerli konuma atla.

¿№KV#⊞υ⟦ικ⟧

Bir bitişik #varsa konumu kaydedin.

»⎚Iυ

Döngünün sonunda bulunan konumların çıktısını alın.

Sıkıcı cevap:

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

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı versiyonudur. Bitişik konumları matematiksel olarak bularak çalışır.


0

Haskell, 62 bayt

kullanma daire denklemi

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

Çevrimiçi deneyin!

Sıkıcı yaklaşım: 81 bayt

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)]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.