拒绝的好时机


16

设置

假设你给ñ保险丝,1≤ ñ ≤5,每一个都是一米长,其中每个保险丝具有的相关燃烧率ñ每米d小时。

保险丝可以在一端或两端点亮,然后在一端或两端熄灭,重新点亮,重新熄灭等,直到保险丝完全耗尽为止。您可以立即点亮和熄灭保险丝,并且可以观察到保险丝完全耗尽(烧毁)的确切时间。

保险丝不能切断,也不能在除其末端以外的任何地方点亮。

通过测量任意两个保险丝点亮/消耗事件之间的时间,这样的设置允许无限精确的计时系统。例如,给定两个保险丝,其每小时的燃烧速度为1米,则您可以精确地测量45分钟(3/4小时)

  1. 同时:在两端点亮第一个保险丝,在一端点亮第二个保险丝,并标记时间间隔的开始
  2. 消耗第一根保险丝的瞬间(30分钟后)点亮第二根保险丝的第二端
  3. 在消耗第二根保险丝的瞬间(15分钟后)标记时间间隔的结束

挑战

给定小时数t的分数,以及代表n个保险丝的确切烧毁率的n 分数的集合,编写一个程序或函数,如果可以通过系统性地熔断保险丝来精确地测量t小时,则输出或返回真实值。否则为假值。

程序的输入可以是以下任意一项:

  • 形式的命令行参数 TN/TD N1/D1 N2/D2 N3/D3 ...
  • TN/TD N1/D1 N2/D2 N3/D3 ...读取stdin或等效形式的字符串
  • TN/TD N1/D1 N2/D2 N3/D3 ...作为函数参数传递的形式的字符串
  • ["TN/TD", "N1/D1", "N2/D2", "N3/D3", ...]作为函数参数传递的字符串数组

在所有情况下,t = TN/ TD,其中TNTD∈[1,10000]。

同样地,在所有的情况下:燃烧速率为熔丝 = Ñ / d = N<i>/ D<i>,其中N<i>D<i>∈[1,10]∀

您可能会假设总是有1至5根保险丝(含),并且所有输入均有效且在范围内。您还可以假定所有输入分数均以最低的术语给出。

您可能无法将浮点数与小数部分一起使用来解决此挑战。也就是说,如果您在应用程序中的任何地方使用浮点数,则它们只能采用零值部分的整数值。

计分

这是一个挑战,因此以字节为单位的最短合规提交将获胜。


输入/输出示例

input:  29/6 3/2 2/3 3/5 3/7 7/5
output: true

One solution:
  - light both ends of fuse 1, mark start of interval
  - on fuse 1 consumption: light both ends of fuse 2, light one end of fuse 5
  - on fuse 5 consumption: extinguish one end of fuse 2, light both ends of fuse 3,
    light both ends of fuse 4
  - on fuse 2 consumption: extinguish one end of fuse 3, extinguish both ends of
    fuse 4
  - on fuse 3 consumption: relight one end of fuse 4
  - on consumption of fuse 4: mark end of interval (29/6 hours)

input:  2/1 3/1 5/1 7/1
output: false

input:  5/1 6/1 1/6 9/1 1/9
output: true

One solution:
  - light fuse 1 at one end, light fuse 2 at both ends, light fuse 4 at both ends
  - on fuse 1 consumption: extinguish one end of fuse 2, mark start of interval
  - on fuse 4 consumption: relight one end of fuse 2
  - on fuse 2 consumption: mark end of interval (5 hours)

融合愉快!:)


@MartinBüttner我想这将是浮点数限制。
hmatt1 2014年

2
@MartinBüttner我同意这不是对源代码的限制。我不认为[受限来源]符合目前的问题。
hmatt1 2014年

@chilemagic:我想提请注意不能使用浮点逻辑的事实,但是如果一致认为这不是对标签的正确使用,我将剥离它。
COTO 2014年

测试用例太大:)
feersum 2014年

5
大声笑,我正在使用O((n!)^ 3)算法进行高尔夫运动。
feersum 2014年

Answers:


8

python 2,305

这是高尔夫版本。n> 3实际上是不可用的,因为时间(和空间)的复杂度大约是3 n 2 ...实际上对于时间而言可能太低了。无论如何,该函数接受字符串列表。

def f(i):
 Z=range;r=map(__import__('fractions').Fraction,i);R=r[1:];n=len(R);L=[[[1]*n,[0]]];g=0
 for m,p in L: 
  for d in([v/3**i%3for i in Z(n)]for v in Z(3**n)):
    try:x=min(m[i]/R[i]/d[i]for i in Z(n)if m[i]*d[i]>0);L+=[[[m[i]-x*R[i]*d[i]for i in Z(n)],[p[0]+x]+p]]
    except:g|=p[0]-r[0]in p
 return g

稍微优化的版本可以在几分钟内完成测试用例。但是对于不可能的n = 5情况,它可能仍然很慢。

def fLessslow(i):
 Z=range
 r=map(__import__('fractions').Fraction,i)
 R=r[1:]
 n=len(R)
 L=[((1,)*n,(0,))]
 ls = set(L)
 for m,p in L: 
  if p[0]-r[0]in p: return 1
  for d in([v/3**i%3 for i in Z(n)]for v in Z(3**n)):
   if any(d[i] and m[i]<=0 for i in Z(n)):continue
   try:
    x=min(m[i]/R[i]/d[i]for i in Z(n)if m[i]*d[i]>0)
    thing = (tuple(m[i]-x*R[i]*d[i]for i in Z(n)),(p[0]+x,)+p)
    if thing not in ls:L+=[thing];ls.add(thing)
   except:5
 return 0

print fLessslow('5/1 6/1 1/6 9/1 1/9'.split())
print fLessslow('29/6 3/2 2/3 3/5 3/7 7/5'.split())

1
不错,有8个错误代码代表错误:使用说明中的示例调用该函数:print f('3/4 1/1 1 / 1'.split())返回0,尽管如说明所述,它是可解决的。
雅库布2014年

@Jakube感谢您的测试...在此网站上非常罕见!现在已修复;我忘了在一个地方根据绳子的多少端除以1或2的因数。
feersum 2014年

3

Python 2,331

它比feersum的版本长一点,但速度更快。在我的笔记本电脑上,所有测试用例合计大约需要3秒钟。但是,完整搜索n = 5大约需要10分钟。有些代码类似于feersum的版本,但是我没有故意复制任何代码。

from fractions import*
f=Fraction
r=range
g=lambda x:h(f(x[0]),[1/f(i)for i in x[1:]],[])
def h(t,x,y):
 for i in r(1,3**len(x)):
  c=[[],[],[]]
  for j in r(len(x)):c[i/3**j%3]+=[x[j]]
  n,b,w=c
  m=min(b+[i/2 for i in w])
  if h(t,[i for i in n+[j-m for j in b]+[j-2*m for j in w]if i],[i+m for i in y]+[m]):return True
 return t in y

用法:

print g('3/4 1/1 1/1'.split())
print g('29/6 3/2 2/3 3/5 3/7 7/5'.split())
print g('2/1 3/1 5/1 7/1'.split())
print g('5/1 6/1 1/6 9/1 1/9'.split())

说明:

lambda表达式g对输入进行一些预处理,例如将字符串转换为分数,将目标时间与燃烧速率分开并计算燃烧时间(= 1 /燃烧速率)。

函数h将所有刻录时间x分为3组n,b和w(n代表non_burning,b代表one_end_burning,w代表both_ends_burning)。迭代所有这些布置(布置n = x,b = [],w = []除外),确定熔断率最短的熔丝(保存时间以m为单位),并以更新的燃烧时间递归调用h。在y中,我保存了所有可能使用保险丝进行测量的时间。在递归调用中,这些值也会被更新。

一旦找到该值,它将以True终止alle调用。


4
年轻的Python程序员对所有内置分数和大整数都情有独钟。早在我年轻的时候,我们所拥有的只是1一个和0一个,我们不得不一次在没有监视器的控制台上一次键入。有时我们没有1
COTO 2014年
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.