当子弹相撞


16

这项挑战是基于我不久前在一本书中读到的一个谜语,我在这里再次发现了这个谜语。这是关于每秒以不同速度从枪上发射的子弹永远沿直线传播。当一颗子弹击中另一颗子弹时,两者都被完全摧毁。(可以将所有“子弹”实例替换为“导弹”。)

任务

给定子弹速度的发射顺序列表,确定是否销毁了所有子弹。

规则

  • 输入是一列非负整数,由任何定界符分隔,并在其前后带有一个可选字符。这些是有效的输入:1 2 3 4 5 6[1,2,3,4,5,6]。程序员做出选择。
  • 如果至少一颗子弹可以永远存活,则输出真实值,否则输出虚假值。
  • 子弹速度以每秒单位给出。
  • 项目符号同时且连续地移动。
  • 项目符号可能会在小数偏移处发生碰撞。
  • 同时到达精确相同位置的多个子弹(无论是与原点的偏移量是整数偏移还是分数偏移)都相互碰撞。

例子

在这些图中,G表示枪,>子弹,*是子弹碰撞和爆炸的时间。

特鲁西

输入: 0

        0123456789
Time 0 G>
     1 G>
     2 G>
   ...

输出: 1


输入: 0 0 0

        0123456789
Time 0 G>
     1 G*
     2 G>
     3 G>
     4 G>
   ...

输出: 1


输入: 1

        0123456789
Time 0 G>
     1 G >
     2 G  >
     3 G   >
   ...

输出: 1


输入: 2 1

        0123456789
Time 0 G>
     1 G> >
     2 G >  >
     3 G  >   >
     4 G   >    >
   ...

输出: 1


输入: 2 3 1

        0123456789
Time 0 G>
     1 G> >
     2 G>  >>
     3 G >    *
     4 G  >
     5 G   >
   ...

输出: 1


虚假

输入: 1 2 3 4 5 6

        Unit      1111111111
        01234567890123456789
Time 0 G>
     1 G>>
     2 G> *
     3 G>  >
     4 G>   > >
     5 G>    >  >>
     6 G      >   > *
     7 G            >  >
     8 G                  > >
     9 G                        >>
    10 G                              *
                  111111111122222222223
        0123456789012345678901234567890

输出: 0


输入: 1 0 0 3

        Unit
        0123456789
Time 0 G>
     1 G>>
     2 G* >
     3 G>  >
     4 G   >>
     5 G     *

(第二次碰撞在时间4.5)
输出:0


输入: 2 1 2 3 6 5

        Unit      1111111111
        01234567890123456789
Time 0 G>
     1 G> >
     2 G>>  >
     3 G> *   >
     4 G>  >    >
     5 G>     *   >
     6 G     >      >
     7 G          >   >
     8 G               >>
     9 G                *
                  1111111111
        01234567890123456789

输出: 0


输入: 2 3 6

        Unit
        0123456789
Time 0 G>
     1 G> >
     2 G>  >>
     3 G      *

输出: 0


我可以要求输入被分隔1<enter>2<enter>3...吗?

@sysreq:推动它,但是我会允许的。
El'endia Starman 2015年

我同意qunitopia-这个挑战很难实现,但我正在努力解决……
zmerch 2015年

Answers:


4

Python 2中,388个 392 388 346 342 336 331字节

z=k=input();l=len(k);v=range;u=v(l)
while l<z:
 r="";o=[r]*l;z=l
 for h in v(l):
    if r:o[h-1]=o[m]=r;m=h;r=""
    for j in v(h+1,l):
     p=k[h];q=k[j];t=u[j];n=(1.0*q*t-p*u[h])/(q-p)if q-p else""if p>0 else t
     if t<=n<r<()>o[j]>=n<=o[h]:r=n;m=j
 i=0;s=o and min(o)
 while i<l:
    if o[i]==s!="":del k[i],o[i],u[i];l-=1
    else:i+=1
print l

我的天,这东西很大,但我相信它确实有效。一旦您看到了它的所有复杂性,这个挑战就很难了。

我不确定是否可以在不输入几个小时的情况下详细解释它的工作原理,所以我只给出一个执行摘要。

主要的while循环不断循环,直到输入列表不收缩为止。

嵌套的for循环(您可以相信嵌套的for循环实际上是这里最短的吗?)遍历每个子弹的速度,并用于numpy.roots计算计算子弹与随后的每个子弹碰撞的时间。在这里,""被用来表示无穷大(无交集)。必须包含一个附加条件,以确保已停止的子弹在出现的那一刻而不是在零时被标记为发生碰撞。

对于每个数字,我们都会跟踪它将最快击中哪一颗子弹(如果有的话),然后o以所涉及子弹的最小碰撞时间进行更新。

在此双循环终止后,我们将遍历输入列表并删除所有在所有碰撞时间(如果有的话)中最少发生碰撞的项目符号。如果子弹碰巧同时发生碰撞,这使我们可以同时删除大量子弹。

然后,我们对其余的子弹重复整个过程,因为它们现在可能已经被碰撞到的子弹销毁了。

一旦没有项目符号被删除(列表未缩小),我们就退出while循环并打印剩余列表的长度。因此,该程序不仅可以在子弹幸存时打印出真相,而且还可以实际打印出幸存的子弹数量。

编辑:特别感谢feersum生成测试用例以帮助我发现错误。

编辑2:通过手动求解线性方程式而不是使用numpy,并将开始时间分成一个单独的列表并重组条件,从而节省了42个字节。

编辑3:通过重命名范围保存了4个字节

编辑4:通过使用制表符替换双倍空格,又节省了6个字节。另外,feersum还很友好,可以使用分数和集合进行比较。我打了一下高尔夫球,结果达到331个字节,这与我的解决方案联系在一起。

编辑5:通过删除不必要的初始化并重写条件语句来节省5个字节


您是否没有再次测试示例输入?[1、0、0、3]不起作用。
feersum

@feersum,我唯一没有测试过的,dangit。但固定的。尽一切努力,我会更好地支持您。:P
quintopia 2015年

仍然不起作用。[
1、16、18、20、30

好吧,至少在大多数情况下,它现在似乎可以正常工作。
feersum
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.