Каждая возможная длина цикла

21

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

Input:  n    1 2 3 4 5 6
Output: f(n) 5 7 1 3 4 9

Если мы начинаем с n=1, f(n)=5, f(f(n))=f(5)=4, f(f(f(n)))=f(4)=3, f(f(f(f(n))))=f(3)=1.

Это написано (1 5 4 3). Поскольку в этом цикле 4 уникальных числа, это цикл длины 4.


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

Кроме того, ваша функция / программа должна быть от положительных целых чисел до положительных целых чисел, и она должна быть биективной , то есть для каждого возможного выходного значения должно быть ровно одно входное значение по всем положительным целым числам. Другими словами, функция / программа должна вычислять перестановку натуральных чисел.


Подробности: разрешена любая стандартная система ввода / вывода, включая STDIN, STDOUT, аргумент функции, возврат и т. Д. Стандартные лазейки запрещены.

Вам не нужно беспокоиться об ограничениях типов данных - перечисленные выше свойства нужно хранить только в предположении, что, например, intили floatможет содержать любое значение.

Нет ограничений на поведение функции на входах, которые не являются положительными целыми числами, и эти входы / выходы будут игнорироваться.


Подсчет очков - это код в байтах, самый короткий код выигрывает.

isaacg
источник
«должен быть цикл длины 1, длины 2 и т. д.» Если это следует интерпретировать как «должен быть хотя бы цикл длины 1, как минимум один из длины 2 и т. д.» или «должен быть быть точно циклом длины 1, длиной 2 и т. д. ".
Бакуриу
@Bakuriu Как минимум один цикл каждой положительной длины.
Исаак

Ответы:

11

Pyth, 11 8 байт

.<W-0zz1

Намного скучнее, чем мой предыдущий ответ.

Каждое число, которое содержит 0 цифр, отображается на себя. Любое другое число отображается на число, цифры которого повернуты на 1. Так, например:

1 -> 1
10 -> 10
15 -> 51 -> 15
104 -> 104
123 -> 231 -> 312 -> 123
orlp
источник
8

Python 2, 56 55 54 байта

n=input()
a=b=1
while a+b<=n:a+=b;b+=1
print(n+~a)%b+a

Вот первые 21 вывод:

[1, 3, 2, 6, 4, 5, 10, 7, 8, 9, 15, 11, 12, 13, 14, 21, 16, 17, 18, 19, 20]

Шаблон очевиден, если разбить список на куски примерно так:

 1    2  3    4  5  6    7  8  9  10    11  12  13  14  15    16  17  18  19  20  21
[1]  [3, 2]  [6, 4, 5]  [10, 7, 8, 9]  [15, 11, 12, 13, 14]  [21, 16, 17, 18, 19, 20]
Sp3000
источник
Блин, это шаблон, который я тоже собирался, но с закрытой формой.
orlp
1
Интересно .. a-значения следуют последовательности A000124 . Но я думаю, вы уже знали, что: P
Kade
Обратите внимание, что эта последовательность oeis.org/A066182 .
orlp
8

Pyth, 25 байт

+hK/*J/h@h*8tQ2 2tJ2%-QKJ

Это та же последовательность, что и у @ Sp3000, но с закрытой формой. Закрытая форма:

M (n) = этаж ((1 + sqrt (1 + 8 * (n - 1))) / 2) B (n) = M (n) * (M (n) - 1) / 2 f (n) = B (n) + ((n - B (n) + 1) mod M (n))

orlp
источник
5

Python3, 40 байт

n=input();print([n[1:]+n[0],n]['0'in n])

Каждое число, которое содержит 0 цифр, отображается на себя. Любое другое число отображается на число, цифры которого повернуты на 1. Так, например:

1 -> 1
10 -> 10
15 -> 51 -> 15
104 -> 104
123 -> 231 -> 312 -> 123
orlp
источник
1
Дежавю! Здорово видеть это на двух языках!
Денхем Кут
3

Рубин, 22 + 1 = 23

С флагом командной строки -pзапустите

~/(.)(.?)/
$_=$1+$'+$2

Когда задано в качестве входных данных строковое представление числа (без завершающего символа новой строки), оно сохраняет первую цифру постоянной, а затем поворачивает остаток влево, таким образом, 1234становится 1342.

Это может быть уменьшено до 21 символа $_=$1+$'+$2if/(.)(.)/, но выводит предупреждение.

histocrat
источник
3

Рубин, 16 + 1 = 17

С флагом командной строки -pзапустите

$_=$_[/.0*$/]+$`

Это более сложная функция, чем мой другой ответ, но, оказывается, она более пригодна для игры в гольф (и терпима к последующим переводам строки). Он берет последнюю ненулевую цифру ввода, плюс любые завершающие нули, и перемещает ее в начало числа. Так 9010300становится 3009010. Любое число с n ненулевыми цифрами будет частью цикла n длины.

Ввод - это строка в любой базе через STDIN, вывод - это строка в этой базе.

histocrat
источник
2

Python, 43

Обратная функция Sp3000 в , реализовано рекурсивно.

f=lambda n,k=1:n>k and k+f(n-k,k+1)or n%k+1

Функция представляет собой один цикл, за которым следует два цикла, за которыми следует три цикла ...

(1)(2 3)(4 5 6)(7 8 9 10)(11 12 13 14 15)...

Операция n%k+1действует как kцикл на числах 1..k. Чтобы найти подходящий kдля использования, сдвиньте все вниз k=1, затем k=2, и так далее, до тех пор, пока n<=k.

XNOR
источник
2

Pyth, 15 байт

Самый короткий ответ, который использует числовые операции, а не строковые.

.|.&Q_=.&_=x/Q2

    Q                input
            /Q2      input div 2
           x   Q     that XOR input
          =          assign that to Q
         _           negate that
       .&       Q    that AND Q
      =              assign that to Q
     _               negate that
  .&                 input AND that
.|               Q   that OR Q

Влияние этой функции на двоичное представление заключается в расширении самого правого блока 1 с до следующего 0; или, если нет 0, чтобы сбросить его обратно до одного 1:

10010110100000 ↦  
10010110110000 ↦  
10010110111000 ↦  
10010110111100 ↦  
10010110111110 ↦  
10010110111111 ↦
10010110100000  

Pyth, 26 байтов, забавный вариант

.|.&Q_h.&/Q2+Qy=.&/Q2_h.|y

    Q                           input
         /Q2                    input div 2
             Q                  input
                  /Q2           input div 2
                         yQ     twice input
                       .|  Q    that OR input
                     _h         NOT that
                .&              (input div 2) AND that
               =                assign that to Q
              y                 twice that
            +                   input plus that
       .&                       (input div 2) AND that
     _h                         NOT that
  .&                            input AND that
.|                          Q   that OR Q

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

1000010001001 ↦
1100011001101 ↦
1110011101001 ↦
1111010001101 ↦
1000011001001 ↦
1100011101101 ↦
1110010001001 ↦
1111011001101 ↦
1000011101001 ↦
1100010001101 ↦
1110011001001 ↦
1111011101101 ↦
1000010001001
Андерс Касеорг
источник
1

Swift 1.2, 66 байт

func a(b:Int){var c=0,t=1,n=b
while n>c{n-=c;t+=c++}
print(n%c+t)}
Input:  1,   2, 3,  4, 5, 6,   7, 8, 9, 10,   11, 12, 13, 14, 15
Output: 1,   3, 2,  5, 6, 4,   8, 9, 10, 7,   12, 13, 14, 15, 11
Дэвид Скрундз
источник
1

Брахилог , 5 байт

∋0&|↺

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

Порт ответа @ orlp's Pyth. Получается просто и аккуратно:

∋0    % If input contains a 0 (since input is a single number, "contains" ∋ treats it as an array 
      %   of its digits, so this means "if any of input's digits are 0")
&     % Then output is the input
|     % Otherwise
↺     % Circularly shift the input once, and unify that with the output

Первоначально я хотел портировать решение Python @ Sp3000, но это заняло колоссальные 23 байта :

⟧∋B-₁⟦++₁A≤?;A--₁;B%;A+

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

sundar - Восстановить Монику
источник
0

JavaScript (ES6), 43 байта

f=(n,i=1,j=1)=>n>j?f(n,++i,j+i):n++<j?n:n-i
Нил
источник
0

Matlab (189)

  function u=f(n),if(~n|n==1)u=n;else,u=n;y=factor(n);z=y(y~=2);if ~isempty(z),t=y(y~=max(y));if isempty(t),u=y(end)*2^(nnz(y)-1);else,g=max(t);e=primes(g*2);u=n/g*e(find(e==g)+1);end,end,end

  • Функция:

    Отображает любое целое число в соответствии с его простыми множителями, если число равно нулю или разложено на 2 или 1, число сопоставляется с самим собой, в противном случае мы выбираем самый большой простой множитель из этого числа, затем мы увеличиваем оставшиеся различные простые простые множители на ближайший большего простого множителя, пока мы не достигнем числа, biggest_prime^nгде nесть сумма всех показателей всех факторов, как только мы достигнем этого количества, мы обращаемся max_prime*2^(n-1)и воспроизводим тот же цикл снова.

Abr001am
источник
0

Matlab (137)

  function u=h(n),if(~n|n==1)u=n;else,u=n;y=factor(n);z=y(y~=2);if~isempty(z),e=nnz(y);f=nnz(z);if(~mod(e,f)&e-f)u=n/2^(e-f);else,u=u*2;end

  • Немного похожий подход, постепенно умножая любое число, не равное {0,1,2 ^ n}, 2до тех пор, пока мы не наткнемся на показатель степени, 2который делится на сумму показателей других простых факторов. затем мы переходим к началу цикла деления на 2^(sum of exponents of other primes). другие онемели отображаются на себя.
Abr001am
источник