拒否する良い時期


16

セットアップ

あなたが与えられていると仮定し、N 1と、ヒューズ≤ N ≤5、長いメートルでそれぞれが、そしてここで、各ヒューズの関連する燃焼速度有するN個当たりのメートルDの時間。

ヒューズは、片端または両端で点灯し、その後片端または両端で消灯、再点灯、再消灯などを、ヒューズが完全に消費されるまで何度でも行うことができます。ヒューズを瞬時に点灯および消灯することができ、ヒューズが完全に消費された(燃えた)瞬間を正確に観察できます。

ヒューズ切断できず、端以外は点灯できません

このような設定により、2つのヒューズ点灯/消費イベント間の時間を測定することにより、無限に正確なタイミングシステムが可能になります。たとえば、1時間あたり1メートルの燃焼速度を持つ2つのヒューズがある場合、次の方法で正確に45分(3/4時間)を測定できます。

  1. 同時に:最初のヒューズを両端で点灯し、2番目のヒューズを一端で点灯し、時間間隔の開始をマークします
  2. 最初のヒューズが消費された瞬間(30分後)に2番目のヒューズの2番目の端を点灯
  3. 2番目のヒューズが消費された瞬間(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]。

同様に、すべての場合において:ヒューズ用の燃焼速度は、iが = NをI / D I = N<i>/ D<i>、ここでN<i>D<i>∈[1,10]∀ I

常に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 14年

2
@MartinBüttner私はそれがソースコードの制限ではないことに同意します。[restricted-source]が現在の問題に当てはまるとは思わない。
hmatt1 14年

@chilemagic:浮動小数点ロジックを使用できないという事実に注意を喚起したかったのですが、タグの適切な使用ではないというコンセンサスがあれば、それを取り除きます。
COTO 14年

テストケースが大きすぎる:)
feersum 14年

5
Lol、私はゴルフの目的でO((n!)^ 3)アルゴリズムを使用しています。
feersum

回答:


8

Python 2、305

これはゴルフバージョンです。時間(およびスペース)の複雑さは3 n 2のようであるため、n> 3の場合は実際には使用できません。とにかく、関数は文字列のリストを受け入れます。

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を返しますが、説明にあるように解決可能です。
ジャクベ14年

@Jakubeテストありがとうございます...このサイトでは非常にまれです!現在修正されています。ロープの端の数に応じて、1か2で割るのを1か所で忘れていました。
feersum 14年

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

説明:

ラムダ式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で終了します。


4
あなたの若いPythonプログラマーは、すべての組み込み分数と大きな整数に甘やかされています。若い頃、私たちが持っていたのは1「と0」だけで、モニターのないコンソールで一度に1つずつ入力する必要がありました。時々がありませんでした1
COTO
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.