Questa linea passa attraverso quel quadrato?


19

Dividi il primo quadrante (includendo l'asse x positivo, l'asse y positivo e l'origine) in griglie 1x1, con ciascuna griglia etichettata dalle coordinate del suo angolo inferiore sinistro, come mostrato di seguito:

Si noti che ogni griglia contiene i suoi confini e i suoi vertici. Usando i simboli matematici, la griglia etichettata (m, n) rappresenterebbe il quadrato {(x,y) | m ≤ x ≤ m+1, n ≤ y ≤ n+1}.


Data una linea retta sotto forma di ax+by+c=0numeri interi ae b, e c, e una griglia rappresentata da (m,n), indica se la linea passa attraverso la griglia, ovvero se sulla linea è presente un punto qualsiasi della griglia.


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

Si prega di suggerire ulteriori test nei commenti.


Questo è . Vince la risposta più breve in byte. Si applicano scappatoie standard .


1
Ovviamente dovremmo essere in grado di supporre che non sia a che b siano 0, dal momento che se c è zero ci possono essere linee infinite mentre se c è diverso da zero non può esserci alcuna linea.
Erik the Outgolfer,

Posso ottenere input come due o più array, ad esempio [a, b, c](la linea) e [m, n](il quadrato)?
Erik the Outgolfer,

@EriktheOutgolfer Sono sorpreso che non sia in meta.
Leaky Nun,


Risposte:


5

Python 3, 84 66 byte

Primo golf, primo fallimento (forse).

Grazie a Rod per la rasatura di 18 byte utilizzando una funzione anziché l'input diretto.

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

Provalo online!

Spiegazione:

Fondamentalmente calcoliamo il valore della funzione di linea per m e m + 1, se n è compreso tra i valori, quindi l'elenco deve attraversarlo ad un certo punto. Sarebbe molto meglio se la lingua avesse un modo più semplice per inserire più numeri interi.



2
Benvenuti in PPCG!
Betseg,

1
Non è necessario verificare con n + 1 e m + 1?
Neil,

3
Divisione per zero quando bè 0.
Olivier Grégoire,

Inoltre, non passa diversi casi di test evidenziati da Leaky Nun.
Olivier Grégoire,

5

Gelatina , 10 byte

ż‘{Œpæ.ṠE¬

Provalo online!

sfondo

Come altre risposte prima della mia, ciò si basa sul fatto che una linea retta divide l'aereo in due semi-piani. Il rettangolo è contenuto in uno di questi semi-piani (nessuna intersezione con la linea) o interseca entrambi i semiplanes (e quindi la linea che li separa.

Come funziona

ż‘{Œ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 byte

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

Provalo online!

Possiamo dire da quale parte della linea un punto è rappresentato dal segno a*x+b*y+c. La linea passa attraverso il quadrato (contando toccando) a meno che tutti e quattro i vertici non (m,n),(m,n+1),(m+1,n),(m+1,n+1)siano strettamente sullo stesso lato della linea. Possiamo inserire questi valori in un estratto la costante a*m+b*n+cche appare in tutti e quattro:

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

Quindi, la linea passa attraverso il quadrato a meno che questi quattro valori non siano tutti positivi o tutti negativi. Quindi, è sufficiente che il loro minimo sia <=0e il massimo sia >=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)

Sottraendo il comune a*m+b*n+cda ogni parte si ottiene il codice.

Un approccio leggermente più lungo consiste nel verificare se l'insieme di segni (+, 0, -) ha una lunghezza di almeno 2.

Python 2 , 62 byte

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

Provalo online!


3

Mathematica, 60 55 byte

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

-5 byte grazie a @MartinEnder

modulo di input

[A, b, c, m, n]


2
Ah, vorrei che ogni lingua avesse una Solvefunzione ...
Erik the Outgolfer,

3

Lotto, 66 byte

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

Spiegazione: Consideriamo i valori presi dall'equazione ai quattro angoli della cella. Se la linea non interseca la cella, tutti e quattro i valori hanno lo stesso segno, ma se interseca la cella, almeno un valore sarà zero o il segno opposto. Il confronto è semplificato moltiplicando le coppie di angoli opposti, quindi se entrambi i valori sono positivi la linea non interseca la cella. Alcuni bit-twiddling convertono quindi le moltiplicazioni in un risultato complessivo.


1

Mathematica, 50 byte

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

Provalo online!

Accetta m, n, c, a, bcome input in questo ordine.

Spiegazione: Tuples@{{#,#+1},{#2,#2+1}}crea un elenco delle coordinate dei quattro angoli del quadrato, quindi prende il prodotto punto con .{##4}(che significa {#4, #5}) e aggiunge +#3calcoli ax + by + cper x,yogni angolo. Se la linea passa attraverso il punto, questo è zero; se la linea è più lontana dall'origine, è negativa; e se la linea è più vicina all'origine, è positiva - quindi controlliamo la Signs di questi quattro valori. La linea passa fuori dal quadrato se e solo se tutti e quattro i valori sono 1 o tutti e quattro sono -1, quindi controlliamo che la loro somma sia strettamente compresa tra -4 e 4.

(Questa risposta è vagamente ispirata dalla mia risposta a questa domanda .)



1

Python , 54 byte

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

Provalo online!

(Grazie a xnor per lo script di test.)

Come funziona

La linea passa attraverso m + 1/2 + x , n + 1/2 + y se e solo se

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

Questo è possibile per alcuni | x |, | y | ≤ 1/2 se e solo se | 2⋅ ( am + bn + c ) + a + b | ≤ | a | + | b |.


1

Java (OpenJDK 8) , 71 byte

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

Provalo online!

Porta della soluzione Python di xnor.

Soluzione originale, utilizzando la forma / intersezione linea Java incorporati (108 byte)

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

Provalo online!

Titoli di coda

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.