Est-ce que cette ligne passe par ce carré?

19

Divisez le premier quadrant (y compris l'axe x positif, l'axe y positif et l'origine) en grilles 1x1, chaque grille étant étiquetée par les coordonnées de son coin inférieur gauche, comme illustré ci-dessous:

Notez que chaque grille contient ses limites et ses sommets. En utilisant des symboles mathématiques, la grille étiquetée (m, n) représenterait le carré {(x,y) | m ≤ x ≤ m+1, n ≤ y ≤ n+1}.


Compte tenu d' une ligne droite sous la forme d' ax+by+c=0avec des nombres entiers a, bet c, et une grille représentée par (m,n), la sortie si la ligne passe à travers la grille, à savoir si un point quelconque de la grille donnée est sur la ligne.


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

Veuillez suggérer plus de tests dans les commentaires.


C'est du . La réponse la plus courte en octets l'emporte. Des échappatoires standard s'appliquent.

Leaky Nun
la source
1
Bien sûr, nous devrions pouvoir supposer que a et b ne sont pas tous les deux égaux à 0, car alors si c est nul, il peut y avoir des lignes infinies tandis que si c est non nul, il ne peut pas y avoir de ligne du tout.
Erik the Outgolfer
Puis-je obtenir une entrée sous forme de deux tableaux ou plus, disons [a, b, c](la ligne) et [m, n](le carré)?
Erik the Outgolfer
@EriktheOutgolfer Je suis surpris que ce ne soit pas dans la méta.
Leaky Nun
Connexes
Pas un arbre
Fortement lié .
Olivier Grégoire

Réponses:

5

Python 3, 84 66 octets

Premier golf, premier échec (peut-être).

Merci à Rod d'avoir rasé 18 octets en utilisant une fonction au lieu d'une entrée directe.

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

Essayez-le en ligne!

Explication:

Fondamentalement, nous calculons la valeur de la fonction de ligne pour m et m + 1, si n est entre les valeurs, alors la liste doit la traverser à un moment donné. Ce serait beaucoup mieux si le langage avait un moyen plus simple de saisir plusieurs entiers.

irréparable
la source
2
Bienvenue chez PPCG!
betseg
1
Cela n'a-t-il pas besoin de vérifier aussi bien n + 1 que m + 1?
Neil
3
Division par zéro quand best 0.
Olivier Grégoire
De plus, il ne passe pas plusieurs cas de test mis en évidence par Leaky Nun.
Olivier Grégoire
5

Gelée , 10 octets

ż‘{Œpæ.ṠE¬

Essayez-le en ligne!

Contexte

Comme d'autres réponses avant la mienne, cela repose sur le fait qu'une ligne droite divise l'avion en deux demi-plans. Le rectangle est soit contenu dans l'un de ces demi-plans (pas d'intersection avec la ligne) ou coupe les deux demi-plans (et donc la ligne qui les sépare.

Comment ça fonctionne

ż‘{Œ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.
Dennis
la source
4

Python 2 , 59 octets

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

Essayez-le en ligne!

Nous pouvons dire de quel côté de la ligne se trouve un point par le signe a*x+b*y+c. La ligne passe par le carré (en comptant le toucher) à moins que les quatre sommets ne (m,n),(m,n+1),(m+1,n),(m+1,n+1)soient strictement du même côté de la ligne. Nous pouvons brancher ces valeurs dans un extrait de la constante a*m+b*n+cqui apparaît dans les quatre:

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

Ainsi, la ligne passe par le carré à moins que ces quatre valeurs soient toutes positives ou toutes négatives. Il suffit donc que leur minimum <=0et leur maximum soient >=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)

La soustraction du commun a*m+b*n+cde chaque partie donne le code.

Une approche légèrement plus longue consiste à vérifier si l'ensemble des signes (+, 0, -) a une longueur d'au moins 2.

Python 2 , 62 octets

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

Essayez-le en ligne!

xnor
la source
3

Mathematica, 60 55 octets

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

-5 octets merci à @MartinEnder

formulaire de saisie

[a, b, c, m, n]

J42161217
la source
2
Ah, je souhaite que chaque langue ait une Solvefonction ...
Erik the Outgolfer
3

Lot, 66 octets

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

Explication: Nous considérons les valeurs prises par l'équation aux quatre coins de la cellule. Si la ligne n'intersecte pas la cellule, alors les quatre valeurs ont le même signe, mais si elle intersecte la cellule, alors au moins une valeur sera zéro ou le signe opposé. La comparaison est simplifiée en multipliant les paires de coins opposés, puis si les deux valeurs sont positives, la ligne n'intersecte pas la cellule. Un peu de twiddling convertit ensuite les multiplications en un résultat global.

Neil
la source
1

Mathematica, 50 octets

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

Essayez-le en ligne!

Prend m, n, c, a, b en entrée dans cet ordre.

Explication: Tuples@{{#,#+1},{#2,#2+1}}fait une liste des coordonnées des quatre coins du carré, puis prend le produit scalaire avec .{##4}(ce qui signifie {#4, #5}) et ajoute des +#3calculs ax + by + cpourx,y à chaque coin. Si la ligne passe par le point, c'est zéro; si la ligne est plus éloignée de l'origine, c'est négatif; et si la ligne est plus proche de l'origine, elle est positive - nous vérifions donc le Signs de ces quatre valeurs. La ligne passe à l'extérieur du carré si et seulement si les quatre valeurs sont égales à 1 ou si les quatre sont égales à -1, nous vérifions donc que leur somme est strictement comprise entre -4 et 4.

(Cette réponse est vaguement inspirée de ma réponse à cette question .)

Pas un arbre
la source
1

Python 2, 147 110 octets

def f(a,b,c,m,n):
 if b:d=sorted((-a*x-c)/float(b)for x in(m,m+1));return d[0]-1<=n<=d[1]
 return m<=-c/a<=m+1

Et un énorme merci à Leaky Nun!

TIO.

Daniel
la source
131 octets
Leaky Nun
121 octets
Leaky Nun
@LeakyNun, wow génial!
Daniel
114 octets
Leaky Nun
110 octets
Leaky Nun
1

Python , 54 octets

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

Essayez-le en ligne!

(Merci à xnor pour le script de test.)

Comment ça fonctionne

La ligne passe par m + 1/2 + x , n + 1/2 + y si et seulement si

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

C'est possible pour certains | x |, | y | ≤ 1/2 si et seulement si | 2⋅ ( am + bn + c ) + a + b | ≤ | a | + | b |.

Anders Kaseorg
la source
1

Java (OpenJDK 8) , 71 octets

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

Essayez-le en ligne!

Port de la solution Python de xnor.

Solution originale, utilisant l'intersection forme / ligne de Java intégrée (108 octets)

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

Essayez-le en ligne!

Crédits

Olivier Grégoire
la source