Un buen momento para rechazar

16

La puesta en marcha

Suponga que tiene n fusibles, con 1 ≤ n ≤ 5, cada uno de los cuales tiene un metro de largo, y donde cada fusible tiene una velocidad de combustión asociada de N metros por D horas.

Se puede encender un fusible en uno o ambos extremos, luego apagarlo en uno o ambos extremos, volver a encenderlo, volver a apagarlo, etc., tantas veces como sea necesario hasta que el fusible se haya consumido por completo. Puede encender y apagar los fusibles instantáneamente, y puede observar el instante exacto en que un fusible se consume por completo (se quema).

Un fusible no se puede cortar ni se puede encender en ninguna parte, excepto en sus extremos.

Tal configuración permite un sistema de sincronización infinitamente preciso, midiendo el tiempo entre dos eventos de iluminación / consumo de fusibles. Por ejemplo, con dos fusibles con una velocidad de combustión de 1 metro por hora, puede medir exactamente 45 minutos (3/4 horas) por

  1. simultáneamente: encender el primer fusible en ambos extremos, encender el segundo fusible en un extremo y marcar el inicio de su intervalo de tiempo
  2. encender el segundo extremo del segundo fusible en el instante en que se consume el primer fusible (30 minutos después)
  3. marcando el final de su intervalo de tiempo en el instante en que se consume el segundo fusible (15 minutos después)

El reto

Dado un número fraccionario de horas t , y un conjunto de n fracciones que representan velocidades de combustión exactas de n fusibles, escriba un programa o función que genere / devuelva un valor verdadero si t horas se pueden medir con precisión mediante la quema sistemática de los fusibles, o un valor falso de lo contrario.

La entrada al programa puede ser cualquiera de los siguientes:

  • argumentos de la línea de comandos del formulario TN/TD N1/D1 N2/D2 N3/D3 ...
  • una cadena de la forma TN/TD N1/D1 N2/D2 N3/D3 ...leída stdino equivalente
  • una cadena del formulario TN/TD N1/D1 N2/D2 N3/D3 ...pasado como argumento de función
  • una serie de cadenas ["TN/TD", "N1/D1", "N2/D2", "N3/D3", ...]pasadas como argumento de función

En todos los casos t = TN/ TD, donde TN, TD∈ [1,10000].

Asimismo, en todos los casos: velocidad de combustión del fusible i = N i / D i = N<i>/ D<i>, donde N<i>, D<i>∈ [1,10] ∀ i .

Puede suponer que siempre habrá entre 1 y 5 fusibles (inclusive), y que todas las entradas son válidas y están dentro del rango. También puede suponer que todas las fracciones de entrada se dan en los términos más bajos.

No puede usar números de coma flotante con componentes fraccionales para este desafío. Es decir, si usa números de coma flotante en cualquier lugar de su aplicación, solo pueden tomar valores integrales con componente fraccional cero.

Puntuación

Este es un desafío de , por lo tanto, se otorgará la victoria al envío más breve en bytes.


Ejemplo de entradas / salidas

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)

¡Feliz fusión! :)

COTO
fuente
@ MartinBüttner Supongo que sería la restricción de número de coma flotante.
hmatt1
2
@ MartinBüttner Estoy de acuerdo en que no es una restricción en el código fuente. No creo que [fuente restringida] se ajuste a esta pregunta tal como está actualmente.
hmatt1
@chilemagic: Quería llamar la atención sobre el hecho de que la lógica de coma flotante no se podía usar, pero si el consenso es que no es un uso adecuado de la etiqueta, la eliminaré.
COTO
Los casos de prueba son demasiado grandes :)
feersum
55
Lol, estoy usando un algoritmo O ((n!) ^ 3) para jugar al golf.
fiesta del

Respuestas:

8

Pitón 2, 305

Esta es la versión de golf. Es prácticamente inutilizable para n> 3 , ya que la complejidad del tiempo (y el espacio) es como 3 n 2 ... en realidad eso puede ser demasiado bajo para el tiempo. De todos modos, la función acepta una lista de cadenas.

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

Una versión ligeramente optimizada puede terminar los casos de prueba en un par de minutos. Sin embargo, aún podría ser lento para un caso n = 5 imposible .

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
fuente
1
Agradable, 8 votos a favor para un código con errores: llamando a la función con el ejemplo en la descripción: print f ('3/4 1/1 1 / 1'.split ()) devuelve 0, aunque como dice la descripción, es solucionable .
Jakube
@Jakube Gracias por probar ... ¡es muy raro en este sitio! Ya está arreglado; Olvidé en un lugar dividir por el factor 1 o 2 dependiendo de cuántos extremos de la cuerda estén encendidos.
fiesta
3

Pitón 2, 331

Es un poco más largo que la versión de Feersum, pero es mucho más rápido. Todos los casos de prueba juntos toman alrededor de 3 segundos en mi computadora portátil. Sin embargo, una búsqueda completa de n = 5 lleva unos 10 minutos. Parte del código es similar a la versión de feersum, pero no copié ningún código deliberadamente.

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

Uso:

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

Explicación:

La expresión lambda g realiza un preprocesamiento de la entrada, como convertir cadenas en fracciones, separar el tiempo objetivo de las velocidades de grabación y calcular los tiempos de grabación (= 1 / tasa de grabación).

La función h divide todos los tiempos de grabación x en 3 conjuntos n, byw (n significa non_burning, b para one_end_burning y w para both_ends_burning). Se itera sobre todos esos arreglos (excepto el arreglo n = x, b = [], w = []), determina el fusible con la tasa de quemado más corta (ahorra tiempo en m) y llama recursivamente h con tiempos de quemado actualizados. En y guardo todos los tiempos posibles que alguien puede medir usando los fusibles. En la llamada recursiva, estos valores también se actualizan.

Tan pronto como encuentro el valor, termina todas las llamadas con True.

Jakube
fuente
44
Ustedes jóvenes programadores de Python están mimados con todas sus fracciones integradas y enteros grandes. Cuando era joven, todo lo que teníamos era 1"s" y 0"s", que teníamos que escribir uno a la vez en una consola sin monitor. A veces no teníamos 1s.
COTO