Чи проходить ця лінія через цю площу?


19

Розділіть перший квадрант (включаючи позитивну вісь x, позитивну вісь y та початок) на сітки 1x1, кожну сітку позначте координатами її лівого нижнього кута, як показано нижче:

Зауважте, що кожна сітка містить свої межі та вершини. Використовуючи математичні символи, сітка з міткою (m, n) буде представляти квадрат {(x,y) | m ≤ x ≤ m+1, n ≤ y ≤ n+1}.


Дано пряму лінію у вигляді ax+by+c=0цілих чисел a, bі cта сітку, представлену символом (m,n), виведіть, чи проходить лінія через сітку, тобто чи є якась точка в даній сітці.


a  b  c m n output
1  1  0 0 0 true
1  1  0 1 1 false
1  1  0 0 2 false
1  1 -3 0 1 true
1  1 -3 0 0 false
2 -1  0 1 1 true
2 -1  0 1 0 false
2 -1  0 0 2 true
2 -1  0 0 1 true
2 -1  0 1 2 true
2  0 -1 0 0 true
2  0 -1 0 1 true
2  0 -1 0 2 true
2  0 -1 1 0 false
2  0 -1 1 1 false
0  2 -1 0 0 true
0  2 -1 1 0 true
0  2 -1 2 0 true
0  2 -1 0 1 false
0  2 -1 1 1 false
1  0 -1 0 0 true
1  0 -1 0 1 true
1  0 -1 0 2 true
1  0 -1 1 0 true
1  0 -1 1 1 true

Просимо запропонувати більше тестів у коментарях.


Це . Найкоротша відповідь у байтах виграє. Застосовуються стандартні лазівки .


1
Звичайно, ми повинні мати можливість припустити, що не і a, і b дорівнюють 0, оскільки тоді, якщо c дорівнює нулю, може існувати нескінченна лінія, тоді як якщо c ненульова, то взагалі не може бути лінії.
Ерік Аутгольфер

Чи можу я отримати вхід у вигляді двох або більше масивів, скажімо [a, b, c](лінія) та [m, n](квадрат)?
Ерік Аутгольфер

@EriktheOutgolfer Я здивований, що це не мета.
Лина монашка


Відповіді:


5

Пітон 3, 84 66 байт

Перший гольф, перший провал (можливо).

Дякуємо Роду, що голив 18 байт, використовуючи функцію замість прямого введення.

def f(a,b,c,m,n):f=-(a*m+c)/b;g=f-a/b;print(min(f,g)<=n<=max(f,g))

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

Пояснення:

В основному ми обчислюємо значення функції рядка для m і m + 1, якщо n знаходиться між значеннями, то список повинен пройти через нього в якийсь момент. Було б набагато краще, якби мова мала якийсь простіший спосіб введення декількох цілих чисел.



2
Ласкаво просимо до PPCG!
betseg

1
Чи не потрібно це перевіряти на n + 1, а також на m + 1?
Ніл

3
Ділення на нуль, коли bє 0.
Олів'є Грегоар

Крім того, він не проходить декілька тестових випадків, наголошених Leaky Nun.
Олів'є Грегоар

5

Желе , 10 байт

ż‘{Œpæ.ṠE¬

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

Фон

Як і інші відповіді перед моєю, і ця спирається на той факт, що пряма ділить площину на дві напівплощини. Прямокутник або міститься в одній із цих напівплощин (не перетинається з лінією), або перетинає обидві напівплощини (і, отже, лінію, яка їх розділяє.

Як це працює

ż‘{Œpæ.ṠE¬  Main link. Left argument: [m, n]. Right argument: [a, b, c]

 ‘{         Increment left; yield [m+1, n+1].
ż           Zipwith; yield [[m, m+1], [n, n+1]].
   Œp       Cartesian product; yield [[m, n], [m, n+1], [m+1, n], [m+1, n+1]].
     æ.     Take the dot products with [a, b, c], mapping each [x, y] to ax+by+c.
       Ṡ    Take the signs.
        E   Test the signs for equality.
         ¬  Logical NOT.

4

Python 2 , 59 байт

lambda a,b,c,m,n:min(0,a,b,a+b)<=-a*m-b*n-c<=max(0,a,b,a+b)

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

Ми можемо сказати, на якій стороні прямої знаходиться точка від знака a*x+b*y+c. Лінія проходить через квадрат (рахуючи дотик), якщо всі чотири вершини не (m,n),(m,n+1),(m+1,n),(m+1,n+1)знаходяться строго на одній стороні лінії. Ми можемо підключити ці значення до витягу з константи, a*m+b*n+cяка з’являється у всіх чотирьох:

a*m+b*n+c
a*m+b*n+c+a
a*m+b*n+c+b
a*m+b*n+c+a+b

Отже, лінія проходить через квадрат, якщо всі ці чотири значення не є позитивними або всіма негативними. Отже, достатньо, щоб їх мінімум був <=0і максимум був >=0.

min(a*m+b*n+c,a*m+b*n+c+a,a*m+b*n+c+b,a*m+b*n+c+a+b)<=0<=max(a*m+b*n+c,a*m+b*n+c+a,a*m+b*n+c+b,a*m+b*n+c+a+b)

Віднімання спільного a*m+b*n+cз кожної частини дає код.

Трохи довший підхід - перевірити, чи має набір знаків (+, 0, -) довжину щонайменше 2.

Python 2 , 62 байти

lambda a,b,c,m,n:len({cmp(a*m+b*n+c,-d)for d in(0,a,b,a+b)})>1

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


3

Математика, 60 55 байт

Solve[m#+n#2==-#3&&#4<=m<=#4+1&&#5<=n<=#5+1,{m,n}]!={}&

-5 байт більше ніж на @MartinEnder

форма введення

[a, b, c, m, n]


2
Ах, я б хотів, щоб у кожної мови була Solveфункція ...
Ерік Позакореневий

3

Пакет, 66 байт

@cmd/cset/a"q=%1*%4+%2*%5+%3,((-(q+%1)*(q+%2)&-q*(q+%1+%2))>>31)+1

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


1

Математика, 50 байт

-4<Tr@Sign[Tuples@{{#,#+1},{#2,#2+1}}.{##4}+#3]<4&

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

Бере m, n, c, a, b як вхід у цьому порядку.

Пояснення: Tuples@{{#,#+1},{#2,#2+1}}складає список координат чотирьох кутів квадрата, потім бере крапковий добуток із .{##4}(що означає {#4, #5}) та додає +#3обчислення ax + by + cдля x,yкожного кута. Якщо лінія проходить через точку, це дорівнює нулю; якщо рядок далі від початку, це негатив; і якщо лінія наближається до початку, вона позитивна - тому ми перевіряємо Signs цих чотирьох значень. Рядок проходить поза квадратом тоді і лише тоді, коли всі чотири значення дорівнюють 1 або всі чотири дорівнюють -1, тому ми перевіряємо, чи сума їх суворо між -4 і 4.

(Ця відповідь смутно надихається моєю відповіддю на це запитання .)



1

Пітон , 54 байти

lambda a,b,c,m,n:abs(2*(a*m+b*n+c)+a+b)<=abs(a)+abs(b)

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

(Завдяки xnor за тестовий сценарій.)

Як це працює

Лінія проходить через m + 1/2 + x , n + 1/2 + y, якщо і тільки якщо

a ⋅ ( m + 1/2 + x ) + b ⋅ ( n + 1/2 + y ) + c = 0
⇔ 2⋅ ( am + bn + c ) + a + b = −2⋅ ax - 2⋅ by .

Це можливо для деяких | х |, | у | ≤ 1/2 тоді і тільки тоді, коли | 2⋅ ( am + bn + c ) + a + b | ≤ | a | + | б |.


1

Java (OpenJDK 8) , 71 байт

(a,b,c,x,y)->(0<a?0:a)+(0<b?0:b)<=(x=-a*x-b*y-c)&x<=(0>a?0:a)+(0>b?0:b)

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

Порт рішення Python xnor.

Оригінальне рішення з використанням вбудованого перетину форми / лінії Java (108 байт)

(a,b,c,x,y)->b==0?x<=-c/a&-c/a<=x+1:new java.awt.Rectangle(x,y,1,1).intersectsLine(x,c=(c+a*x)/-b,x+1,c-a/b)

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

Кредити

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