Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

411
Vistas
¿Cómo puedo generar tres enteros aleatorios que satisfagan alguna condición?

Soy un principiante en programación y estoy buscando una buena idea sobre cómo generar tres números enteros que satisfagan una condición.

Ejemplo:

Nos dan n = 30 y nos piden que generemos tres enteros a, b y c, de modo que 7*a + 5*b + 3*c = n . Traté de usar bucles for , pero lleva demasiado tiempo y tengo un tiempo máximo de prueba de 1000 ms.

Estoy usando Python 3.

Mi intento:

 x = int(input()) c = [] k = [] w = [] for i in range(x): for j in range(x): for h in range(x): if 7*i + 5*j + 3*h = x: c.append(i) k.append(j) w.append(h) if len(c) == len(k) == len(w) print(-1) else: print(str(k[0]) + ' ' + str(c[0]) + ' ' + str(w[0]))
over 4 years ago · Hanz Gallego
5 Respuestas
Responde la pregunta

0

import numpy as np def generate_answer(n: int, low_limit:int, high_limit: int): while True: a = np.random.randint(low_limit, high_limit + 1, 1)[0] b = np.random.randint(low_limit, high_limit + 1, 1)[0] c = (n - 7 * a - 5 * b) / 3.0 if int(c) == c and low_limit <= c <= high_limit: break return a, b, int(c) if __name__ == "__main__": n = 30 ans = generate_answer(low_limit=-5, high_limit=50, n=n) assert ans[0] * 7 + ans[1] * 5 + ans[2] * 3 == n print(ans)

Si selecciona dos de los números a, b, c, conoce el tercero. En este caso, aleatorizo enteros para a, b, y encuentro c por c = (n - 7 * a - 5 * b) / 3.0 .

Asegúrese de que c sea un número entero y esté dentro de los límites permitidos, y listo.

Si no es así, vuelve a aleatorizar.


Si quieres generar todas las posibilidades,

 def generate_all_answers(n: int, low_limit:int, high_limit: int): results = [] for a in range(low_limit, high_limit + 1): for b in range(low_limit, high_limit + 1): c = (n - 7 * a - 5 * b) / 3.0 if int(c) == c and low_limit <= c <= high_limit: results.append((a, b, int(c))) return results
over 4 years ago · Hanz Gallego Denunciar

0

Si se permiten bibliotecas de terceros, puede usar el solucionador de ecuaciones diophantine.diop_linear lineales diophantine.diop_linear de SymPy:

 from sympy.solvers.diophantine.diophantine import diop_linear from sympy import symbols from numpy.random import randint n = 30 N = 8 # Number of solutions needed # Unknowns a, b, c = symbols('a, b, c', integer=True) # Coefficients x, y, z = 7, 5, 3 # Parameters of parametric equation of solution t_0, t_1 = symbols('t_0, t_1', integer=True) solution = diop_linear(x * a + y * b + z * c - n) if not (None in solution): for s in range(N): # -10000 and 10000 (max and min for t_0 and t_1) t_sub = [(t_0, randint(-10000, 10000)), (t_1, randint(-10000, 10000))] a_val, b_val, c_val = map(lambda t : t.subs(t_sub), solution) print('Solution #%d' % (s + 1)) print('a =', a_val, ', b =', b_val, ', c =', c_val) else: print('no solutions')

Salida (aleatoria):

 Solution #1 a = -141 , b = -29187 , c = 48984 Solution #2 a = -8532 , b = -68757 , c = 134513 Solution #3 a = 5034 , b = 30729 , c = -62951 Solution #4 a = 7107 , b = 76638 , c = -144303 Solution #5 a = 4587 , b = 23721 , c = -50228 Solution #6 a = -9294 , b = -106269 , c = 198811 Solution #7 a = -1572 , b = -43224 , c = 75718 Solution #8 a = 4956 , b = 68097 , c = -125049
over 4 years ago · Hanz Gallego Denunciar

0

Por qué su solución no puede hacer frente a grandes valores de n

Puede comprender que todo en un bucle for con un rango de i , se ejecutará i veces. Entonces multiplicará el tiempo que toma por i .

Por ejemplo, supongamos (para mantener las cosas simples) que esto se ejecuta en 4 milisegundos:

 if 7*a + 5*b + 3*c = n: c.append(a) k.append(b) w.append(c)

entonces esto se ejecutará en 4 × n milisegundos:

 for c in range(n): if 7*a + 5*b + 3*c = n: c.append(a) k.append(b) w.append(c)

Aproximadamente:

  • n = 100 tardaría 0,4 segundos
  • n = 250 tomaría 1 segundo
  • n = 15000 tardaría 60 segundos

Si coloca eso dentro de un bucle for en un rango de n , todo se repetirá n veces. Es decir

 for b in range(n): for c in range(n): if 7*a + 5*b + 3*c = n: c.append(a) k.append(b) w.append(c)

tomará 4n² milisegundos.

  • n = 30 tardaría 4 segundos
  • n = 50 tardaría 10 segundos
  • n = 120 tardaría 60 segundos

Ponerlo en un tercer ciclo for tomará 4n³ milisegundos.

  • n = 10 tardaría 4 segundos
  • n = 14 tardaría 10 segundos.
  • n = 24 tardaría 60 segundos.

Ahora, ¿qué pasa si reduce a la mitad el original if a 2 milisegundos? n podría aumentar en 15000 en el primer caso... y 23 en el último caso. La lección aquí es que un menor número de bucles for suele ser mucho más importante que acelerar lo que hay dentro de ellos. Como puede ver en la respuesta de Gulzar, parte 2, solo hay dos bucles for, lo que marca una gran diferencia. (Esto solo se aplica si los bucles están uno dentro del otro; si están uno tras otro, no tienes el problema de la multiplicación).

over 4 years ago · Hanz Gallego Denunciar

0

Primero, permítanme señalar que su tarea está subespecificada en al menos dos aspectos:

  1. No se especifica el rango permitido de los valores generados. En particular, no especifica si los resultados pueden incluir números enteros negativos.
  2. No se especifica la distribución deseada de los valores generados.

Normalmente, si no se especifica, se podría suponer que se esperaba una distribución uniforme en el conjunto de posibles soluciones de la ecuación (ya que es, en cierto sentido , la distribución más aleatoria posible en un conjunto dado). Pero una distribución uniforme (discreta) solo es posible si el conjunto de soluciones es finito, lo que no será posible si el rango de resultados no está restringido. (En particular, si ( a , b , c ) es una solución, entonces también lo es ( a , b + 3 k , c − 5 k ) para cualquier entero k ). Entonces, si interpretamos la tarea como si pidiéramos una distribución uniforme con un rango ilimitado, ¡es realmente imposible!


Por otro lado, si se nos permite elegir cualquier distribución y rango, la tarea se vuelve trivial: simplemente hacer que el generador siempre devuelva a = − n , b = n , c = n . Claramente, esta es una solución a la ecuación (ya que −7 n + 5 n + 3 n = (−7 + 5 + 3) n = 1 n ), y una distribución degenerada que asigna toda la masa de probabilidad a un solo punto sigue siendo válida ¡Distribución de probabilidad!

Si quisiera una solución un poco menos degenerada, podría elegir un número entero aleatorio k (usando cualquier distribución de su elección) y devolver a = − n , b = n + 3 k , c = n − 5 k . Como se señaló anteriormente, esta también es una solución a la ecuación para cualquier k . Por supuesto, esta distribución es todavía algo degenerada, ya que el valor de a es fijo.

Si desea que todos los valores devueltos sean al menos algo aleatorios, también puede elegir una h aleatoria y devolver a = − n + h , b = n − 2 h + 3 k y c = n + h − 5 k . Nuevamente, se garantiza que esta es una solución válida para cualquier h y k , ya que claramente satisface la ecuación para h = k = 0, y también es fácil ver que aumentar o disminuir h o k dejará el valor de la izquierda -Lado de la mano de la ecuación sin cambios.

De hecho, se puede probar que este método puede generar todas las soluciones posibles a la ecuación, y que cada solución corresponderá a un único par ( h , k )! (Una forma bastante intuitiva de ver esto es graficar las soluciones en el espacio 3D y observar que forman una red regular de puntos en un plano 2D, y que los vectores (+1, −2, +1) y (0, + 3, −5) abarcan esta red.) Si elegimos h y k de alguna distribución que (al menos en teoría) asigna una probabilidad distinta de cero a cada número entero, entonces tendremos una probabilidad distinta de cero de devolver cualquier número válido solución. Entonces, al menos para una interpretación algo razonable de la tarea (rango ilimitado, cualquier distribución con soporte completo), el siguiente código debería resolver la tarea de manera eficiente :

 from random import gauss def random_solution(n): h = int(gauss(0, 1000)) # any distribution with full support on the integers will do k = int(gauss(0, 1000)) return (-n + h, n - 2*h + 3*k, n + h - 5*k)

Si se restringe el rango de valores posibles, el problema se vuelve un poco más complicado. En el lado positivo, si todos los valores están acotados por debajo (o por encima), entonces el conjunto de posibles soluciones es finito, por lo que existe una distribución uniforme en él. Por otro lado, muestrear eficientemente esta distribución uniforme no es trivial.

Un enfoque posible, que ha utilizado usted mismo, es generar primero todas las soluciones posibles (suponiendo que haya un número finito de ellas) y luego tomar muestras de la lista de soluciones. Podemos hacer la generación de soluciones de manera bastante eficiente de esta manera:

  1. encontrar todos los valores posibles de a para los cuales la ecuación podría tener una solución,
  2. para cada uno de tales a , encuentre todos los valores posibles de b para los cuales todavía hay una solución,
  3. para cada uno de estos pares ( a , b ), resuelva la ecuación para c y verifique si es válida (es decir, un número entero dentro del rango especificado), y
  4. en caso afirmativo, agregue ( a , b , c ) al conjunto de soluciones.

La parte complicada es el paso 2, donde queremos calcular el rango de posibles valores de b . Para esto, podemos hacer uso de la observación de que, para un a dado, establecer c en su valor más pequeño permitido y resolver la ecuación da un límite superior para b (y viceversa).

En particular, resolviendo la ecuación para a , b y c respectivamente, obtenemos:

  • un = ( norte - 5 segundo - 3 do ) / 7
  • segundo = ( norte - 7 un - 3 do ) / 5
  • do = ( norte - 7 un - 5 segundo ) / 3

Dados los límites inferiores de algunos de los valores, podemos usar estas soluciones para calcular los límites superiores correspondientes de los demás. Por ejemplo, el siguiente código generará todas las soluciones no negativas de manera eficiente (y se puede modificar fácilmente para usar un límite inferior distinto de 0, si es necesario):

 def all_nonnegative_solutions(n): a_min = b_min = c_min = 0 a_max = (n - 5*b_min - 3*c_min) // 7 for a in range(a_min, a_max + 1): b_max = (n - 7*a - 3*c_min) // 5 for b in range(b_min, b_max + 1): if (n - 7*a - 5*b) % 3 == 0: c = (n - 7*a - 5*b) // 3 yield (a, b, c)

Luego podemos almacenar las soluciones en una lista o una tupla y tomar muestras de esa lista :

 from random import choice solutions = tuple(all_nonnegative_solutions(30)) a, b, c = choice(solutions)

PD. Aparentemente, la random.choice de Python no es lo suficientemente inteligente como para usar el muestreo de reservorio para tomar muestras de un iterable arbitrario, por lo que necesitamos almacenar la lista completa de soluciones incluso si solo queremos tomar muestras una vez. O, por supuesto, siempre podríamos implementar nuestro propio sampler :

 def reservoir_choice(iterable): r = None n = 0 for x in iterable: n += 1 if randrange(n) == 0: r = x return r a, b, c = reservoir_choice(all_nonnegative_solutions(30))

Por cierto, podríamos hacer que la función all_nonnegative_solutions de arriba sea un poco más eficiente al observar que la condición (n - 7*a - 5*b) % 3 == 0 (que verifica si c = ( n − 7 a − 5 b ) / 3 es un número entero y, por lo tanto, una solución válida) es cierto para cada tercer valor de b . Por lo tanto, si primero calculamos el valor más pequeño de b que satisface la condición para un a dado (lo que se puede hacer con un poco de aritmética modular ), podríamos iterar sobre b con un tamaño de paso de 3 a partir de ese valor mínimo y omitir la comprobación de divisibilidad por completo. Dejaré la implementación de esa optimización como un ejercicio.

over 4 years ago · Hanz Gallego Denunciar

0

desde mi perspectiva, el último número de los tres nunca es un número aleatorio. digamos que primero genera a y b , luego c nunca es aleatorio porque debe calcularse a partir de la ecuación

 n = 7*a + 5*b + 3*c c = (7*a + 5*b - n) / -3

esto significa que necesitamos generar dos valores aleatorios (a,b) que 7*a + 5*b - n es divisible por 3

 import random n = 30; max = 1000000; min = -1000000; while True: a = random.randint(min , max); b = random.randint(min , max); t = (7*a) + (5*b) - n; if (t % 3 == 0) : break; c = (t/-3); print("A = " + str(a)); print("B = " + str(b)); print("C = " + str(c)); print("7A + 5B + 3C =>") print("(7 * " + str(a) + ") + (5 * " + str(b) + ") + (3 * " + str(c) + ") = ") print((7*a) + (5*b) + (3*c));

REEMPLAZAR

over 4 years ago · Hanz Gallego Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda