Полуэкспоненциальная функция

21

Половинной экспоненциальная функция является один , который , когда в составе с собой дает экспоненциальную функцию. Например, если f(f(x)) = 2^x, то fбудет полуэкспоненциальной функцией. В этом задании вы вычислите определенную половину экспоненциальной функции.

В частности, вы будете вычислять функцию от неотрицательных целых чисел до неотрицательных целых чисел со следующими свойствами:

  • Монотонно возрастающий: если x < y, тоf(x) < f(y)

  • По крайней мере, наполовину: для всех x,f(f(x)) >= 2^x

  • Лексикографически наименьший: среди всех функций с указанными выше свойствами выведите ту, которая минимизирует f(0), которая при этом выборе минимизирует f(1), затем f(2)и так далее.

Начальные значения этой функции для входов 0, 1, 2, ...:

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

Вы можете вывести эту функцию любым из следующих методов, либо в виде функции, либо в виде полной программы:

  • Принять xкак вход, выход f(x).

  • Взять в xкачестве входных данных, вывести первые xзначения f.

  • Бесконечно выводим все f.

Если вы хотите взять xи вывести f(x), xдолжен быть индексирован ноль.

Ссылочная реализация

Это код гольфа - выигрывает самый короткий код в байтах. Стандартные лазейки , как всегда, запрещены.

isaacg
источник
Кажется, определение не подтверждено для 0: f (f (0)) = f (1) = 2, но 2 ^ 0 = 1
Науэль Фуийе
и для 1: f (f (1)) = f (2) = 3, но 2 ^ 1 = 2
Науэль Фуийе
1
@NahuelFouilleul требование: f (f (x)) > = 2 ^ x.
Мартин Эндер
1
Должны ли мы подчиняться OEIS ?
Джепп Стиг Нильсен

Ответы:

8

JavaScript (ES7), 51 48 байт

Сохранено 3 байта благодаря @Arnauld

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

Принимает n и выводит n -й элемент в последовательности.


JavaScript (ES7), 70 68 64 байта

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

Рекурсивная функция, которая принимает xи возвращает первые xэлементы последовательности в виде массива.

Как это устроено

Массив a генерируется процедурно, по одному элементу за раз, пока не достигнет желаемой длины. (Порт бесконечной техники, используемой в превосходном ответе Python от xnor, вероятно, будет короче.)

Мы можем сделать следующее наблюдение для каждого индекса i (0-indexed):

  • Если я существую как элемент в под индексом J ( а [J] = I ), то а [я] должно быть по крайней мере 2 J .

Это верно, потому что f (f (j)) должно быть не менее 2 j , а f (f (j)) эквивалентно a [a [j]] , что, в свою очередь, эквивалентно a [i] .

Обычно правильный вариант - ровно 2 j . Однако для особого случая я = 2 , 2 существует в массиве под индексом J = 1 , что означает , что 2 J было бы 2 бут это означает , что мы имели бы 2 на обоих A [1] и в [2] . Чтобы обойти это, мы берем максимум 2 j и a [i-1] + 1 (на один больше, чем в предыдущем пункте), что дает 3 для i = 2 .

Этот метод также помогает решить, существует j или нет - если .indexOf()метод JS не существует, возвращается -1 , что приводит к максимальному значению [i-1] + 1 и 2 -1 = 0,5 . Поскольку все элементы в последовательности по крайней мере 1 , это всегда будет возвращать предыдущий элемент плюс один.

(Я пишу это объяснение поздно вечером, поэтому, пожалуйста, дайте мне знать, если что-то сбивает с толку, или я что-то пропустил)

ETHproductions
источник
Обратите внимание, что входные данные 272и up дают неправильные ответы из-за проблем переполнения целых чисел. Это нормально, так как работает до предела типа данных.
Исаак
Используйте 2**вместо того, чтобы, 1<<надеюсь, решить проблему.
user202729
Теперь .99убивает решение. Но зачем использовать, +.99а не только +.9? Какая разница?
user202729
@ user202729 Я чувствую себя идиотом - он был оставлен там от предыдущей версии, где я использовал Math.log2(...)и должен был вычислить потолок. Теперь это вообще не нужно. Благодарность! Я посмотрю на 2**вещь - я использовал 2**...+.99|0первоначально, но 1<<был короче, потому что мне не нужно |0. Теперь я думаю, что нет никакой разницы ...
ETHproductions
1

Желе , 14 байт

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

Попробуйте онлайн!

Как это устроено

⁸Ç¡         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 байт

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]

Попробуйте онлайн!

Это существенная модификация ответа пользователя 202729 . Я бы опубликовал это улучшение как комментарий, но ответ удален, и поэтому комментарии отключены.

notjagan
источник
Это терпит неудачу с исключением «индекс списка вне диапазона» на входе 258. Я думаю, что проблема в том, что x**2он слишком мал.
Исаак
Ну ... Python 2 отличается (часто меньше байтов) от Python 3.
user202729
1
Как и ожидалось, полуэкспонента намного больше, чем квадратичная. Решение получить «индекс списка вне диапазона» в x=1000. Вы можете попробовать 2**x- ужасно большой, но Codegolf - это Codegolf.
user202729
@ user202729 Ах, это правда. К сожалению, теперь он сталкивается с совершенно другой проблемой с большими входными данными, которая 2**xсоздает слишком большой диапазон для продолжения Python.
notjagan
0

Swift , 137 байт

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

Принимает ввод как Int(целое число) и печатает как [Int](целочисленный массив).

Неуправляемая версия

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)
}
Герман Л
источник
Мне любопытно, что произойдет, если вы уберете место перед ??
ETHproductions
@ETHproductions Это приводит к ошибке компилятора, поскольку целые числа не могут быть необязательными .
Герман Л