Поворот тривиальной последовательности

15

Вступление

Рассмотрим последовательность целых чисел f, определенную следующим образом:

  1. f (2) = 2
  2. Если n нечетное простое число, то f (n) = (f (n-1) + f (n + 1)) / 2
  3. Если n = p · q является составным, то f (n) = f (p) · f (q)

Нетрудно понять, что f (n) = n для каждого n ≥ 2 , и, таким образом, вычисление f не будет очень интересной задачей. Давайте сделаем поворот к определению: наполовину первый случай и двойной второй случай. Мы получаем новую последовательность g, определенную следующим образом:

  1. г (2) = 1
  2. Если n нечетное простое число, то g (n) = g (n-1) + g (n + 1)
  3. Если n = p · q составное, то g (n) = g (p) · g (q)

Задание

Ваша задача - взять целое число n ≥ 2 в качестве входных данных и вывести g (n) в качестве выходных. Вам не нужно беспокоиться о переполнении целых чисел, но вы должны быть в состоянии правильно вычислить g (1025) = 81 , и ваш алгоритм теоретически должен работать для произвольно больших входных данных.

Вы можете написать полную программу или функцию. Побеждает самое низкое число байтов.

пример

Выше я утверждал, что g (1025) = 81 , поэтому давайте вычислим его вручную. Первичная факторизация 1025 дает

1025 = 5*5*41 => g(1025) = g(5)*g(5)*g(41)

Поскольку 41 простое число, мы получаем

g(41) = g(40) + g(42)

Далее мы вычисляем простые факторизации 40 и 42 :

40 = 2*2*2*5 => g(40) = g(2)*g(2)*g(2)*g(5) = g(5)
42 = 2*3*7 => g(42) = g(2)*g(3)*g(7) = g(3)*g(7)

Для этих небольших простых чисел мы получаем

g(3) = g(2) + g(4) = 1 + 1 = 2
g(5) = g(4) + g(6) = 1 + 2 = 3
g(7) = g(6) + g(8) = 2 + 1 = 3

Это означает, что

g(41) = g(40) + g(42) = g(5) + g(3)*g(7) = 3 + 2*3 = 9

и

g(1025) = g(5)*g(5)*g(41) = 3*3*9 = 81

Контрольные примеры

Вот значения g до 50 .

2 -> 1
3 -> 2
4 -> 1
5 -> 3
6 -> 2
7 -> 3
8 -> 1
9 -> 4
10 -> 3
11 -> 5
12 -> 2
13 -> 5
14 -> 3
15 -> 6
16 -> 1
17 -> 5
18 -> 4
19 -> 7
20 -> 3
21 -> 6
22 -> 5
23 -> 7
24 -> 2
25 -> 9
26 -> 5
27 -> 8
28 -> 3
29 -> 9
30 -> 6
31 -> 7
32 -> 1
33 -> 10
34 -> 5
35 -> 9
36 -> 4
37 -> 11
38 -> 7
39 -> 10
40 -> 3
41 -> 9
42 -> 6
43 -> 11
44 -> 5
45 -> 12
46 -> 7
47 -> 9
48 -> 2
49 -> 9
50 -> 9
Zgarb
источник
Очень жутко похож на A002487 , но все же нет (отличается 15, 21, 25, 29, 33, 41, и еще куча, но я не могу найти реальный образец того, почему.)
Габриэль Бенами
@GabrielBenamy Ну, моя последовательность также удовлетворяет a(2*n) = a(n), и a(2*n+1) = a(n) + a(n+1)держится, если 2*n+1простое число. Для многих других нечетных чисел последовательности, вероятно, совпадают по совпадению.
Згарб
Возвращение True вместо 1 приемлемо?
Деннис
@ Денис: задача состоит в том, чтобы оценить числовую функцию, а не в решении проблемы, поэтому я бы предположил, что нет.
Павел
1
@Pavel Хотя есть большая поддержка в пользу, и, по крайней мере в Python, True действует как 1 для всех намерений и целей.
Деннис

Ответы:

7

Haskell, 69 байт

x#a|x<3=1|a>x=a#2+(x-1)#2|mod x a<1,a<x=a#2*div x a#2|b<-a+1=x#b
(#2)

Пример использования: (#2) 1025->81

Параметр aсчитается до тех пор, пока он не разделится xили не достигнет x(т. xЕ. Будет простым). Это на один байт короче, чтобы проверять a > xи добавлять дополнительное условие ( a < x) к проверке модуля вместо проверки a == x, потому что первое связывается aс x+1, что помогает в рекурсивном вызове. Для сравнения:

|a==x=(x+1)#2+(x-1)#2|mod x a<1=
|a>x=a#2+(x-1)#2|mod x a<1,a<x=
Ними
источник
4

Желе , 18 байт

‘;’Ñ€Sµ1n2$?
ÆfÇ€P

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

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

объяснение

У нас есть две взаимно рекурсивные функции. Вот вспомогательная функция (которая вычисляет g (n) для простого n ):

‘;’Ñ€Sµ1n2$?
           ?  If
        n2$     the input is not equal to 2 (parsed as a group due to $)
      µ       then do all the following (parsed as a group due to µ):
‘;’             Find the list [n+1, n-1];
   р           Call the main program on each element (i.e. [g(n+1),g(n-1)]);
     S          and return the sum of the list (i.e. g(n+1)+g(n-1)).
              Otherwise:
       1        Return 1.

А вот основная программа, которая вычисляет g (n) для любого n :

ÆfÇ€P
Æf            Factorize the input into its prime factors;
  ǀ          Call the helper function on each element of that list;
    P         Then take the product.

Понятно, что если мы вызываем основную программу по простому числу, все не работает, кроме Ç, поэтому в этом случае возвращается g (n) . Остальная часть программы обрабатывает поведение для составного n .


источник
4

JavaScript (ES6), 59 байт

f=(n,d=2)=>n-2?d<n?n%d?f(n,d+1):f(n/d)*f(d):f(n-1)+f(n+1):1

Тестовое задание

Arnauld
источник
3

Python 2, 85 69 байт

g=lambda n,k=3:(n&~-n<1)or n%k and g(n,k+2)or(g(k+1)+g(k-1))*g(n/k,k)
orlp
источник
3

Желе , 13 байт

Æfḟ2µ‘,’߀€SP

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

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

Æfḟ2µ‘,’߀€SP  Main link. Argument: n

Æf             Yield the array of prime factors of n.
  ḟ2           Remove all occurrences of 2.
    µ          Begin a new, monadic chain. Argument: A (array of odd prime factors)
     ‘         Increment all elements of A.
       ’       Decrement all elements of A.
      ,        Pair; yield [A+1, A-1].
        ߀€    Map the main link over all elements of A+1 and A-1.
           S   Column-wise reduce by addition.
            P  Reduce by multiplication.
Деннис
источник
3

Clojure, 126 байт

(defn t[n](if(= n 2)1(let[a(+(.indexOf(for[b(range 2 n)](mod n b)2)0))](if(> a 1)(*(t(/ n a))(t a))(+(t(dec n))(t(inc n)))))))

Ура! Это почти вдвое дольше, чем ответ Python!

Разрушенный и объяснение:

(defn trivial [n]
  ; Define the function.
  (if (= n 2) 1
  ; If the number is 2, return 1
    (let [a (+ 2 (.indexOf (for [b (range 2 n)] (mod n b)) 0))]
      ; Let a be the lowest prime factor of n
      (if (> a 1)
        ; The .indexOf function returns -1 if a is a prime, so -1 + 2 = 1.
        ; Checks if a is a prime.
        (* (trivial (/ n a)) (trivial a))
        ; If a is prime, return the trivial(a/n) * trivial(a).
        (+ (trivial (dec n)) (trivial (inc n)))))))
        ; Else, return trivial(n-1) + trivial(n + 1).
clismique
источник
Круто, я не знал, что ты можешь сделать (.indexOf (for [...] ...) x)!
NikoNyrh
Текущая версия 118 байт возвращает 11 для (t 1025), может быть, это ifбыло задумано :when? Но потом nthиз пустого списка выбрасывает IndexOutOfBoundsException.
NikoNyrh
@NikoNyrh Да, этого не должно случиться - я тоже это проверял, и код недействителен. Вернется к исходной версии.
clismique
2

Mathematica, 83 байта

Which[#<4,#-1,PrimeQ@#,Tr[#0/@({#-1,#+1}/2)],0<1,1##&@@#0/@Divisors@#~Part~{2,-2}]&

Безымянная рекурсивная функция одного положительного целочисленного аргумента, возвращающего целое число. Не все так коротко, в конце концов. Tr[#0/@({#-1,#+1}/2)](в случае, когда вход простое) вызывает функцию для обоих членов упорядоченной пары {(#-1)/2,(#+1)/2}и добавляет результаты; это нормально, так как функция имеет то же значение в (#-1)/2и #-1, например. Точно так же 1##&@@#0/@Divisors@#~Part~{2,-2}вызывает функцию на втором наименьшем делителе #и его дополнительном делителе (делителе второго наибольшего) и умножает ответы вместе.

Грег Мартин
источник
Как работают безымянные рекурсивные функции?
Павел
1
Проверьте раздел о #0в этом ответе .
Грег Мартин
2

Clojure, 120 байт

(defn g[n](if(= n 2)1(if-let[F(first(for[i(range 2 n):when(=(mod n i)0)]i))](*(g F)(g(/ n F)))(+(g(dec n))(g(inc n))))))

Пользы :whenполучить делители n, Fэто nilесли такой делитель не найден ( nпервична).

NikoNyrh
источник
Вы хотите ссориться, сэр? Это на (Товарищеский конкурс?)
clismique