Знайдіть функцію з циклами кожної довжини


11

Кажуть, що функція має цикл довжини n, якщо в її області існує х такий, що f n (x) = x і f m (x) ≠ x при 0 <m <n , де суперечний n позначає n - складне застосування ф . Зауважимо, що цикл довжиною 1 є фіксованою точкою f (x) = x .

Ваше завдання - реалізувати бієктивну функцію від цілих чисел до самих себе, яка має рівно один цикл кожної додатної довжини n . Бієктивна функція - це відповідність один на один, тобто кожне ціле число, відображене точно на один раз. Маючи рівно один цикл довжини n означає, що існує точно n чітких чисел x, для яких f n (x) = x і f m (x) ≠ x при 0 <m <n .

Ось приклад того, як може виглядати така функція навколо x = 0 :

x     ... -7 -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7 ...
f(x)  ...  2  4  6 -3 -1  1 -4  0 -2  5  7 -7 -6  3 -5 ...

Цей уривок містить цикли довжиною від 1 до 5 :

n   cycle
1    0
2   -2  1
3   -4 -3 -1
4   -5  6  3  7
5   -7  2  5 -6  4
...

Зауважте, що вище я використовую "функцію" лише в математичному сенсі. Ви можете написати або функцію, або повну програму на обраній вами мові, якщо це буде введене одне (підписане) ціле число як вхідне значення і поверне одне (підписане) ціле число. Як завжди, ви можете приймати введення через STDIN, аргумент командного рядка, аргумент функції тощо та виводити через STDOUT, значення повернення функції або аргумент функції (out) тощо.

Звичайно, багато мов не (легко) підтримують цілі числа з довільною точністю. Добре, якщо ваша реалізація працює лише на діапазоні цілого цілого типу вашої мови, якщо вона охоплює принаймні діапазон [-127, 127], і що вона буде працювати для довільних цілих чисел, якби тип цілого числа мови був замінений на довільний- точні цілі числа.

Діють стандартні правила .


2
Тісно пов'язані. Хоча відмінності здаються незначними, вони означають, що жоден із старих підходів не працює без суттєвих змін, і, зокрема, я не думаю, що виграшний підхід у цій проблемі взагалі не може бути адаптований.
Мартін Ендер

"має рівно один цикл на кожну довжину", "має багато циклів довжини еврі": це єдина відмінність, яка відволікає тридцять від інших?
Abr001am

@ Agawa001 Це одна відмінність, інша полягає в тому, що інша задача полягає у функціях на натуральних цілих числах, тоді як ця задача викликає функцію для всіх цілих чисел.
Мартін Ендер

1
Я думаю, що ваше визначення циклу повинно включати, що n мінімально. В іншому випадку ваш цикл довжини 2 також вважається циклом довжини 4 і 6 тощо.
xnor

@xnor Whoops, хороший момент.
Мартін Ендер

Відповіді:


2

Pyth, 27 18 байт

_h?gQ0^2Q*.5@,Q-xh

Пояснення (Pyth ініціалізує Q вхідне ціле число):

_                       negative of (
                          (
  ?gQ0                      if Q >= 0:
      ^2Q                     2**Q
                            else:
         *.5                  half of
            @        Q          element Q (modulo list length) in
             ,                    the two element list [
              Q                     Q,
                 hQ                 ((Q plus 1)
                x  Q                 XOR Q)
               -    Q               minus Q
                                  ]
 h                        ) plus 1
                        )

У цьому є цикли

(−1)
(0, −2)
(1, −3, −4)
(2, −5, −7, −6)
(3, −9, −13, −11, −8)
(4, - 17, −25, −21, −15, −10)
(5, −33, −49, −41, −29, −19, −12)
(6, −65, −97, −81, −57, −37, −23, −14)
(7, −129, −193, −161, −113, 73, −45, −27, −16)
(8, −257, −385, −321, −225 , −145, 89, −53, −31, −18)
(9, −513, −769, −641, −449, −289, −177, −105, −61, −35, −20)

Цикл довжини n задається числом

( n - 2,
−2 ^ ( n - 2) ⋅1 - 1,
−2 ^ ( n - 3) ⋅3 - 1,
−2 ^ ( n - 4) ⋅5 - 1,
…,
−2 ^ 2 ⋅ (2 · n - 7) - 1,
−2 ^ 1⋅ (2 · n - 5) - 1,
−2 ^ 0⋅ (2 · n - 3) - 1).

Кожне ціле число k ≥ −1 постає як перший елемент циклу ( k + 2). Для кожного цілого k <−1 ми можемо однозначно записати 1 - k = 2 ^ i ⋅ (2⋅ j + 1) для деяких i , j ≥ 0; тоді k постає як ( j + 2)-й елемент циклу ( i + j + 2).


5

MATL , 47 байт

E|G0<-QXJ:tQ*2/0hStJ<f0))Q2MQ)&:J6M-)2/ttk>Eq*k

Спробуйте в Інтернеті!

Загальне пояснення

Функція 2 нижче така ж, як і у відповіді @ Sp3000 на відповідний виклик. Дякуємо @ Agawa001 за те, що помітили.

Функція - це склад з трьох:

  1. Відрізок від Z (цілих чисел) до N (натурали).
  2. Відрізок від N до N з бажаною характеристикою (по одному циклу кожної довжини).
  3. Зворотна функція 1.

Функції 1 і 3 використовуються тому, що досягти бажаної поведінки в N легше (я думаю), ніж у Z .

Функція 2 полягає в наступному: верхній рядок - домен, нижній - кодомен. Для чіткості використовуються коми:

1,  2  3,  4  5  6,  7  8  9  10  ...
1,  3  2,  6  4  5, 10  7  8   9  ...

Перший блок (від верхнього 1до нижнього 1) - цикл довжиною 1. Другий (від 2 3до3 2 ) - цикл довжиною 2 і т. Д. У кожному блоці нижня частина (зображення функції) - верхня частина кругово зміщена один крок вправо.

Функція 1 така:

 -5  -4  -3  -2  -1   0  +1  +2  +3  +4  ...
+10  +8  +6  +4  +2  +1  +3  +5  +7  +9  ...

Функція 3 така сама, як 1, при цьому два рядки поміняються.

Приклади

Образ 3є -5. Спочатку 3відображається 7функція 1; потім 7відображається за 10допомогою функції 2; потім 10відображається до -5` за допомогою функції 3.

Цикл довжиною-1 становить 0. Цикл довжини-2 становить -1 1. Цикл довжиною-3 становить-3 2 -2 і т.д.

Код пояснено

Функції 1 і 3 є прямими.

Функція 2 працює, знаходячи нижню кінцеву точку відповідного вхідного блоку. Наприклад, якщо вхід до цієї функції 9він знайде 7(див. Блоки вище). Потім він вибирає верхню кінцеву точку, що є 10в прикладі. Круговий зсув блоку досягається завдяки 1-му модульному індексуванню на основі MATL.

         % FUNCTION 1
         % Implicit input
E|       % Multiply by two. Absolute value
G0<      % 1 if input is negative, 0 otherwise
-        % Subtract
Q        % Add 1
XJ       % Copy to clipboard J. Used as input to the next function

         % FUNCTION 2
:        % Range [1 2 ... J], where J denotes the input to this function
tQ*      % Duplicate, increment by 1, multiply
2/       % Divide by 2
0hS      % Prepend a 0. This is needed in case J is 0
tJ<f     % Duplicate. Find indices that are less than the input J
0)       % Pick the last index.
)        % Apply as index to obtain input value that ends previous block
Q        % Add 1: start of current block
2M       % Push the two arguments to second-to-last function call
Q)       % Add 1 and use as index: end of current block
&:       % Inclusive binary range: generate input block 
J        % Push J (input to function 2)
6M-      % Subtract start of block
)        % Apply as index (1-based, modular). This realizes the shifting

         % FUNCTION 3
2/       % Divide by 2
ttk>     % Duplicate. 1 if decimal part is not 0; 0 otherwise
Eq       % Multiply by 2, add 1
*        % Multiply
k        % Round down
         % Implicit display

це поворот функції sp3000 s, правда?
Abr001am

@ Agawa001 О, це? Я не бачив іншого виклику. Я
погляну

Ой. Це безумовно. Принаймні, це пояснює, що мої міркування, якщо не оригінальні, були правильними :-)
Луїс Мендо

дивно, як не один розум тісно обрамлений, щоб випромінювати близькі ідеї.
Abr001am

4

Python 2, 55 байт

g=lambda n,k=1:n/k and~g(~n+k*(n>0),k+1)+k*(n>0)or-~n%k

59 байт:

g=lambda n,k=1:n<0and~g(~n,2)or n/k and k+g(n-k,k+2)or-~n%k

Створює цикли

[0]
[-1, -2]
[1, 2, 3]
[-3, -4, -5, -6]
[4, 5, 6, 7, 8]
...

Змінено з мого рішення на попередньому виклику , який модифікується з конструкції Sp3000 .

Функція

g=lambda n,k=1:n/k and k+g(n-k,k+2)or-~n%k

робить цикли непарних розмірів невід’ємних чисел

[0]
[1, 2, 3]
[4, 5, 6, 7, 8]
...

Щоб знайти правильний розмір циклу k, змістіть введення nвниз на, k=1,3,5,7,...поки результат не буде в інтервалі [0,k). Обведіть цей інтервал за допомогою операції n->(n+1)%k, а потім скасуйте всі віднімання, виконані на вході. Це реалізується рекурсивноk+g(n-k,k+2) .

Тепер нам потрібен мінус, щоб зробити рівні цикли. Зверніть увагу , що якщо ми змінюємо , gщоб почати з k=2ін g, ми отримаємо цикли навіть розміру

[0, 1]
[2, 3, 4, 5]
[6, 7, 8, 9, 10, 11]
...

Ці бідекти до негативу через бітове доповнення ~. Отже, коли nце негативно, ми просто оцінюємо g(n)як ~g(~n,2).


Я не знаю, чи допомагає це, але, kздається , інший спосіб розрахунку Math.floor(Math.sqrt(n))*2+1.
Ніл

@Neil Я вивчив визначення арифметичних меж та розмірів циклу і навіть таким чином робив цілі обчислення, але ці вирази у Python є тривалими, і я виявив, що рекурсія буде коротшою.
xnor

3

Python 3, 110 байт

Я досі не зрозумів, як туди занести лямбда

якщо n - число трикутника [1,3,6,10,15,21,28 і т. д.]], тоді f (n) - це порядок у списку, помножений на від'ємний. якщо число від’ємне, дайте йому 1 + наступне найменше число трикутника. інше, прирощення.

Приклад: 5 - це не число трикутника, тому додайте 1.

Наступна ітерація у нас 6. 6 - це число трикутника, і воно є 3-м у списку, тому виходить -3.

Програма дає ці списки

довжина 1: [0]

довжина 2: [1, -1]

довжина 3: [2,3, -2]

довжина 4: [4,5,6, -3]

довжина 5: [7,8,9,10, -4]

x=int(input())
if x<0:print((x**2+x)/2+1)
else:
 a=((8*x+1)**.5-1)/2
 if a%1:print(x+1)
 else:print(-a)

Редагувати: Ще раз дякую @TuukkaX за видалення зайвих діаграм.


1
Ви можете змінити , 0.5щоб .5і input('')в input().
Yytsi

2

Python 3, 146 байт

На кожне число, що перевищує 0, є парні петлі (len 2,4,6,8 ...) і менше 0, непарні петлі (1,3,5,7). 0 карт до 0.

(-3, -2, -1), (0), (1,2), (3,4,5,6)

карти до

(-2, -1, -3), (0), (2,1), (6,3,4,5)

f=lambda x:1+2*int(abs(x)**.5)if x<1 else 2*int(x**.5+.5)
x=int(input());n=f(x)
if x>0:b=n*(n-2)/4
else:b=-((n+1)/2)**2
print(b+1+(x-b-2)%n)

Редагувати: @TuukkaX зняв 8 байт з попереднього рішення. І ще 3.


1
Я думаю, ви можете видалити пробіл перед оператором if у першому рядку. І miможе бути змінено на щось менше, наприклад b.
Yytsi

Ось така ж програма, яку переграли:f=lambda x:1+2*int(abs(x)**0.5)if x<1 else 2*int(x**0.5+0.5) x=int(input()) n=f(x) if x>0:b=n*(n-2)/4 else:b=-((n+1)/2)**2 print(b+1+(x-b-2)%n)
Yytsi

1
Дякую, @TuukkaX. Я забув про 2-х символьну змінну 'mi'.
Маджента

1
Я також змінився input('')на input(). Котирування марні, оскільки нам не потрібно нічого друкувати на консолі, коли ми хочемо просто отримати введення.
Yytsi

1
Ще коротше. Видалено нулі перед крапками. f=lambda x:1+2*int(abs(x)**.5)if x<1 else 2*int(x**.5+.5) x=int(input());n=f(x) if x>0:b=n*(n-2)/4 else:b=-((n+1)/2)**2 print(b+1+(x-b-2)%n)
Yytsi

2

Матлаб (423)

function u=f(n),if(~n)u=n;else,x=abs(n);y=factor(x);for o=1:nnz(y),e=prod(nchoosek(y,o)',1);a=log(x)./log(e);b=find(a-fix(a)<exp(-9),1);if ~isempty(b),k=e(b);l=fix(a(b));break;end;end,if(abs(n)==1)k=2;l=0;end,if(k==2)l=l+1;x=x*2;end,e=dec2base(l,k)-48;o=xor(e,circshift(e,[0 1]));g=~o(end);if(~o|nnz(o==1)~=numel(e)-g),u=n*k;else,if((-1)^g==sign(n)),u=sign(n)*k^(base2dec([e(2:end-1) 1]+48,k)-(k==2));else,u=n*k;end,end,end
  • Неконкурентований, тому що він дає добрий рекорд про те, що він був підтвердженим для останнього рейтингу, в той час як я намагаюся скоротити його, наскільки це можливо.

  • Деякі несенсифічні помилки щодо точності в matlab, які я не міг знайти жодного виходу, за винятком того, щоб зробити свій код саркатично великим, з іншого боку, картографування, яке я обрав, було з точки зору простих факторів і n-арійського логарифму.

Виконання

 f(2)

 1

 f(1)

 2

 f(-2)

 -4

 f(-4)

 -8

 f(-8)

 -1

 f(0)

 0



 ----------------------------

Пояснення

  • Зрозумівши, по-перше, що будь-яке число може бути записане як добуток експонентів прайменів N=e1^x1*e2^x2...з цієї основи, я вибрав для відображення зображень циклів, Cякі витягуються з найбільшого показника найменшого фактора (не обов'язково простого), що N - це досконала сила .

  • простішими словами, нехай N=P^xтам, де P - найменший досконалий корінь, xпозначає точно два найважливіші терміни циклу:, x=Ʃ(r*P^i)термін Pє базовим циклом, а також ідеальним коренем для основного числа N, і kє ступенем циклу C=p^k, де iколивається між 1 і k, коефіцієнтr збільшується на 1 і обмежується P-1 для будь-якого наступного попереднього зображення, поки всі коефіцієнти не будуть встановлені на r = 1, тому ми переходимо до початку цього циклу.

  • Щоб уникнути зіткнень між циклами, вибір експоненції прайменів, а не їх продуктів, є точним, оскільки, як приклад двох циклів основ 3і 2точки зустрічі між ними, можна 3*2цього уникнути, оскільки цикл визначається на ступінь більше, ніж його бази, а для точки зустрічі існує ще один цикл бази 6та ступеня 1.

  • Негативні числа ставлять виняток, як для нього, я зарезервував непарні градуси для від’ємних чисел і навіть градуси для решти. Як так ?

    для будь-якого числа N, вбудованого в цикл P^k, записується як P^(a0*P^i0+a1*P^i1+...), що величина (a0*P^i0+a1*P^i1+...)переводиться в P-ary базу як a0,a1,...., щоб уточнити цю точку, якщо (p = 2) послідовність повинна бути у двійковій базі. Як відомо заздалегідь, без встановлення умови позитивних / від'ємних ступенів та виключення (+/- 1), число N знаходиться на краях циклу градусів kтоді і лише тоді, коли послідовність Aзаписується як 1111..{k+1}..10або 111..{k}..1для всіх баз, інакше не потрібне обертання, таким чином, призначення негативної / позитивної умови для відповідних непарних / парних ступенів k/k'для обох робить непарну послідовність, записану у формі 101..{k}..100, парна послідовність записується у формі 101..{k'}..10для початку краю відповідно негативного / позитивного циклу чисел .

    Приклад:

    Беручи число N=2^10, x=10=2^1+2^3записується послідовність A A=1010, цей тип послідовності символізує кінцевий край позитивного циклу чисел, який є C=2^3, тому наступне зображення - це початковий край, A=011який є 8, але , стандартизуючи цей результат до (+ / -) 1 виняток 2^10/2карт 8/2і попереднє зображення не повинно повертатися.

    Беручи номер N=-3^9 , x=9=3^2записується послідовність A A=100, цей тип послідовності символізує кінцевий край негативного циклу числа, який є C=3^1, тому наступне зображення - це початковий край, A=01який є 3, але, пристосовуючи цей результат до негативного / позитивного -3^9карти умов до -3.

  • для пари (-/+)1, я передбачав вторгнутись її в кількість баз циклів, маючи 2на увазі, що звичайна послідовність циклічних груп {2,4}{8,16,32,64}..складається в іншій формі {1,2}{4,8,16,32}.., це запобігає будь-якій втраті попередніх елементів, і операція, що виконується, просто зміщується з вискочуванням новий елемент в.


Результати:

запуск цього маленького кодового аркуша для перевірки перших розумних діапазонів циклічних чисел:

for (i=1:6) 
index=1;if(max(factor(i))>=5) index=0;end
for ind=0:index
j=f(((-1)^ind)*i); while(((-1)^ind)*i~=j)fprintf('%d ',j);j=f(j);end,fprintf('%d \n',(-1)^ind*i),pause,end,
end

Це призводить до цих результатів

 2 1 
 -2 -4 -8 -1 
 1 2 
 -4 -8 -1 -2 
 9 27 3 
 -9 -27 -81 -243 -729 -2187 -6561 -19683 -3 
 8 16 32 64 128 256 512 4 
 -8 -1 -2 -4 
 25 125 625 3125 5 
 36 216 1296 7776 46656 6 
 -36 -216 -1296 -7776 -46656 -279936 -1679616 -10077696 -60466176 -362797056 -2.176782e+009 -1.306069e+010 ??? Error using ==> factor at 27

Останній - це помилка сегментації, але вона відповідає стандартному діапазону підписаних цілих чисел [-127,127].


Я використовував цю техніку деякий час тому, щоб визначити хеш-функції в старій програмі С, вона працює акуратно!
Abr001am

0

JavaScript (ES6), 73 байти

f=(n,i=0,j=0,k=0,l=1,m=i<0?-i:~i)=>n-i?f(n,m,k++?j:i,k%=l,l+!k):++k-l?m:j

Працює, перераховуючи послідовність (0, -1, 1, -2, 2, -3, 3, ...), поки вона не знайде n, підраховуючи цикли по ходу. iмістить поточний запис; jмістить початок поточного циклу, kіндекс всередині циклу, lтривалість поточного циклу та mнаступний запис у послідовності. Як тільки ми знайдемо, nми беремо, jчи ми в кінці циклу чи mні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.