Ваша База на 1-2-3-Трибоначі до Бінарного назад до Бази


19

Фон

Послідовність 1-2-3-трибобочки

Уявіть собі на секунду, що ви можете скласти послідовність вирівнювання, замінивши стандартну формулу ітерації на таке:

трибочніки

По суті, замість того, щоб підсумовувати останні два, щоб отримати наступне, ви підсумовуєте останні три. Це основа для послідовності 1-2-3-Трибонаші.

Критерій Брауна

Критерій Брауна стверджує, що ви можете представляти будь-яке ціле значення у вигляді суми членів послідовності за умови, що:

  1. x sub n дорівнює 1

  2. Для всіх, nбільших за 1,x sub n менше 2 x sub n - 1

Що це означає для виклику

Ви можете описати будь-яке додатне ціле число як суму членів послідовності 1-2-3-Трибоначчі, утворених такими початковими умовами:

початкові умови

Це відомо, як для кожного значення в цій послідовності співвідношення між термінами ніколи не перевищує 2 (коефіцієнт в середньому становить приблизно 1,839).

Як записати в цю числову систему подання

Скажімо, ви використовуєте малоповажне представлення. Розташуйте членів послідовності так:

1  2  3  6 11 20 37 68

Потім ви берете своє число для представлення (для наших тестів, скажімо, це 63) і знаходите значення заданих 1-2-3-трибочніків, які дорівнюють 63 (спочатку використовуючи найбільші значення!) . Якщо число є частиною суми, покладіть під ним 1, 0 якщо ні.

1  2  3  6 11 20 37 68
0  0  0  1  0  1  1  0

Ви можете зробити це для будь-якого цілого числа - просто переконайтеся, що спочатку ви використовуєте найбільші значення нижче вказаного вводу!

Визначення (нарешті)

Напишіть програму або функцію, яка буде виконати наступне, задавши введення додатного цілого числа n(записане в будь-якій стандартній базі) між 1 і максимальним значенням вашої мови:

  1. Перетворіть значення у визначене числове представлення 1-2-3-Трибоначчі.
  2. Використовуючи це бінарне подання, і читайте його так, ніби двійкове. Це означає, що цифри залишаються однаковими, але те, що вони означають, змінюється.
  3. Візьміть це двійкове число і перетворіть його в основу вихідного числа.
  4. Виведіть або поверніть це нове число.

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

Приклади

Нехай функція f- це функція, описана визначенням, і нехай []представляє кроки, зроблені (як маленькі ендіани, хоча це не має значення) (вам не потрібно слідувати за цим процесом, це лише описаний процес):

>>> f(1)
[1]
[1]
[1]
1

>>> f(5)
[5]
[0, 1, 1]
[6]
6

>>> f(63)
[63]
[0, 0, 0, 1, 0, 1, 1]
[104]
104

Чи можу я подати окрему програму, яка хоч і не така коротка, вирішить питання швидше? log (log (n)) + n час на відміну від log (n) + n час. Перейти до N-ї матриці потужності.
fəˈnɛtɪk

@LliwTelracs Я не можу перешкодити вам публікувати свої рішення. Просто зробіть цільовий метод рішення максимально стислим до своїх знань, щоб переконатися, що ви все ще змагаєтесь у правильному полі.
Аддісон Кримп

Ну, не збираюся робити цього хоча б. Швидке
викриття

2
@LliwTelracs Можливо, просто додати його як доповнення до вже існуючої посади.
Джонатан Аллан

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

Відповіді:


7

Javascript 117 111 байт

Дякуємо @theonlygusti за те, що допомагає гольфу на 5 байтах

x=>{r=0;a=[1,2,3];i=1;while(a[++i]<x)a[i+1]=a[i]+a[i-1]+a[i-2];for(;x;i--)if(x>=a[i]){r+=1<<i;x-=a[i]}return r}

Як це працює

По-перше, функція генерує всі трибонацькі числа до тих пір, поки не знайде одне більше, ніж вхідне

a=[1,2,3];i=1;for(;a[++i]<x;)a[i+1]=a[i]+a[i-1]+a[i-2];

Далі відбувається зворотний пошук списку чисел. Якщо число менше введення, воно додає 2 ^ (індекс цього числа) до значення, що повертається, і зменшує введення на це число.

for(;x;i--)if(x>=a[i]){r+=1<<i;x-=a[i]}

Нарешті він повертає результат.

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


1
як щодо a[++i]<xвнутрішньої умови для збереження байта?
theonlygusti

1
Також ви можете замінити x>0на x. Збережіть ще 2 байти.
theonlygusti

Це досить хороший алгоритм. oo
Addison Crump

7

Пітон 2 , 110 102 байти

-3 байти завдяки Роду (акуратний трюк для iпередачі булевих даних до int, +iтому репр `+i`працює)

n=input()
x=[3,2,1]
r=''
while x[0]<n:x=[sum(x[:3])]+x
for v in x:i=n>=v;n-=v*i;r+=`+i`
print int(r,2)

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


1
ви можете замінити '01'[i]з`+i`
Rod

iбулевий, а не int. Редагувати - Ой +i, акуратно.
Джонатан Аллан

3
@Rod Це хитрість у поради та підказки Python 2?
Аддісон Кримп

@VoteToClose Я так не думаю
Rod

7

JavaScript (ES6), 97 93 байт

Тут ми використовуємо reduce()рекурсивну функцію. Ми припускаємо, що вихід є 31-бітовим (що є найбільшою безпідписаною кількістю, з якою JS так чи інакше може легко працювати для розрядних операцій).

n=>[...Array(x=31)].reduce(p=>(c=(F=k=>k<4?k:F(--k)+F(--k)+F(--k))(x--))>n?p:(n-=c,p|1<<x),0)

Продуктивність розумна, це, очевидно, не дуже ефективно.

Для допитливих:

  • Співвідношення між кількістю викликів F()для N + 1 reduce()ітерацій проти N ітерацій швидко сходить до константи Трибоначчі (≈ 1,83929). Тому кожен додатковий біт на виході коштує приблизно вдвічі більше часу, ніж попередній.
  • Маючи 31 біт, F()функція називається гарною 124 мільйони разів.

Тест

Примітка: це може знадобитися 1 або 2 секунди.


Нічого собі, це відстає від мого браузера, коли я ним користуюся. xD
Addison Crump

@VoteToClose Ефективність, це жахливо неефективно. :-) Проте тестовий код не повинен затримуватися занадто довго. У моїй коробці я отримую близько 600 мс в Firefox і 900 мс в Chrome. Чи набагато повільніше на вашому боці?
Арнольд

Мовляв, 5 секунд. xD
Addison Crump

@VoteToClose Зараз має бути трохи швидше. 32-а ітерація була безглуздою, тому я обмежив вихід непідписаним 31-бітовим цілим числом.
Арнольд

6

Математика, 78 74 байт

Fold[#+##&,#~NumberDecompose~Reverse@LinearRecurrence[{1,1,1},{1,2,3},#]]&

LinearRecurrence[{1,1,1},{1,2,3},#]генерує список, довжиною, рівним вхідному, числа 1-2-3 числа трибочків. (Значення {1,1,1}являє собою суму попередніх трьох доданків, тоді {1,2,3}як початкові значення.) Потім#~NumberDecompose~ знаходить найкорисніший спосіб записати введення як суму елементів списку (це та сама функція, яка розклала б грошову суму на кратні доступні валюти, наприклад). Нарешті, Fold[#+##&,...]перетворює отриманий бінарний список у ціле число (base-10).

Попереднє подання:

Fold[#+##&,#~NumberDecompose~Reverse@Array[If[#<4,#,Tr[#0/@(#-Range@3)]]&,#]]&

Як це часто буває (хоча і не вище), ця версія для гольфу надто повільна на входах більше 20 або більше, оскільки вона генерує (з неоптимізованою рекурсією) список племен, довжина яких є входом; заміна фіналу #на більш розумну пов'язану форму, як Round[2Log@#+1]результат, значно краща.


Whaat? У Mathematica немає 123Tribonacci[]вбудованого?
палш

1
Не зовсім так, хоча виявляється, що використання вбудованого трохи допомагає.
Грег Мартін

5

Haskell, 95 байт

(a!b)c=a:(b!c)(a+b+c)
e#(r,c)|c-e<0=(2*r,c)|1<2=(2*r+1,c-e)
f n=fst$foldr(#)(0,n)$take n$(1!2)3

Приклад використання: f 63-> 104.Спробуйте в Інтернеті! .

Як це працює: !будує послідовність 1-2-3-Трибонаші. З огляду на 1, 2а 3також параметри запуску, ми візьмемо перші nелементи послідовності. Тоді ми згин правої функції , #яка віднімає наступний елемент eз nі встановлює біт в повернутому значенні , rякщо eце необхідно або дозволяє бітову невстановлені. Встановлення біту подвоєне, rа додавання 1, а його скидання просто подвоєне.


4

Желе , 31 байт

S=³
3RUµḣ3S;µ<³Ạµ¿µŒPÇÐfṀe@ЀµḄ

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

Я майже впевнений, що В ЖЕЛІ це набагато коротший спосіб досягти цього.

Як?

S=³ - Link 1, compare sum to input: list
S   - sum
  ³ - 3rd command line argument which is 1st program argument.
 =  - equal?

3RUµḣ3S;µ<³Ạµ¿µŒPÇÐfṀe@ЀµḄ - Main link: n
3RU                         - range(3) upended -> [3,2,1]
   µ    µ   µ¿              - while
         <³                 - less than input (vectorises)
           Ạ                - all?
    ḣ3S;                    -     head(3), sum, and concatenate
                                  [3,2,1] -> [6,3,2,1] -> [11,6,3,2,1] -> ...
              µ             - monadic chain separation, call the result x
               ŒP           - power set of x - e.g. for [6,3,2,1] -> [[],[6],[3],[2],[1],[6,3],[6,2],[6,1],[3,2],[3,1],[2,1],[6,3,2],[6,3,1],[6,2,1],[3,2,1],[6,3,2,1]]
                  Ðf        - filter keep
                 Ç          -     last link (1) as a monad (those that sum to the input)
                    Ṁ       - maximum (e.g. an input of 63 would yield [[37,20,6],[37,20,3,2,1]], the maximum of which is [37,20,6], the one with the largest numbers used)
                         µ  - monadic chain separation (to have x as the right argument below)
                     e@Ѐ   - exists in with reversed arguments mapped over x (e.g. [37,20,6] with x = [68,37,20,11,6,3,2,1] yields [0,1,1,0,1,0,0,0])
                          Ḅ - convert from binary to integer.        

4

Perl 6 , 93 91 байт

-2 байти завдяки b2gills

{my@f=1,2,3,*+*+*...*>$^n;sum @f».&{$_~~any first *.sum==$n,@f.combinations}Z*(2 X**^∞)}

Як це працює

  • По-перше, він генерує 1-2-3-трибонацьку послідовність до першого елемента, більшого за вхідний:

    my @f = 1, 2, 3, *+*+* ... * > $^n;
  • Виходячи з цього, він знаходить підмножину послідовності, яка додає до вводу:

    first *.sum==$n, @f.combinations
  • На підставі цього він будує список булевих даних, вказуючи, чи є кожен елемент послідовності частиною суми:

    @f».&{$_~~any ...}
  • І, нарешті, він інтерпретує цей список True = 1, False = 0 значень як базовий 2 та повертає його як (базове 10) число:

    sum ... Z* (2 X** ^∞)

1
Ви можете скоротити його за допомогою *>$^nі .sum==$n. Також простір не потрібен між myі@f
Бред Гілберт b2gills

3

JavaScript (ES6), 61 60 байт

n=>(g=(x,y,z)=>(n>x&&g(y,z,x+y+z)*2)+!(n<x||![n-=x]))(1,2,3)

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

Редагувати: Збережено 1 байт завдяки @Arnauld.


Оце Так! Дуже хороша. Не вдалося n=>(g=(x,y,z)=>(n>x&&g(y,z,x+y+z)*2)+!(n<x||![n-=x]))(1,2,3)зберегти байт?
Арнольд

@Arnauld Я шукав щось, використовуючи, n<x||але ![]це просто геній.
Ніл

2

Пакетна, 151 148 145 байт

@set/ar=0,n=%1
@call:c 3 2 1
@echo %r%
@exit/b
:c
@set/as=%1+%2+%3
@if %n% gtr %3 call:c %s% %*
@set/ar*=2
@if %n% geq %3 set/an-=%3,r+=1

Порт моєї відповіді на JavaScript. Правка: Збережено 3 байти, передавши мої аргументи підпрограми у зворотному порядку та ще 3 байти за допомогою окремих@ s у кожному рядку замість @echo off.


2

Желе , 19 18 17 байт

Ḣx3+
BÇL¡2ị
²Ç€»ċ

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

Фон

Замість того, щоб намагатися перетворити ціле число в базу 1,2,3-Трибоначчі, потім з двійкового в ціле, ми зробимо навпаки: перетворимо цілі числа в бінарні, потім з 1,2,3-бази Trionacci в цілі, і повернемося найвищий, який відповідає вхідному. Це легко здійснити.

Ми наведемо приклад процесу введення 63 , зокрема кроку, на якому тестується 104 . У двійковій, від найбільш значущої до найменш значущої цифри, 104 дорівнює

 1  1  0  1  0  0  0
37 20 11  6  3  2  1

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

Ми можемо розширити 1,2,3-трибонацьку послідовність праворуч, зауважуючи, що додані цифри відповідають тій же рекурсивній формулі. Для трьох мережевих цифр це дає

 1  1  0  1  0  0  0  0  0  0
37 20 11  6  3  2  1  0  1  0

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

 1  1  0  1  0  0  0  0  0  0
37 20 11  6  3  2  1  0  1  0

    2  1  2  0  0  0  0  0  0
   20 11  6  3  2  1  0  1  0

       3  4  2  0  0  0  0  0
      11  6  3  2  1  0  1  0

          7  5  3  0  0  0  0
          6  3  2  1  0  1  0

            12 10  7  0  0  0
             3  2  1  0  1  0

               22 19 12  0  0
                2  1  0  1  0

                  41 34 22  0
                   1  0  1  0

                     75 63 41
                      0  1  0

Тепер, оскільки обидва перший і останній цифри мають позиційне значення 0 , результат - середня цифра, тобто 63 .

Як це працює

²Ç€»ċ   Main link. Argument: n

²       Yield n². Since 1.839² = 3.381921 > 2, the range [1, ..., n²] will contain
        the answer. Better bounds, at the cost of additional bytes are possible.
 Ç€     Map the the second helper link over [1, ..., n²].
   »    Take the maximum of n and each result.
    ċ   Count the occurrences of n.


BÇL¡2ị  Second helper link. Left argument: k. Right argument: n

B       Convert k to binary. Let's call the result A.
  L     Length; count the number of binary digits. Let's call the result l.
 Ç ¡    Apply the first helper link l times to A.
    2ị  Retrieve the second element.


Ḣ×3+    First helper link. Argument: A (array)

Ḣ       Head; pop and yield the first element of A.
 x3     Repeat it thrice.
   +    Add the result, component by component, to the beheaded A.

2

Желе ( виделка ), 17 16 байт

ḣ3S;µ¡
3RṚdzæFṪḄ

Збережено 1 байт завдяки @Dennis, який переграв його, навіть не запустивши його.

Це спирається на вилку Jelly, де я невтішно все ще працюю над впровадженням ефективного атома Frobenius. Для тих, хто цікавиться, я хотів би відповідати швидкості Mathematica FrobeniusSolveі, на щастя, є пояснення їх методу в статті "Внесення змін і пошук рефінігітів: врівноваження ранку" Даніеля Ліхтблау.

Пояснення

ḣ3S;µ¡  Helper link. Input: a list
    µ   Create monadic chain
ḣ3        Take the first 3 items
  S       Sum
   ;      Prepend to the list
     ¡  Repeat it n (initial argument from main) times

3RṚdzæFṪḄ  Main link. Input: integer n
3          The constant 3
 R         Range. Makes [1, 2, 3]
  Ṛ        Reverse. Makes [3, 2, 1]
   Ç       Call the helper link on that list.
           Generates the first (n+3) 123-Tribonacci values in reverse
    ³      Get n
     æF    Frobenius solve for n using the first n 123-Tribonacci values in reverse
       Ṫ   Tail. Take the last value. The results of Frobenius solve are ordered
           where the last result uses the least
        Ḅ  Unbinary. Convert digits from base 2 to base 10

3
Ви знаєте, що ви заглиблюєтеся в код гольфу, коли використовуєте вилки супер-езоланг.
Аддісон Кримп

Було б ḣ3S;µ¡¶3RṚdzæFṪḄпрацювати? У мене не встановлена ​​ваша виделка, тому я не можу перевірити.
Денніс

@Dennis Це означає, що стідін не має аргументів, правда? У мене виникли проблеми з використанням аргументів і я просто зрозумів, що це працює інакше.
миль

Ні, це все одно мають бути аргументи. ³посилається на перший аргумент.
Денніс

@Dennis Nvm, це спрацьовує аргументами, у мене jelly.pyбули деякі інші речі після цього останнього зобов'язання.
миль

1

постійного струму , 110 102 байти

?se1sa2sb3sc_1sf[laddSdlbdsalcdsb++sclf1+sfle>y]dsyx0sk[lk2lf^+skler-se]sr[Lddle!<rlf1-dsf0!>z]dszxlkp

Ну, схоже, великі уми так і думають. Мабуть, алгоритм, який я придумав, щоб подолати обмеження, dcє збігом випадково тих самих, які використовувались у відповіді @ LliwTelrac. Цікаво.

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



1

bash + BSD утиліти (OS X тощо), 53 байти

jot $[2#$1**4]|egrep -v '[2-9]|11(1|$)'|sed $[2#$1]!d

bash + GNU утиліти (працює і під BSD), 59 байт

seq -f2o%.fp $[2#$1**2]|dc|egrep -v '11(1|$)'|sed $[2#$1]!d

Вхід і вихід у обох вищезазначених даних є двійковими.


Спробуйте версію GNU на TIO. (Приклад, зв'язаний з демонстрацією введення 111111, що становить 63 у двійковій, та виходу 1101000, що 104 у двійковій.)

Я не думаю, що TIO пропонує варіант BSD, але якщо у вас є Mac, ви можете спробувати їх і там. (59-байтна програма набагато швидша, ніж 53-байтна програма.)


На жаль, seqзамість цього не можна просто потрапити до рішення BSD jot, оскільки вихідний формат дляseq вищий за 999999 відрізняється (це починає бути проблемою для входів близько 32, оскільки 32 ^ 4> 1000000.)

Ви можете замінити jot вище на, seq -f%.fщоб змусити це працювати з утилітами GNU, але для тих же 59 байтів ви можете скористатися рішенням GNU вище, що набагато швидше.

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