Reddetmek İçin İyi Bir Zaman


16

Kurulum

Her biri bir metre uzunluğunda ve her sigortanın D saat başına N metre ile ilişkili yanma oranına sahip olduğu 1 ≤ n ≤ 5 ile n sigorta verildiğini varsayalım .

Bir sigorta bir veya her iki uçta yakılabilir, daha sonra bir veya her iki uçta söndürülebilir, yeniden doldurulabilir, yeniden söndürülebilir vb., Sigorta tamamen tüketilene kadar gerektiği kadar. Sigortaları anında yakabilir ve söndürebilirsiniz ve bir sigortanın tamamen tükendiğini (yandığını) tam olarak görebilirsiniz.

Bir sigorta olamaz kesilmiş olması, ne de onun uçları hariç herhangi bir yere yakılabilir.

Böyle bir kurulum, herhangi iki sigorta aydınlatma / tüketim olayı arasındaki süreyi ölçerek son derece hassas bir zamanlama sistemine izin verir. Örneğin, saatte 1 metre yanma oranına sahip iki sigorta verildiğinde, tam olarak 45 dakika (3/4 saat) ölçebilirsiniz.

  1. eşzamanlı olarak: ilk sigortayı her iki uçtan yakmak, ikinci sigortayı bir uçtan yakmak ve zaman aralığınızın başlangıcını işaretlemek
  2. ilk sigortanın tüketildiği anda ikinci sigortanın ikinci ucunun aydınlatılması (30 dakika sonra)
  3. ikinci sigortanın tükendiği anda zaman aralığınızın sonunu işaretlemek (15 dakika sonra)

Meydan okuma

Kesirli sayıda saat t ve n sigortanın tam yanma oranlarını temsil eden bir n kesir kümesi verildiğinde, eğer t saat, sigortaların sistematik yanmasıyla tam olarak ölçülebiliyorsa, doğru bir değer veren / döndüren bir program veya işlev yazın veya yanlış değeri.

Programa giriş aşağıdakilerden herhangi biri olabilir:

  • formun komut satırı bağımsız değişkenleri TN/TD N1/D1 N2/D2 N3/D3 ...
  • TN/TD N1/D1 N2/D2 N3/D3 ...okunan stdinveya eşdeğer bir form dizesi
  • TN/TD N1/D1 N2/D2 N3/D3 ...işlev bağımsız değişkeni olarak iletilen formun bir dizesi
  • ["TN/TD", "N1/D1", "N2/D2", "N3/D3", ...]işlev bağımsız değişkeni olarak iletilen dizeler dizisi

Her durumda t = TN/ TD, burada TN, TD∈ [1.10000].

Benzer şekilde, her durumda: sigorta i = N i / D i = N<i>/ için yanma oranı D<i>, burada N<i>, D<i>∈ [1,10] ∀ i .

Her zaman 1 ila 5 sigorta (dahil) olacağını ve tüm girişlerin geçerli ve aralıkta olduğunu varsayabilirsiniz. Ayrıca, tüm girdi kesirlerinin en düşük terimlerle verildiğini varsayabilirsiniz.

Bu meydan okuma için kayan nokta sayılarını kesirli bileşenlerle kullanamazsınız. Yani, uygulamanızın herhangi bir yerinde kayan nokta sayıları kullanırsanız, yalnızca sıfır kesirli bileşenle integral değerleri alabilirler.

puanlama

Bu bir meydan okumasıdır, bu nedenle baytlara en kısa uyumlu gönderim kazanılır.


Örnek Girişler / Çıkışlar

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)

Mutlu kaynaştırma! :)


@ MartinBüttner Kayan nokta sayısı kısıtlaması olacağını tahmin ediyorum.
hmatt1

2
@ MartinBüttner Kaynak kodunda bir kısıtlama olmadığını kabul ediyorum. [Kısıtlı kaynak] şu anda olduğu gibi bu soruya uyuyor sanmıyorum.
hmatt1

@chilemagic: Kayan nokta mantığının kullanılamayacağına dikkat çekmek istedim, ancak fikir birliği etiketin uygun bir şekilde kullanılması değilse, onu keserim.
FOTOĞRAF


5
Lol, golf amaçlı bir O ((n!) ^ 3) algoritması kullanıyorum.
feersum

Yanıtlar:


8

Python 2, 305

Bu golf versiyonudur. Zaman (ve uzay) karmaşıklığı 3 n 2 gibi olduğu için n> 3 için pratik olarak kullanılamaz ... aslında bu zaman için çok düşük olabilir. Her neyse, işlev dizelerin bir listesini kabul eder.

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

Biraz optimize edilmiş bir sürüm test senaryolarını birkaç dakika içinde bitirebilir. Yine de imkansız bir n = 5 vakası için hala yavaş olabilir .

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
Güzel, 8 buggy kodu için upvotes: açıklamasındaki örnekle işlevi çağırmak: print f ('3/4 1/1 1/1'.split ()) 0 döndürür, ancak açıklamanın söylediği gibi çözülebilir .
Jakube

@ Jakube Test ettiğiniz için teşekkürler ... bu sitede çok nadirdir! Şimdi düzeltildi; Bir yerde, ipin kaç ucunun yandığına bağlı olarak 1 veya 2 faktörüne bölmeyi unuttum.
feersum

3

Python 2, 331

Feersum'un versiyonundan biraz daha uzun, ama çok daha hızlı. Tüm test kılıfları birlikte dizüstü bilgisayarımda yaklaşık 3 saniye sürüyor. N = 5 için tam bir arama 10 dakika sürer. Kodun bazıları feersum'un sürümüne benzer, ancak kasıtlı olarak herhangi bir kodu kopyalamamıştım.

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

Kullanımı:

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

Açıklama:

Lambda ifadesi g, dizelerin kesirlere dönüştürülmesi, hedef süresinin yanma oranlarından ayrılması ve yanma sürelerinin hesaplanması (= 1 / yanma hızı) gibi girdinin bir miktar önişlemini yapar.

H fonksiyonu x tüm yanma sürelerini x 3 küme n, b ve w'ye böler (yanmayan yanma için n, one_end_burning için b ve her ikisi de yanma için w). Tüm bu düzenlemeleri tekrarlar (n = x, b = [], w = [] düzenlemesi hariç), en kısa yanma oranına sahip sigortayı belirler (m olarak zaman tasarrufu) ve güncellenmiş yanma süreleriyle h'yi tekrarlı olarak çağırır. Birinde sigortaları kullanarak ölçebileceğim tüm zamanları kaydederim. Özyinelemeli çağrıda bu değerler de güncellenir.

Değeri bulur bulmaz, True ile yapılan tüm çağrıları sonlandırır.


4
Genç Python programcıları, tüm yerleşik kesirleriniz ve büyük tamsayılarınızla şımarıksınız. Bir young'un iken Geri, elimizde olan oldu 1'ın ve 0bir monitör olmadan konsolda az bir-at-a-time yazmak için vardı' ler. Bazen 1s yoktu .
COTO
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.