Напишіть функцію, яка повертає ітерабельний об'єкт усіх дійсних точок, 4-спрямованих поруч із (x, y)


17

Дуже поширеною потребою в класах алгоритмів та інформатики взагалі є ітерація в 4 напрямках по сітці або матриці (наприклад, у BFS або DFS). Це, здається, часто призводить до багато незграбних та багатослівних кодів з великою кількістю арифметики та порівнянь в циклі. Я бачив багато різних підходів до цього, але не можу похитнутись від відчуття, що існує більш стислий спосіб зробити це.

Завдання полягає в тому, щоб написати чисту функцію, яка, враховуючи ширину і висоту кінцевої площини, що n, mпочинається в точці (0,0), і координати, (x,y)які можуть представляти будь-яку дійсну точку в цій площині, повертає ітерабельний об'єкт усіх точок всередині площини, які є 4-х напрямними. прилеглий до (x,y).

Мета - визначити цю функцію якомога менше байтів.

Деякі приклади, які допоможуть проілюструвати дійсні введення / виведення:

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

Ось приклад (ця в Python) функції, яка задовольняє умовам:

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

У наведеному вище прикладі визначена названа функція, але анонімні функції також прийнятні.

Усі входи n, m, x, y- це непідписані 32-бітні цілі числа в наступних діапазонах:

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

Вихід повинен мати форму ітерабельного (проте ваша мова вибору визначає цю) з (x, y) пар.

Додаткові роз'яснення:

Комплексні числа (та інші представлення / серіалізації) в порядку, поки споживач ітерабельного доступу може отримати доступ xі yяк цілі числа, знаючи лише їх місцезнаходження.

Ненульові індекси є прийнятними, але лише якщо обраною мовою є ненульова мова. Якщо мова використовує суміш систем нумерації, за замовчуванням система нумерації структури даних, яка найчастіше використовується для представлення матриці. Якщо це все ще іноземні поняття даною мовою, будь-який початковий індекс є прийнятним.


6
Ласкаво просимо на сайт! Цей виклик за нашими мірками досить хороший, але тут є кілька речей, які суперечать нашому стилю. Для одного ми віддаємо перевагу проблемам, які, якщо можливо, не обмежуються однією мовою. Набагато веселіше, коли кожен може змагатися. Ми також загалом набираємо код-гольф у байтах , на відміну від символів, вони однакові для більшості цілей, але є кілька хитрощів, які можна зробити, якщо відповіді набрані символами. Сподіваюся, вам тут весело!
Опублікувати Rock Garf Hunter

Ми гарантуємо, що (x,y)сама знаходиться у прямокутнику, правда?
xnor

4
За замовчуванням CGCC дозволяє повноцінні програми, а також функції як подання. Це допомагає дозволити конкурувати мовам, які не обов'язково мають поняття функцій
Jo King,

3
Вихід буде STDOUT, а не об'єктом коду. Як правило, це може бути будь-який вихід із чіткими роздільниками, тому це однозначно та дотримуйтесь стандартних форматів виводу
Jo King,

2
Чи дозволяється представляти координати як складні числа, а не цілі кортежі?
Джоель

Відповіді:


12

Python 2 , 66 байт

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

Спробуйте в Інтернеті!

Списки чотирьох сусідів, а потім використовує розріз списку, щоб видалити ті, хто знаходиться поза межами.


Python 2 , 71 байт

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]

Спробуйте в Інтернеті!

Замість того, щоб перевіряти, хто з чотирьох сусідів знаходиться в межах, ми робимо це більш повільним способом перевірки всіх точок в межах для тих, хто є сусідами, тобто відстань Евклідова рівно 1 від (x,y). Ми також використовуємо класичний фокус div-mod, щоб перебирати сітку , економлячи необхідність написання двох циклів на кшталт for i in range(m)for j in range(n).

Я намагався використовувати складну арифметику, щоб записати умову відстані, але вийшло довше писати abs((k/n-x)*1j+k%n-y)==1.


Python 2 , 70 байт

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]

Спробуйте в Інтернеті!


11
З повагою 100 к!
Арнольд

4

Октава , 90 байт

Для цього використовується геометричний підхід: спочатку ми створюємо матрицю нулів потрібного розміру та встановлюємо а 1на потрібне місце. Потім обертаємося ядром

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

яка створює нову матрицю однакового розміру з такою у 4-сусідів вихідної точки. Тоді ми find()індексуємо ненульові записи цієї нової матриці.

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

Спробуйте в Інтернеті!

згортання - запорука успіху.


4
Дійсно, як би не був шрифт
Луїс Мендо


3

JavaScript (ES6), 74 байти

Нудний підхід.

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

Спробуйте в Інтернеті!


JavaScript (Node.js) , 74 байти

Менш нудно, але так само довго. Вводиться як " ([h,w,x,y]).

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

Спробуйте в Інтернеті!


JavaScript (V8) , 67 байт

Якби всі стандартні методи виводу були дозволені, ми могли б просто надрукувати дійсні координати за допомогою:

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

Спробуйте в Інтернеті!


2

Желе ,  13  12 байт

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

Двійковий Посилання приймаючи список з двох (0-індексованих) цілих чисел на лівій стороні , [row, column]і два цілих числа по правому [height, width], що дає список списків цілих чисел, [[adjacent_row_1, adjacent_column_1], ...].

Спробуйте в Інтернеті!

Як?

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

Ви можете замінити ḶṚƬна Ṭ€. 2ḶṚƬNƬẎповертається [[0, 1], [1, 0], [0, -1], [-1, 0]], тоді як 2Ṭ€NƬẎповертається [[1], [0, 1], [-1], [0, -1]], і, оскільки сингли завернуті, +лише векторизується з першим елементом для них, тож вони діють так, ніби другий їх елемент 0(ідентифікатор добавки). В результаті може змінюватися лише порядок виводу.
Erik the Outgolfer

2

Perl 6 , 56 49 байт

-7 байт завдяки nwellnhof!

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

Спробуйте в Інтернеті!

Вилучає елементи поза межами, перевіряючи, якщо при поділі на межі масиву він знаходиться між 0 і 1. Здійснює введення та виведення за допомогою складних чисел, де реальна частина є xкоординатою, а уявна - y. Ви можете витягнути їх за допомогою .imі .reфункцій.



@nwellnhof Дуже приємно! Я б побудувати на ньому , щоб зробити що - щось на зразок цього , але divне схоже на роботу для Numз
Джо Кінг

(*.reals>>.Int Zdiv@^b).noneабо (*.reals Z/@^b)>>.Int.noneможе працювати, але Int-лиття здається занадто дорогим.
nwellnhof

1

J , 30 29 28 байт

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

Спробуйте в Інтернеті!

Як:

  • Перетворіть праву руку mx narg в сітку складних чиселj./&i./
  • Те саме для лівого аргументу (наша точка) j./
  • Створіть маску, яка показує, де рівно відстань між нашою точкою та сіткою 1=|@-
  • Використовуйте це для фільтрації сітки після вирівнювання обох #~&,
  • Перетворіть результат назад у реальні точки +.@


0

Вугілля деревне , 29 байт

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Приймає входи у порядку x, y, ширині, висоті. Пояснення:

Jθη#

Роздрукуйте в #заданій позиції.

FIζFIε«

Проведіть петлю над заданим прямокутником.

Jικ

Перейти до поточного положення.

¿№KV#⊞υ⟦ικ⟧

Якщо є сусідній, #тоді збережіть позицію.

»⎚Iυ

Вивести виявлені положення в кінці циклу.

Нудна відповідь:

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Працює, знаходячи сусідні положення математично.


0

Хаскелл, 62 байти

Використання рівняння круга

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

Спробуйте в Інтернеті!

Нудний підхід: 81 байт

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)]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.