Число трикутник перевернути


30

Скажімо, ви перераховуєте додатні цілі числа в трикутнику, а потім переверніть його вліво-вправо. Давши номер, виведіть номер, на який він надісланий. Це самообернене відображення.

         1                      1         
       2   3                  3   2       
     4   5   6    <--->     6   5   4     
   7   8   9  10         10   9   8   7   
11  12  13  14  15     15  14  13  12  11

Це п’ятий елемент A038722 , одноіндексований :

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

Ця послідовність обертає суміжні фрагменти натуральних чисел із збільшенням довжини:

 1, 3, 2, 6, 5, 4, 10, 9, 8, 7, 15, 14, 13, 12, 11, ...
<-><----><-------><-----------><------------------>

Тестові приклади:

1 -> 1
2 -> 3
3 -> 2
4 -> 6
14 -> 12
990 -> 947
991 -> 1035
1000 -> 1026
1035 -> 991
1036 -> 1081
12345 -> 12305

Табло:

Відповіді:


15

JavaScript (ES7), 26 байт

n=>((2*n)**.5+.5|0)**2-n+1

Впровадження наступної формули від OEIS :

формула

Демо


Мені подобається операція АБО, щоб скинути її на ціле число! хороша робота!
CraigR8806

7

Желе , 8 7 байт

RṁR€UFi

Завдяки @ErikTheOutgolfer за збереження 1 байта!

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

Як це працює

RṁR€UFi  Main link. Argument: n

R        Range; yield [1, ..., n].
  R€     Range each; yield [[1], [1, 2], [1, 2, 3], ..., [1, ..., n]].
 ṁ       Mold the left argument like the right one, yielding
         [[1], [2, 3], [4, 5, 6], ...]. The elements of the left argument are 
         repeated cyclically to fill all n(n+1)/2 positions in the right argument.
    U    Upend; reverse each flat array, yielding [[1], [3, 2], [6, 5, 4], ...].
     F   Flatten, yielding [1, 3, 2, 6, 5, 4, ...].
      i  Index; find the first index of n in the result.

6

Аліса , 27 байт

Завдяки Sp3000 за .Cідею.

/o
\i@/.2:e2,tE*Y~Z.H2*~.C+

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

Пояснення

Я думаю, може бути коротший спосіб обчислити це за допомогою трикутних чисел, але я подумав, що це цікаве зловживання вбудованим, тому ось інше рішення.

Основна ідея - використовувати вбудовані вбудовані модулі Аліси та "розпакувати". "Пакет", або Z, приймає два цілі числа, бієктивно їх відображає в одне ціле число. "Розпакувати", або Yперетворює це біекція і перетворює одне ціле число на два. Зазвичай це можна використовувати для зберігання списку чи дерева цілих чисел в одному (великому) цілому цілому та відновлення окремих значень пізніше. Однак у цьому випадку ми можемо використовувати функції у зворотному порядку, щоб дозволити природі біекції працювати на нас.

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

  1. Карта ℤ → ℕ (включаючи нуль) з простим "складанням". Тобто, зіставляйте негативні цілі числа на непарні натурали, а негативні цілі числа - на натуральні.
  2. Мапа → ℕ 2 , використовуючи функцію сполучення Cantor . Тобто натурали записуються по діагоналях нескінченної сітки і повертаємо індекси:

       ...
    3  9 ...
    2  5 8 ...
    1  2 4 7 ...
    0  0 1 3 6 ...
    
       0 1 2 3
    

    Наприклад, 8було б відображено в пару (1, 2).

  3. Мапа 2 → ℤ 2 , використовуючи зворотний крок 1 для кожного цілого числа окремо. Тобто непарні натурали відображаються на негативні цілі числа, і навіть натурали відображаються на невід’ємні цілі числа.

Щоб упакувати два цілих числа в одне, ми просто інвертуємо кожен із цих кроків.

Тепер ми можемо бачити, що структура функції спарювання Кантора зручно кодує потрібний нам трикутник (хоча значення є одиничними). Щоб повернути ці діагоналі, все, що нам потрібно зробити, - це поміняти координати x і y в сітку.

На жаль, оскільки всі три вищезазначені етапи об'єднані в одну вбудовану Y(або Z), нам потрібно скасувати відображення ℤ → ℕ або ℕ → ℤ самостійно. Однак, зробивши це, ми можемо зберегти пару байтів, використовуючи безпосередньо відображення + → ℤ або ℤ → ℕ + , щоб попередити помилку, що вводиться в одну таблицю. Отже, ось весь алгоритм:

  1. Карта + → ℤ використовуючи (п / 2) * (-1) п-1 . Це відображення вибрано таким чином, що воно скасовує неявне ℤ → ℕ під час розпакування, за винятком того, що воно зміщує значення вниз на 1.
  2. Розпакуйте результат на два цілих числа.
  3. Поміняйте їх.
  4. Знову упакуйте замінені значення в одне ціле число.
  5. Мапа ℤ → ℕ + за допомогою | 2n | + (n≥0) . Знову ж таки, це відображення вибирається таким, що воно скасовує неявне ℕ → ℤ під час упаковки, за винятком того, що воно зміщує значення вгору на 1.

Не виходячи з цього, ми можемо подивитися на програму:

/o
\i@/...

Це просто основа для лінійних арифметичних програм з цілим числом введення та виводу.

.    Duplicate the input.
2:   Halve it.
e    Push -1.
2,   Pull up the other copy of the input.
t    Decrement.
E    Raise -1 to this power.
*    Multiply. We've now computed (n/2) * (-1)^(n-1).
Y    Unpack.
~    Swap.
Z    Pack.
.H   Duplicate the result and take its absolute value.
2*   Double.
~    Swap with other copy.
.C   Compute k-choose-k. That's 1 for k ≥ 0 and 0 for k < 0.
+    Add. We've now computed |2n| + (n≥0).



4

Октава , 71 68 байт

3 байта зберігаються завдяки Конор О'Брайен .

x=triu(ones(n=input('')));x(~~x)=1:nnz(x);disp(nonzeros(flip(x))(n))

Це не працює для великих входів через обмеження пам'яті.

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

Пояснення

Розглянемо вхід n = 4. Код спочатку будує матрицю

 1     1     1     1
 0     1     1     1
 0     0     1     1
 0     0     0     1

Потім він замінює ненульові елементи в стовпці порядку (вниз, а потім по горизонталі) від 1, 2, 3...:

 1     2     4     7
 0     3     5     8
 0     0     6     9
 0     0     0    10

Потім він перевертає матрицю вертикально:

 0     0     0    10
 0     0     6     9
 0     3     5     8
 1     2     4     7

Нарешті, він приймає n-не ненулеве значення у порядку стовпців-мажорів, яке в цьому випадку є 6.


1
@ rahnema1 Це eгеній! Ви обов'язково повинні розмістити його як відповідь разом з іншими вашими дуже хорошими пропозиціями. Що стосується ans =, я ніколи не впевнений, чи дійсно це чи ні
Луїс Мендо

4

Haskell , 31 байт

r=round
f n=r(sqrt$2*n)^2-r n+1

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

Ця відповідь просто використовує формулу. Тут це найменш цікава відповідь, але він буває і самим гольфістом.

Haskell , 38 36 34 байт

x!y|x<=y=1-x|v<-y+1=v+(x-y)!v
(!0)

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

(!0) це точкова вільна функція, про яку ми маємо справу.

Пояснення

Дозвольте розпочати, кажу, що я дуже задоволений цією відповіддю.

Основна ідея тут полягає в тому, що якщо ми видалимо найбільше трикутне число, менше, ніж наш вхід, ми можемо повернути його назад і додати трикутне число назад. Таким чином, ми визначаємо оператора !, !бере наш регулярний вхід x, але він також займає додаткове число y. yвідстежує розмір зростаючого трикутного числа. Якщо x>yми хочемо рекурсию, ми зменшуємо xшляхом yі збільшення yна одиницю. Тому ми обчислюємо (x-y)!(y+1)і додаємо y+1до цього. Якщо x<=yми дійшли до нашого базового випадку, для повернення xрозміщення у рядку трикутника повернемося 1-x.

Haskell , 54 байти

f x|u<-div(x^2-x)2=[u+x,u+x-1..u+1]
(!!)$0:(>>=)[1..]f

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

(!!)$0:(>>=)[1..]f є точковою функцією

Пояснення

Перше, що нас хвилює f, fце функція, яка приймає xі повертає xтретій ряд третього трикутника в зворотному напрямку. Це роблять, спочатку обчислюючи x-1друге трикутне число і призначаючи його u. u<-div(x^2-x)2. Потім повертаємо список [u+x,u+x-1..u+1]. u+x- це xтрикутне число і перше число в ряду, u+x-1на одне менше, а друге число в ряду u+1на одне більше, ніж останнє трикутне число, і, отже, останнє число в ряду.

Як тільки ми маємо, fми формуємо список (>>=)[1..]f, який є сплющенням трикутника. Ми додаємо нуль на передню 0:частину, щоб наші відповіді не компенсувались одиницею, і подавали їх на нашу функцію індексації (!!).

Haskell , 56 байт

f 0=[0]
f x|u<-f(x-1)!!0=[u+x,u+x-1..u+1]
(!!)$[0..]>>=f

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

Цей на 2 байти довше, але на мою думку трохи елегантніший.


3

C (gcc) , 48 байт

k,j,l;f(n){for(k=j=0;k<n;)l=k,k+=++j;n=1+k-n+l;}

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

Можливо, неоптимальний, але я цілком задоволений цим. Використовує той факт, що

NTF N = T N + A057944 ( N ) - N + 1

(Якщо я правильно записав формулу, тобто).


Ви не викликаєте return, але використовується значення повернення. Це невизначена поведінка.
2501

@ 2501 Поки програма працює, це дозволено. І написання першого аргументу функції еквівалентно поверненню значення.
Conor O'Brien

І написання першого аргументу функції еквівалентно поверненню значення. У мові С такого немає. Стандарт навіть явно говорить, що використання повернутого значення функції, яка не повертається, є невизначеним поведінкою.
2501,

1
@ 2501 Ви, мабуть, плутаєте середовище C (gcc) для специфікації C. Так, мова C / специфікація називає її невизначеною, але вона реалізована як така. Тому, коли я кажу "еквівалент", я, безумовно, маю на увазі реалізацію C gcc та більшість інших компіляторів. На PPCG ми не пишемо "ідеальний" код - багато код іде проти специфікацій заради гольфу. Як я вже сказав, поки це працює, це відповідь справедлива.
Conor O'Brien

@ 2501 Я рекомендую вам прочитати деякі статті на мета-сайті, зокрема цю .
Conor O'Brien

2

05AB1E , 30 байт

U1V[YLO>X›iYLOX-UY<LO>X+,q}Y>V

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


Я збирався сказати "Що? Відповідь 05AB1E без Unicode?" але тоді той, хто не є ASCII символом, руйнує його ...: P Приємна перша відповідь, правда, ласкаво просимо до головоломки програмування та коду гольфу!
клісмік

@ Qwerp-Derp Дуже дякую! Я тільки почав вивчати цю мову, тому не дивуюсь, що моя відповідь була такою поганою.
Едуардо Гоефель

2

Лушпиння , 6 байт

!ṁ↔´CN

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

Пояснення

!ṁ↔´CN  -- implicit input N, for example: 4
   ´ N  -- duplicate the natural numbers:
           [1,2,3,…] [1,2,3,…]
    C   -- cut the second argument into sizes of the first:
           [[1],[2,3],[4,5,6],[7,8,9,10],…]
 ṁ↔     -- map reverse and flatten:
           [1,3,2,6,5,4,10,9,8,7,15,…
!       -- index into that list:
           6

2

тинілісп , 78 байт

(d _(q((R N T)(i(l T N)(_(a R 1)N(a T R))(a 2(a T(s T(a N R
(d f(q((N)(_ 2 N 1

Визначає функцію, fяка виконує відображення. Спробуйте в Інтернеті!

Безумовно

Ми знаходимо найменше трикутне число, яке більше або дорівнює вхідному номеру, а також, у якому рядку трикутника знаходиться наше число. З них можна обчислити перевернуту версію числа.

  • Якщо поточне трикутне число менше N, повторіть перехід до наступного ряду трикутника. (Ми розглядаємо верхній ряд як рядок 2, щоб зробити математику простішою.)
  • В іншому випадку перевернута версія N дорівнює (TN) + (TR) +2.

Основна функція flipпросто викликає функцію помічника, _flipпочинаючи з верхнього ряду.

(load library)

(def _flip
 (lambda (Num Row Triangular)
  (if (less? Triangular Num)
   (_flip Num (inc Row) (+ Triangular Row))
   (+ 2
    (- Triangular Num)
    (- Triangular Row))))))

(def flip
 (lambda (Num) (_flip Num 2 1)))

1

05AB1E , 9 байт

·LD£í˜¹<è

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

Пояснення

·L          # push range [1 ... 2n]
  D         # duplicate
   £        # split the first list into pieces with size dependent on the second list
    í       # reverse each sublist
     ˜      # flatten
      ¹<è   # get the element at index <input>-1

Вирівнювання масиву, на жаль, не обробляє великі списки дуже добре.
Ціною в 1 байт ми могли б зробити · t2z + ïn¹-> за допомогою математичної формули, floor(sqrt(2*n)+1/2)^2 - n + 1знайденої в OEIS .


1

Пакетна, 70 байт

@set/ai=%2+1,j=%3+i
@if %j% lss %1 %0 %1 %i% %j%
@cmd/cset/ai*i+1-%1

Використовує цикл, щоб знайти індекс трикутного числа хоча б на величині n.




0

APL (Dyalog), 27 байт

У мене є два рішення на одному рахунку.

Потяг:

⊢⊃⊃∘(,/{⌽(+/⍳⍵-1)+⍳⍵}¨∘⍳)

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

І dfn:

{⍵⊃⊃((⍳⍵),.{1+⍵-⍳⍺}+\⍳⍵)}

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

Обидва ці рішення спочатку створюють перевернутий трикутник, а потім витягують елемент в індексі, вказаному аргументом ( 1-основа).


0

J, 25 байт

3 :'>:y-~*:>.-:<:%:>:8*y'

Як пояснення розглянемо f(n) = n(n+1)/2. f(r), З огляду на рядок r, повертає крайній лівий номер - rй рядку дзеркальному трикутника. А тепер розглянемо g(n) = ceiling[f⁻¹(n)]. g(i), з огляду на індекс i, повертає рядок, в якому знаходиться індекс i. Потім f(g(n))повертає найменше ліве число рядка, в якому знайдено індекс n. Отже, h(n) = f(g(n)) - (n - f(g(n)-1)) + 1є відповідь на вищезазначену проблему.

Спрощуючи, ми отримуємо h(n) = [g(n)]² - n + 1 = ceiling[(-1 + sqrt(1 + 8n))/2]² - n + 1.

З вигляду формули @ Арнольда видно, що:

ceiling[(-1 + sqrt(1 + 8n))/2] = floor[1/2 + sqrt(2n)].


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