这条线是否穿过那个正方形?


19

将第一个象限(包括正x轴,正y轴和原点)划分为1x1网格,每个网格均由其左下角的坐标标记,如下所示:

请注意,每个网格都包含其边界和顶点。使用数学符号,标为(m,n)的网格将代表正方形{(x,y) | m ≤ x ≤ m+1, n ≤ y ≤ n+1}


鉴于形式的直线ax+by+c=0与整数ab以及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不为零,则根本没有行。
暴民埃里克(Erik the Outgolfer)'17年

我能否以两个或多个数组(例如,[a, b, c](线)和[m, n](正方形))获得输入?
暴民埃里克(Erik the Outgolfer)'17年

@EriktheOutgolfer我很惊讶这不在meta中。
Leaky Nun


Answers:


5

Python 3,84 66字节

第一次打高尔夫球,第一次失败(也许)。

感谢Rod通过使用函数而不是直接输入来减少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
被零除时b0
奥利维尔·格雷戈尔

而且,它没有通过Leaky Nun强调的几个测试用例。
奥利维尔·格雷戈尔(OlivierGrégoire),

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

Mathematica,60 55字节

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

-5字节thanx到@MartinEnder

输入表格

[a,b,c,m,n]


2
啊,我希望每种语言都有Solve功能……
Outgolfer的Erik

3

批次,66个字节

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

说明:我们考虑方程式在单元格四个角处取的值。如果该线没有与该单元格相交,则所有四个值都具有相同的符号,但是,如果该线与该单元格相交,则至少一个值将为零或相反的符号。通过将成对的对角线相乘来简化比较,然后,如果两个值都为正,则该线不会与像元相交。然后,一些位纠缠将乘法转换为整体结果。


1

Mathematica,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 + cx,y在每个拐角处。如果线穿过该点,则为零;否则为零。如果线离原点较远,则为负;如果该线离原点较近,则为正值-因此我们检查Sign这四个值的s。当且仅当所有四个值均为1或所有四个值为-1时,线才通过正方形之外,因此我们检查其总和严格在-4和4之间。

(这个答案是我对这个问题的回答含糊地启发了我。)



1

Python,54个字节

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

在线尝试!

(感谢xnor提供测试脚本。)

怎么运行的

仅当且仅当行通过m + 1/2 + xn + 1/2 + y

一个 ⋅( + 1/2 + X)+ b ⋅(Ñ + 1/2 + Ý)+ C ^ = 0
⇔2⋅(一个 + bÑ + c ^)+ 一个 + b =-2⋅ 一个X - 2⋅ bÿ

对于某些|这是可能的。x |,| y | ≤1/2当且仅当|2⋅(一个 + bÑ + c ^)+ 一个 + b | ≤| 一个 | + | b |。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.