Un bon moment pour refuser

16

La mise en place

Supposons que l'on vous donne n fusibles, avec 1 ≤ n ≤ 5, dont chacun mesure un mètre de long, et où chaque fusible a un taux de combustion associé de N mètres par D heures.

Un fusible peut être allumé à l'une ou aux deux extrémités, puis éteint à l'une ou aux deux extrémités, rallumé, éteint, etc., autant de fois que nécessaire jusqu'à ce que le fusible soit complètement épuisé. Vous pouvez allumer et éteindre les fusibles instantanément, et vous pouvez observer l'instant exact où un fusible est complètement consommé (brûlé).

Un fusible ne peut pas être coupé ni allumé ailleurs qu'à ses extrémités.

Une telle configuration permet un système de chronométrage infiniment précis, en mesurant le temps entre deux événements d'éclairage / consommation de fusible. Par exemple, étant donné deux fusibles avec un taux de combustion de 1 mètre par heure, vous pouvez mesurer exactement 45 minutes (3/4 heures) en

  1. simultanément: allumer le premier fusible aux deux extrémités, allumer le deuxième fusible à une extrémité et marquer le début de votre intervalle de temps
  2. allumer la deuxième extrémité du deuxième fusible au moment où le premier fusible est consommé (30 minutes plus tard)
  3. marquant la fin de votre intervalle de temps à l'instant où le deuxième fusible est consommé (15 minutes plus tard)

Le défi

Étant donné un nombre fractionnaire d'heures t et un ensemble de n fractions représentant les taux de combustion exacts de n fusibles, écrivez un programme ou une fonction qui génère / renvoie une valeur vraie si t heures peuvent être mesurées avec précision par la combustion systématique des fusibles, ou un valeur fausse sinon.

L'entrée dans le programme peut être l'une des suivantes:

  • arguments de ligne de commande du formulaire TN/TD N1/D1 N2/D2 N3/D3 ...
  • une chaîne du formulaire TN/TD N1/D1 N2/D2 N3/D3 ...lu stdinou équivalent
  • une chaîne du formulaire TN/TD N1/D1 N2/D2 N3/D3 ...passée en argument de fonction
  • un tableau de chaînes ["TN/TD", "N1/D1", "N2/D2", "N3/D3", ...]passées en argument de fonction

Dans tous les cas t = TN/ TD, où TN, TD∈ [1,10000].

De même, dans tous les cas: taux de combustion pour le fusible i = N i / D i = N<i>/ D<i>, où N<i>, D<i>∈ [1,10] ∀ i .

Vous pouvez supposer qu'il y aura toujours entre 1 et 5 fusibles (inclus) et que toutes les entrées sont valides et à portée. Vous pouvez également supposer que toutes les fractions d'entrée sont données en termes les plus bas.

Vous ne pouvez pas utiliser de nombres à virgule flottante avec des composants fractionnaires pour ce défi. Autrement dit, si vous utilisez des nombres à virgule flottante n'importe où dans votre application, ils ne peuvent prendre que des valeurs intégrales avec un composant fractionnel nul.

Notation

Il s'agit d'un défi de , donc la soumission conforme la plus courte en octets sera récompensée.


Exemples d'entrées / sorties

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)

Bonne fusion! :)

COTO
la source
@ MartinBüttner Je suppose que ce serait la restriction du nombre à virgule flottante.
hmatt1
2
@ MartinBüttner Je suis d'accord que ce n'est pas une restriction sur le code source. Je ne pense pas que [source-restreinte] corresponde à cette question telle qu'elle est actuellement.
hmatt1
@chilemagic: Je voulais attirer l'attention sur le fait que la logique à virgule flottante ne pouvait pas être utilisée, mais si le consensus est que ce n'est pas une bonne utilisation de la balise, je vais la supprimer.
COTO
Les cas de test sont trop gros :)
feersum
5
Lol, j'utilise un algorithme O ((n!) ^ 3) à des fins de golf.
feersum

Réponses:

8

Python 2, 305

Ceci est la version golfée. Il est pratiquement inutilisable pour n> 3 , car la complexité temporelle (et spatiale) est comme 3 n 2 ... en fait, cela peut être beaucoup trop faible pour le moment. Quoi qu'il en soit, la fonction accepte une liste de chaînes.

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

Une version légèrement optimisée peut terminer les cas de test en quelques minutes. Cela peut cependant être lent pour un cas n = 5 impossible .

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())
feersum
la source
1
Nice, 8 votes positifs pour un code buggé: appeler la fonction avec l'exemple dans la description: print f ('3/4 1/1 1 / 1'.split ()) renvoie 0, bien que comme le dit la description, il soit résoluble .
Jakube
@Jakube Merci pour les tests ... c'est très rare sur ce site! C'est corrigé maintenant; J'ai oublié au même endroit de diviser par le facteur 1 ou 2 selon le nombre d'extrémités de la corde allumées.
feersum
3

Python 2, 331

C'est un peu plus long que la version de feersum, mais c'est beaucoup plus rapide. Tous les tests prennent ensemble environ 3 secondes sur mon ordinateur portable. Une recherche complète pour n = 5 prend cependant 10 minutes. Une partie du code est similaire à la version de feersum, mais je n'ai délibérément copié aucun code.

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

Usage:

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

Explication:

L'expression lambda g effectue un prétraitement de l'entrée, comme la conversion de chaînes en fractions, la séparation du temps cible des taux de gravure et le calcul des temps de gravure (= 1 / taux de gravure).

La fonction h divise tous les temps de gravure x en 3 ensembles n, b et w (n signifie non_burning, b pour one_end_burning et w pour both_ends_burning). Il itère sur tous ces arrangements (sauf l'arrangement n = x, b = [], w = []), détermine le fusible avec le taux de combustion le plus court (gagner du temps en m) et appelle récursivement h avec des temps de gravure mis à jour. En y, j'économise toutes les fois que quelqu'un peut mesurer à l'aide des fusibles. Dans l'appel récursif, ces valeurs sont également mises à jour.

Dès que je trouve la valeur, elle termine tous les appels avec True.

Jakube
la source
4
Vous, les jeunes programmeurs Python, vous avez l'embarras de toutes vos fractions intégrées et de vos grands nombres entiers. Quand j'étais young'un, tout ce que nous avions était 1« s et 0d », que nous avons dû taper un à-un-temps à une console sans un moniteur. Parfois, nous n'avions pas l' 1art.
COTO