Prima di tutto, le persone che dicono che non si può risolvere questo problema con la forza bruta in meno di un minuto sono sbagliate. Un algoritmo di forza bruta per un problema di queste dimensioni verrà eseguito in pochi secondi.
In secondo luogo, il codice che hai postato ha diversi problemi, alcuni dei quali già menzionati.
- Si dovrebbe terminare il ciclo impostando
one
ad un valore diverso da 0
una volta a raggiungere il tuo obiettivo condizione (dove è attualmente print a
).
- Non si reinizializza mai l'elenco (
l = []
). Questo dovrebbe essere fatto ogni volta che si ricalcola a
e b
, proprio prima di inserire il ciclo for.
- La domanda chiede che il primo numero di triangolo abbia su cinquecento divisori. Le condizioni per la risoluzione dovrebbero essere
if len(l) > 500:
.
- Probabilmente non si desidera
print a
all'interno del ciclo for, ma attendere fino al termine del ciclo.
La cosa che sta realmente rallentare è che per ogni numero triangolo a
si sta controllando ogni valore fino a a/2
per vedere se si tratta di un divisore. È sufficiente verificare i valori fino alla radice quadrata di a
. In questo modo per ogni valore di x
, se x
è un divisore, è sufficiente aggiungere x
e a/x
all'elenco.
Ecco il codice con le modifiche che ho descritto sopra:
import math
def main():
l = []
one = 0
a = 1
b = 2
while one == 0:
a = a + b
b += 1
l = []
sqrt_a = int(math.sqrt(a))
for x in range(1, sqrt_a + 1):
if a % x == 0:
l.append(x)
if x < math.sqrt(a):
l.append(a // x)
if len(l) > 500:
# print(a)
one = 1
print(a, b, len(l))
if __name__ == '__main__':
main()
Vedrai che venga eseguito in circa 5 o 6 secondi, quindi ben al di sotto di un minuto con queste modifiche.
fonte
2012-08-05 22:21:32
Si prega di non pubblicare il codice dove "uno == 0" è true. Fa male guardare: | –
Ci si abitua :-) È un buon paragone come nessun altro. E in questo programma, è sempre vero ... –
'l = []' dovrebbe essere all'interno di 'while while loop altrimenti accumula il divisore per tutti i numeri triangolari non solo uno. – jfs