Função Meia Exponencial


21

Uma função semi-exponencial é aquela que, quando composta consigo mesma, fornece uma função exponencial. Por exemplo, se f(f(x)) = 2^x, então fseria uma função semi-exponencial. Neste desafio, você calculará uma função semi-exponencial específica.

Especificamente, você calculará a função dos números inteiros não negativos para os números inteiros não negativos com as seguintes propriedades:

  • Aumento monotônico: se x < y, entãof(x) < f(y)

  • Pelo menos meio exponencial: para todos x,f(f(x)) >= 2^x

  • Lexicograficamente menor: Entre todas as funções com as propriedades acima, produza a que minimiza f(0), que, dada essa escolha f(1), minimiza , então f(2), e assim por diante.

Os valores iniciais desta função, para entradas 0, 1, 2, ...são:

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

Você pode gerar esta função por meio de qualquer um dos seguintes métodos, como uma função ou como um programa completo:

  • Tome xcomo entrada, saída f(x).

  • Tome xcomo entrada, produza os primeiros xvalores de f.

  • Infinitamente saída tudo f.

Se você deseja obter xe enviar f(x), xdeve ser zero indexado.

Implementação de referência

Este é o código golf - o código mais curto em bytes ganha. As brechas padrão são proibidas, como sempre.


parece definição não é verificado para 0: F (f (0)) = f (1) = 2, mas 2 ^ 0 = 1
Nahuel FOUILLEUL

e para 1: f (f (1)) = f (2) = 3 mas 2 ^ 1 = 2
Nahuel Fouilleul

1
@NahuelFouilleul o requisito é f (f (x)) > = 2 ^ x.
Martin Ender

1
Devemos enviar para o OEIS ?
Jeppe Stig Nielsen

Respostas:


8

JavaScript (ES7), 51 48 bytes

Guardado 3 bytes graças a @Arnauld

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

Recebe n e gera o n- ésimo item na sequência.


JavaScript (ES7), 70 68 64 bytes

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

Uma função recursiva que recebe xe retorna os primeiros xitens da sequência como uma matriz.

Como funciona

A matriz a é gerada proceduralmente, um item de cada vez, até atingir o comprimento desejado. (Uma porta da técnica infinita usada na excelente resposta Python do xnor provavelmente seria mais curta.)

Podemos fazer a seguinte observação para cada índice i (indexado 0):

  • Se i existe como um item em a no índice j ( a [j] = i ), então a [i] precisa ter pelo menos 2 j .

Isto é verdade porque f (f (j)) tem de ser pelo menos 2 j , e F (f (j)) é equivalente a um [a [j]] , que por sua vez é equivalente a uma [i] .

Normalmente, a opção correta é exatamente 2 j . No entanto, para o caso singular i = 2 , 2 existe na matriz no índice j = 1 , o que significa que 2 j seria 2 - mas isso significa que teríamos 2 tanto em [1] como em [2] . Para contornar este problema, tomamos o máximo de 2 j e uma [i-1] + 1 (um mais do que o item anterior), o que dá 3 para i = 2 .

Essa técnica também decide decidir se j existe ou não - se não existir, o .indexOf()método JS retornará -1 , o que levará a obter o máximo de [i-1] + 1 e 2 -1 = 0,5 . Como todos os itens na sequência são pelo menos 1 , isso sempre retornará o item anterior mais um.

(Estou escrevendo essa explicação tarde da noite, por favor, deixe-me saber se algo está confuso ou se perdi alguma coisa)


Observe que as entradas 272e acima fornecem respostas incorretas devido a problemas de estouro de número inteiro. Isso é bom, pois funciona até o limite do tipo de dados.
Isaacg

Use em 2**vez de, 1<<esperançosamente, corrigir o problema.
user202729

Agora o .99mata a solução. Mas por que usar +.99e não apenas +.9? Qual é a diferença?
User202729

@ user202729 Eu me sinto como um idiota - que foi deixado lá de uma versão anterior em que eu estava usando Math.log2(...)e tive que calcular o teto. Agora não é mais necessário. Obrigado! Vou dar uma olhada na 2**coisa - eu estava usando 2**...+.99|0originalmente, mas 1<<era mais curto porque não precisava do |0. Agora acho que não há diferença ...
ETHproductions




1

Gelatina , 14 bytes

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

Experimente online!

Como funciona

⁸Ç¡         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 bytes

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]

Experimente online!

Esta é uma modificação significativa da resposta do usuário202729 . Eu teria postado essa melhoria como um comentário, mas a resposta é excluída e, portanto, os comentários estão desabilitados.


Isso falha com uma exceção "índice de lista fora do intervalo" na entrada 258. Acho que o problema x**2é muito pequeno.
Isaacg

Bem ... Python 2 é diferente (muitas vezes menos bytes) do Python 3. #
user202729

1
Como esperado, a meia exponencial é muito maior que a quadrática. A solução obtém "índice da lista fora do intervalo" em x=1000. Você pode tentar 2**x- terrivelmente grande, mas o codegolf é um codegolf.
user202729

@ user202729 Ah, isso é verdade. Infelizmente, agora ele encontra um problema completamente diferente com entradas maiores, que 2**xcria um intervalo muito grande para o Python continuar.
precisa saber é o seguinte

0

Rápido , 137 bytes

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

Pega a entrada como Int(inteiro) e imprime como [Int](matriz inteira).

Versão 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)
}

Estou curioso, o que acontecerá se você remover o espaço antes da ??
ETHproductions

@ETHproductions Isso leva a um erro do compilador, já que números inteiros não podem ser encadeados opcionalmente .
Herman L
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.