Pure Evil: Eval
a=lambda x,y:(y<0)*x or eval("a("*9**9**9+"x**.1"+",y-1)"*9**9**9)
print a(input(),9**9**9**9**9)//1
L'affermazione all'interno di eval crea una stringa di lunghezza 7 * 10 10 10 10 10 10 8.57 che consiste in nient'altro che più chiamate alla funzione lambda ciascuna delle quali costruirà una stringa di lunghezza simile , avanti e y
indietro fino a diventare 0. Apparentemente questo ha la stessa complessità del metodo Eschew di seguito, ma piuttosto che basarsi sulla logica if-and-o control, rompe semplicemente stringhe giganti (e il risultato netto sta ottenendo più stack ... probabilmente?).
Il y
valore più grande che posso fornire e calcolare senza che Python generi un errore è 2, che è già sufficiente per ridurre un input di max-float nel ritorno 1.
Una stringa di lunghezza 7.625.597.484.987 è semplicemente troppo grande: OverflowError: cannot fit 'long' into an index-sized integer
.
Dovrei smettere.
Eschew Math.log
: andando alla (decima) radice (del problema), Punteggio: funzione effettivamente indistinguibile da y = 1.
L'importazione della libreria matematica sta limitando il conteggio dei byte. Eliminiamo ciò e sostituiamo la log(x)
funzione con qualcosa di approssimativamente equivalente: x**.1
e che costa approssimativamente lo stesso numero di caratteri, ma non richiede l'importazione. Entrambe le funzioni hanno un output sublineare rispetto all'input, ma x 0,1 cresce ancora più lentamente . Tuttavia, non ci interessa molto, ci importa solo che abbia lo stesso modello di crescita di base rispetto ai grandi numeri mentre consuma un numero comparabile di caratteri (ad es. x**.9
È lo stesso numero di caratteri, ma cresce più rapidamente, quindi lì è un valore che mostrerebbe la stessa identica crescita).
Ora, cosa fare con 16 personaggi. Che ne dici di ... estendere la nostra funzione lambda per avere le proprietà della sequenza di Ackermann? Questa risposta per grandi numeri ha ispirato questa soluzione.
a=lambda x,y,z:(z<0)*x or y and a(x**.1,z**z,z-1)or a(x**.1,y-1,z)
print a(input(),9,9**9**9**99)//1
La z**z
parte qui mi impedisce di eseguire questa funzione con qualsiasi input vicino agli input sani per y
e z
, i valori più grandi che posso usare sono 9 e 3 per i quali ottengo il valore di 1.0, anche per il float più grande supportato da Python (nota: mentre 1.0 è numericamente maggiore di 6.77538853089e-05, un aumento dei livelli di ricorsione sposta l'output di questa funzione più vicino a 1, rimanendo maggiore di 1, mentre la funzione precedente ha spostato i valori più vicino a 0 rimanendo maggiore di 0, quindi anche una moderata ricorsione su questa funzione provoca così tante operazioni che il numero in virgola mobile perde tutti i bit significativi).
Riconfigurazione della chiamata lambda originale per avere valori di ricorsione di 0 e 2 ...
>>>1.7976931348623157e+308
1.0000000071
Se il confronto viene effettuato su "offset da 0" anziché su "offset da 1" questa funzione ritorna 7.1e-9
, che è decisamente inferiore a 6.7e-05
.
La ricorsione di base del programma effettivo (valore z) è di 10 10 10 10 1,97 livelli in profondità, non appena si esaurisce, viene ripristinata con 10 10 10 10 10 1,97 (motivo per cui è sufficiente un valore iniziale di 9), quindi io don so anche come calcolare correttamente il numero totale di ricorsioni che si verificano: ho raggiunto la fine delle mie conoscenze matematiche. Allo stesso modo non so se spostare una delle **n
esponenziazioni dall'input iniziale al secondario z**z
migliorerebbe o meno il numero di ricorsioni (idem inverso).
Andiamo ancora più lentamente con ancora più ricorsione
import math
a=lambda x,y:(y<0)*x or a(a(a(math.log(x+1),y-1),y-1),y-1)
print a(input(),9**9**9e9)//1
n//1
- salva 2 byte oltre int(n)
import math
, math.
salva 1 byte sufrom math import*
a(...)
salva 8 byte in totale m(m,...)
(y>0)*x
salva un byte sopray>0and x
9**9**99
aumenta il conteggio dei byte di 4 e aumenta la profondità di ricorsione di circa 2.8 * 10^x
dove si x
trova la vecchia profondità (o una profondità vicina a un googolplex in dimensioni: 10 10 94 ).
9**9**9e9
aumenta il numero di byte di 5 e aumenta la profondità di ricorsione di ... una quantità folle. La profondità di ricorsione è ora 10 10 10 9,93 , per riferimento, un googolplex è 10 10 10 2 .
- dichiarazione lambda aumenta ricorsione da un ulteriore passaggio:
m(m(...))
a a(a(a(...)))
costi 7 byte
Nuovo valore di output (a 9 profondità di ricorsione):
>>>1.7976931348623157e+308
6.77538853089e-05
La profondità di ricorsione è esplosa al punto in cui questo risultato è letteralmente insignificante tranne che in confronto ai risultati precedenti utilizzando gli stessi valori di input:
- L'originale ha chiamato
log
25 volte
- Il primo miglioramento lo chiama 81 volte
- Il programma attuale lo chiamerebbe 1e99 2 o circa 10 10 2.3 volte
- Questa versione lo chiama 729 volte
- Il programma attuale lo chiamerebbe (9 9 99 ) 3 o leggermente meno di 10 10 95 volte).
Lambda Inception, punteggio: ???
Ti ho sentito come i lambda, quindi ...
from math import*
a=lambda m,x,y:y<0and x or m(m,m(m,log(x+1),y-1),y-1)
print int(a(a,input(),1e99))
Non riesco nemmeno a eseguire questo, impilo il troppo pieno anche con soli 99 strati di ricorsione.
Il vecchio metodo (sotto) restituisce (saltando la conversione in un numero intero):
>>>1.7976931348623157e+308
0.0909072713593
Il nuovo metodo ritorna, usando solo 9 strati di incursione (anziché il googol completo di essi):
>>>1.7976931348623157e+308
0.00196323936205
Penso che questo abbia una complessità simile alla sequenza di Ackerman, solo piccola invece che grande.
Anche grazie a ETHproductions per un risparmio di 3 byte in spazi che non avevo realizzato potevano essere rimossi.
Vecchia risposta:
Il troncamento intero del registro delle funzioni (i + 1) ha ripetuto 20 volte 25 (Python) usando lambda lambda.
La risposta di PyRulez può essere compressa introducendo una seconda lambda e impilandola:
from math import *
x=lambda i:log(i+1)
y=lambda i:x(x(x(x(x(i)))))
print int(y(y(y(y(y(input()))))))
99 100 caratteri usati.
Questo produce un'iterazione di 20 25, rispetto al 12. originale Inoltre salva 2 caratteri utilizzando int()
invece di quello floor()
consentito per uno x()
stack aggiuntivo . Se gli spazi dopo il lambda possono essere rimossi (al momento non riesco a controllare), è y()
possibile aggiungere un quinto . Possibile!
Se c'è un modo per saltare l' from math
importazione usando un nome completo (es. x=lambda i: math.log(i+1))
), Ciò salverebbe ancora più caratteri e consentirebbe un altro stack di x()
ma non so se Python supporta tali cose (sospetto di no). Fatto!
Questo è essenzialmente lo stesso trucco usato nel post del blog di XCKD su grandi numeri , tuttavia l'overhead nel dichiarare lambdas preclude un terzo stack:
from math import *
x=lambda i:log(i+1)
y=lambda i:x(x(x(i)))
z=lambda i:y(y(y(i)))
print int(z(z(z(input()))))
Questa è la ricorsione più piccola possibile con 3 lambda che superano l'altezza dello stack calcolata di 2 lambda (riducendo qualsiasi lambda a due chiamate si riduce l'altezza dello stack a 18, inferiore a quella della versione 2-lambda), ma purtroppo richiede 110 caratteri.