Funzione semi esponenziale


21

Una funzione semi-esponenziale è quella che, se composta con se stessa, dà una funzione esponenziale. Ad esempio, se f(f(x)) = 2^x, allora fsarebbe una funzione semi-esponenziale. In questa sfida, calcolerai una specifica funzione semi-esponenziale.

In particolare, calcolerai la funzione dagli interi non negativi agli interi non negativi con le seguenti proprietà:

  • Monotonicamente in aumento: se x < y, alloraf(x) < f(y)

  • Almeno mezzo esponenziale: per tutti x,f(f(x)) >= 2^x

  • Lessicograficamente più piccolo: tra tutte le funzioni con le proprietà di cui sopra, emette quella che minimizza f(0), che data quella scelta minimizza f(1), quindi f(2), e così via.

I valori iniziali di questa funzione, per gli ingressi 0, 1, 2, ...sono:

[1, 2, 3, 4, 8, 9, 10, 11, 16, 32, 64, 128, 129, 130, 131, 132, 256, 257, ...]

È possibile generare questa funzione tramite uno dei seguenti metodi, sia come funzione che come programma completo:

  • Prendi xcome input, output f(x).

  • Prendi xcome input, visualizza i primi xvalori di f.

  • Produce all'infinito tutto f.

Se si desidera acquisire xe produrre f(x), è xnecessario indicizzare zero.

Implementazione di riferimento

Questo è il codice golf - vince il codice più corto in byte. Le scappatoie standard sono vietate, come sempre.


sembra che la definizione non sia verificata per 0: f (f (0)) = f (1) = 2 ma 2 ^ 0 = 1
Nahuel Fouilleul,

e per 1: f (f (1)) = f (2) = 3 ma 2 ^ 1 = 2
Nahuel Fouilleul,

1
@NahuelFouilleul il requisito è f (f (x)) > = 2 ^ x.
Martin Ender,

1
Dovremmo presentare a OEIS ?
Jeppe Stig Nielsen,

Risposte:


8

JavaScript (ES7), 51 48 byte

Salvato 3 byte grazie a @Arnauld

f=i=>i?f[f[q=f(i-1),r=f[i]||q+1]=(i>1)<<i,i]=r:1

Prende in n ed emette il n 'esimo elemento della sequenza.


JavaScript (ES7), 70 68 64 byte

f=(n,a=[],q=1)=>n?f(n-1,a,(n=2**a.indexOf(a.push(q)))<++q?q:n):a

Una funzione ricorsiva che accetta xe restituisce i primi xelementi della sequenza come un array.

Come funziona

L'array a viene generato proceduralmente, un elemento alla volta, fino a raggiungere la lunghezza desiderata. (Una porta della tecnica infinita utilizzata nell'eccellente risposta Python di xnor sarebbe probabilmente più breve.)

Possiamo fare la seguente osservazione per ogni indice i (0-indicizzato):

  • Se i esiste come un elemento in una posizione di indice j ( un [j] = i ), poi a [i] deve essere di almeno 2 j .

Questo è vero perché f (f (j)) deve essere almeno 2 j , e f (f (j)) è equivalente a un [a [j]] , che a sua volta è equivalente a un [i] .

Normalmente l'opzione corretta è esattamente 2 j . Tuttavia, per il caso singolare i = 2 , 2 esiste nella matrice nell'indice j = 1 , il che significa che 2 j sarebbe 2, ma ciò significa che avremmo 2 sia in [1] che in [2] . Per ovviare a questo, prendiamo il massimo di 2 j e un [i-1] + 1 (uno in più rispetto all'elemento precedente), che dà 3 per i = 2 .

Questa tecnica si occupa anche di decidere se esiste o meno j , altrimenti il .indexOf()metodo di JS restituisce -1 , il che porta a prendere il massimo di un [i-1] + 1 e 2 -1 = 0,5 . Poiché tutti gli elementi nella sequenza sono almeno 1 , questo restituirà sempre l'elemento precedente più uno.

(Sto scrivendo questa spiegazione a tarda notte, quindi per favore fatemi sapere se qualcosa è confuso o ho perso qualcosa)


Si noti che input 272e up forniscono risposte errate a causa di problemi di overflow di numeri interi. Questo va bene, poiché funziona fino al limite del tipo di dati.
Isaacg,

Usa 2**invece di 1<<speriamo di risolvere il problema.
user202729

Ora .99uccide la soluzione. Ma perché usare +.99e non solo +.9? Qual è la differenza?
user202729

@ user202729 Mi sento un idiota - che era rimasto lì dentro da una versione precedente in cui stavo usando Math.log2(...)e dovevo calcolare il soffitto. Ora non è affatto necessario. Grazie! Esaminerò la 2**cosa: stavo usando 2**...+.99|0originariamente, ma 1<<era più breve perché non ne avevo bisogno |0. Ora penso che non ci sia differenza ...
ETHproductions




1

Gelatina , 14 byte

iL’2*»Ṁ‘$ṭ
⁸Ç¡

Provalo online!

Come funziona

⁸Ç¡         Main link. No arguments.

⁸           Set the left argument and the return value to [].
 Ç¡         Read an integer n from STDIN and call the helper link n times, first on
            [], then on the previous result. Return the last result.


iL’2*»Ṁ‘$ṭ  Helper link. Argument: A (array)

 L          Take the length of A. This is the 0-based index of the next element.
i           Find its 1-based index in A (0 if not present).
  ’         Decrement to a 0-based index (-1 if not present).
   2*       Elevate 2 to the 0-based index.
      Ṁ‘$   Take the maximum of A and increment it by 1.
            Note that Ṁ returns 0 for an empty list.
     »      Take the maximum of the results to both sides.
         ṭ  Tack (append) the result to A.

0

Python 2 , 111 byte

def f(x):
 a=range(1,2**x)
 for i in range(1,x):a[i]=max(a[i],a[i-1]+1);a[a[i]]=max(a[a[i]],2**i)
 return a[:x]

Provalo online!

Questa è una modifica significativa della risposta di user202729 . Avrei pubblicato questo miglioramento come commento, ma la risposta è stata eliminata e quindi i commenti sono disabilitati.


Ciò fallisce con un'eccezione "elenco indice fuori intervallo" sull'input 258. Penso che il problema x**2sia troppo piccolo.
Isaacg,

Bene ... Python 2 è diverso (spesso meno byte) da Python 3.
user202729

1
Come previsto, la metà esponenziale è molto più grande del quadratico. La soluzione ottiene "elenca indice fuori intervallo" in x=1000. Potresti provare 2**x- terribilmente grande, ma codegolf è codegolf.
user202729

@ user202729 Ah, questo è vero. Sfortunatamente ora incontra un problema completamente diverso con input più grandi in quanto 2**xcrea un intervallo troppo ampio perché Python possa continuare.
Notjagan,

0

Rapido , 137 byte

func f(n:Int){var l=Array(1...n).map{$0>3 ?0:$0},p=8;if n>3{for i in 3..<n{if l[i]<1{l[i]=l[i-1]+1};if l[i]<n{l[l[i]]=p};p*=2}};print(l)}

Prende l'input come Int(intero) e lo stampa come [Int](intero).

Versione Ungolfed

func f(n:Int){
    var l = Array(1...n).map{$0 > 3 ? 0 : $0} // Create the range from 1 to n and set all
    var p = 8                                 // values greater than 3 to 0
    if n > 3 {
        for i in 3 ..< n {
            if l[i] < 1 {
                l[i] = l[i - 1] + 1
            }
            if l[i] < n {
                l[l[i]] = p
            }
            p *= 2
        }
    }
    print(l)
}

Sono curioso, cosa succederà se si rimuove lo spazio prima del ??
ETHproductions

@ETHproductions Ciò porta a un errore del compilatore, poiché gli interi non possono essere concatenati facoltativi .
Herman L
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.