Двоичные Фибоначчи


31

Вызов

Вам нужно сгенерировать программу или функцию, которая принимает положительное целое число N, вычисляет первые N членов последовательности Фибоначчи в двоичном формате, объединяет их в одно двоичное число, преобразует это число обратно в десятичное и затем выводит десятичное число как целое число.

Например

1 -> [0] -> 0 to decimal outputs 0
3 -> [0, 1, 1] -> 011 to decimal outputs 3
4 -> [0, 1, 1, 10] -> 01110 to decimal outputs 14

Вам не нужно выводить ->, только число (например, если пользователь вводит 4, просто вывод 14). Стрелки просто помогают объяснить, что должна делать программа.

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

1 -> 0
2 -> 1
3 -> 3
4 -> 14
5 -> 59
6 -> 477
7 -> 7640
8 -> 122253
9 -> 3912117
10 -> 250375522
11 -> 16024033463
12 -> 2051076283353
13 -> 525075528538512
14 -> 134419335305859305
15 -> 68822699676599964537
16 -> 70474444468838363686498
17 -> 72165831136090484414974939
18 -> 147795622166713312081868676669
19 -> 605370868394857726287334099638808
20 -> 4959198153890674493745840944241119317

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

Это , поэтому выигрывает ответ с наименьшим количеством байтов!


1
Добавлены тестовые примеры от 0 до 20 от tio.run/##DYxBCoQwDAC/… . Благодарим @alephalpha за программу.
Натан Вуд

6
Как еще не было сказано: Добро пожаловать в PPCG! Хороший первый вызов.
Лайкони

@Laikoni Спасибо!
Натан Вуд

Где конкретно применяется ограничение по конкретному языку? Будет ли разрешена функция C, которая возвращает 32-разрядное целое число? Как int32_t binary_concat_Fib(int n), что бы ограничить результирующее выходное значение до 2 ^ 31-1. то есть вы предполагаете, что все сцепленные биты помещаются в целое число. Или функция должна работать до точки, где наибольшее число Фибоначчи не помещается в целое число само по себе, поэтому объединение битов требует повышенной точности?
Питер Кордес

1
И нужно ли явное "преобразование в десятичное число", вызывая целочисленную-> строковую функцию или записывая ее самостоятельно? Объединение битов в одно целое дает представление о конечном значении. Если я правильно понимаю, в ответе Денниса на Python возвращается целое число, и вызывающая сторона может преобразовать это значение в десятичную строку или сделать с ней что угодно. Целочисленные значения в компьютерных языках, которые поддерживают операторы битового сдвига, являются естественно двоичными, а не десятичными, если они не хранятся в строках. В языках без сдвигов / побитовых операторов ничто не подразумевает никакой базы.
Питер Кордес

Ответы:



10

Желе ,  7  6 байт

ḶÆḞBẎḄ

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

Как?

ḶÆḞBẎḄ - Link: integer, n
Ḷ      - lowered range -> [0,1,2,3,4,5,...,n]
 ÆḞ    - Fibonacci (vectorises) -> [0,1,1,2,3,5...,F(n)]
   B   - to binary (vectorises) -> [[0],[1],[1],[1,0],[1,1],[1,0,1],...,B(F(n))]
    Ẏ  - tighten -> [0,1,1,1,0,1,1,1,0,1,...,B(F(n))[0],B(F(n))[1],...]
     Ḅ - from binary -> answer

1
Разбираясь с новыми квиками, я обнаружил, что можно также найти первые n чисел Фибоначчи, Ṛc’SƲƤкоторые могут быть полезны для подобных последовательностей.
миль


7

брейкфук , 397 байт

>,[<++++++[->--------<]>>[->++++++++++<]>[-<+>]<<[->+<],]>+[-<<+>>[-[->+<]<<[->+>+<<]<[->+>+<<]>[-<+>]>>[-<<+>>]>]]<<[->+>>>>>+<<<<<<]>[-<+>]>+>>+>>>+<[[->-[<<]>]>[[-]<<<<<<<[->>[-<+>>+<]>[-<+>]<<<]<[->+>>>>>+<<<<<<]>[-<+>]>[-<+>]>[->>[-<+<<+>>>]<[->+<]<]>+>[-]>>+>]<<<<<[[->++>+>++<<<]>[-<+>]<<]>>>]>[-]<<<[-]<<[-]<<->[>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>>>]<+[->++++++[-<++++++++>]<.<<<+]

Ну, это было весело!

Принимает ASCII-ввод (например, 11 ), выводит результат в ASCII.

Примечание: чтобы попробовать это онлайн, убедитесь, что вы установили размер ячейки 32 бита (в правой части веб-страницы). Если вы не введете ввод, ваш браузер может произойти сбой.

Интерпретатор не может обрабатывать ввод 11и выше, потому что он поддерживает только до 32 бит.

Попробуйте это на copy.sh

объяснение

>,[<++++++[->--------<]>>[->++++++++++<]>[-<+>]<<[->+<],]>+

Получите десятичный вход и добавьте один (чтобы смягчить одно за другим)

[-<<+>>[-[->+<]<<[->+>+<<]<[->+>+<<]>[-<+>]>>[-<<+>>]>]]

Генерация чисел Фибоначчи на ленте.

<<[->+>>>>>+<<<<<<]>[-<+>]>+>>+>>>+<

Настройка для входящего двоичного конкатенационного цикла


Таким образом, ячейки содержат значение, начиная с первой позиции,

1 | 0 | 1 | 1 | 2 | 3 | 5 | ... | f_n | 0 | 1 | 0 | 1 | 0 | f_n | 1 | 0 | 0 | 0...

Посмотрите на эти клетки:

f_n | 0 | 1 | 0 | 1 | 0 | f_n | 1

Я обозначу это:

num | sum | cat | 0 | pow | 0 | num | pow

powесть ли найти максимальную степень 2, которая строго больше, чем num. sumэто объединение чисел до сих пор. catэто степень 2, которую мне нужно было бы умножить num, чтобы объединить numперед sum(так что я мог бы просто добавить).


[[->-[<<]>]>

Цикл: проверьте, f_nстрого ли меньше pow.

Truthy:

[[-]<<<<<<<[->>[-<+>>+<]>[-<+>]<<<]<[->+>>>>>+<<<<<<]>[-<+>]>[-<+>]>[->>[-<+<<+>>>]<[->+<]<]>+>[-]>>+>]

Обнулить мусор. Затем добавьте num* catк sum. Далее, загрузите следующий ряд Фибоначчи (= f_(n-1), если он не существует, цикл выхода) и установить catв cat* pow. Подготовьтесь к следующему циклу (обнулите больше мусора, сдвиньте область на один).

Falsey:

<<<<<[[->++>+>++<<<]>[-<+>]<<]

Установите powна 2 * pow, восстановить num.

]

Повторяйте до тех пор, пока не останется число Фибоначчи.


>[-]<<<[-]<<[-]<<->[>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>>>]<+[->++++++[-<++++++++>]<.<<<+]

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


7

Шелуха , 7 байт

ḋṁḋ↑Θİf

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

объяснение

ḋṁḋ↑Θİf                              4
     İf    The Fibonacci numbers     [1,1,2,3,5,8..]
    Θ      Prepends 0                [0,1,1,2,3,5..]
   ↑     Take n elements from list   [0,1,1,2]
  ḋ        Convert to binary digits  [[0],[1],[1],[1,0]]
 ṁ       Map function then concat    [0,1,1,1,0]
ḋ        Convert from base 2         14

Добро пожаловать в PPCG! :)
DJMcMayhem


4

Pyth, 22 байта

JU2VQ=+Js>2J)is.BM<JQ2

Попробуй здесь

объяснение

JU2VQ=+Js>2J)is.BM<JQ2
JU2                       Set J = [0, 1].
   VQ       )             <Input> times...
     =+Js>2J              ... add the last 2 elements of J and put that in J.
                  <JQ     Take the first <input> elements...
               .BM        ... convert each to binary...
              s           ... concatenate them...
             i       2    ... and convert back to decimal.

3

Perl 6 , 38 байт

{:2([~] (0,1,*+*...*)[^$_]>>.base(2))}

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


1
Обратите внимание, что это начинает становиться заметно медленнее с входными данными выше 200. Требуется около 8 секунд, чтобы сгенерировать выходные данные с входным сигналом 1000. (20 секунд, если вы включаете его печать)
Брэд Гилберт b2gills



2

J, 36 байт

3 :'#.;<@#:"0]2}.(,{:+_2&{)^:y _1 1'

Объяснение:

3 :'#.;<@#:"0]2}.(,{:+_2&{)^:y _1 1' | Explicit function
                 (,{:+_2&{)^:y _1 1  | Make n fibonacci numbers, with _1 1 leading
              2}.                    | Drop the _1 1
       <@#:"0]                       | Convert each item to binary and box
      ;                              | Unbox and join
    #.                               | Convert back from binary

2

x86, 37 22 21 байт

Изменения

  • -13 с помощью bsr. Спасибо, Питер Кордес!
  • -2 путем обнуления регистров сmul .

  • -1, используя цикл while вместо loopи push/ pop ecx(кредит Питера Кордеса).

Вход в edi, выход в edx.

.section .text
.globl main
main:
        mov     $5, %edi            # n = 5

start:
        dec     %edi                # Adjust loop count
        xor     %ebx, %ebx          # b = 0
        mul     %ebx                # a = result = 0
        inc     %ebx                # b = 1

fib:
        add     %ebx, %eax          # a += b
        xchg    %eax, %ebx          # swap a,b
        bsr     %eax, %ecx          # c = (bits of a) - 1
        inc     %ecx                # c += 1
        sal     %cl, %edx           # result >>= c
        add     %eax, %edx          # result += a

        dec     %edi                # n--; do while(n)
        jnz     fib 

        ret

Objdump:

00000005 <start>:
   5:   4f                      dec    %edi
   6:   31 db                   xor    %ebx,%ebx
   8:   f7 e3                   mul    %ebx
   a:   43                      inc    %ebx

0000000b <fib>:
   b:   01 d8                   add    %ebx,%eax
   d:   93                      xchg   %eax,%ebx
   e:   0f bd c8                bsr    %eax,%ecx
  11:   41                      inc    %ecx
  12:   d3 e2                   shl    %cl,%edx
  14:   01 c2                   add    %eax,%edx
  16:   4f                      dec    %edi
  17:   75 f2                   jne    b <fib>
  19:   c3                      ret    

1
Используйте leaдля сдвига и добавления в fib2. Кроме того, извлечение каждого бита по одному не требуется. Используйте, bsr %eax, %ecxчтобы найти количество бит в двоичном представлении, и используйте сдвиг на CL / или для слияния, как это делает ответ Денниса на Python.
Питер Кордес

1
Вы нуждаетесь clв счетчиках сдвига, поэтому возьмите свой счетчик циклов в другом регистре (например %edi) и используйте его dec %edi / jnz(3 байта в 32-битном коде, 4 байта в 64-битном). В 32-битном коде это спасает всего 1 байт от сброса push / pop ecx. Не попадайтесь в ловушку использования, loopкогда это усложняет, а не облегчает проблему. (Соглашение о вызовах уже настроено, затуманивается %ebx, поэтому не вызывайте свою функцию main) Вы можете вернуться в EAX, все еще используя преимущества 1-байта xchg, нет необходимости быть нестандартным, если вам это не нужно.
Питер Кордес

1
Вы можете заменить дополнительный inc %ecxсчетчик сдвига на дополнительный сдвиг влево по мере добавления, используя lea (%eax, %edx, 2), %edx. Нейтрально в байтах для 32-разрядных, сохраняет один для x86-64. Но сохраняет инструкцию.
Питер Кордес

1
Каждый раз, когда я в конечном итоге использую loopв коде гольф, я чувствую себя грязным. Ну, не совсем, но разочарован тем, что я не смог найти столь же маленькую реализацию, которая избежала бы такой медленной инструкции; вне кода гольф, loopэто одна из моих любимых мозолей . Я хотел бы, чтобы это было быстро на современных процессорах, потому что это было бы очень хорошо для циклов с расширенной точностью без частичных задержек с флагами, но это не так, и их следует рассматривать только как скрытую инструкцию по оптимизации размера, которая замедляет ваш код.
Питер Кордес

1
Во всяком случае, хорошая работа. Кроме push / pop / loop -> dec / jnz, я не вижу никакой экономии, только ускорение LEA, которое нейтрально по размеру кода. Я всегда задавался вопросом, был ли когда-нибудь реальный вариант использования xor/ multrick для обнуления трех регистров (вам когда-нибудь нужно столько нулей?), Но использование этого как части создания a 1делает его более разумным.
Питер Кордес


2

Haskell , 89 76 75 байт

f=0:scanl(+)1f
foldr1(\x y->y+x*2*2^floor(logBase 2.read.show$y)).(`take`f)

Безголовая версия:

import Data.Bits

fib = 0:scanl (+) 1 fib

catInt :: Integer -> Integer -> Integer
catInt x y = x' + y where
    position = floor $ succ $ logBase 2 $ realToFrac y
    x' = shift x position

answer :: Integer -> Integer
answer n = foldr1 catInt fib' where
    fib' = take n fib

1
Добро пожаловать в PPCG и Haskell в гольф в частности! Более короткий способ генерировать бесконечный список чисел Фибоначчи f=0:scanl(+)1f(взят отсюда ). Функции могут быть анонимными, поэтому вы можете отбросить ведущие g=, см. Наше Руководство по правилам ггольфинга в Haskell .
Лайкони

Благодарность! Это компенсирует некоторые более длинные используемые функции. Я потратил некоторое время, пытаясь найти способ реализовать сдвиг битов более кратким способом, но потерпел неудачу.
user9549915

Вы можете заменить $realToFrac yс .read.show$yодного байта
H.PWiz


1

APL + WIN, 55 байт

Запрашивает ввод целого числа на экране.

v←b←0 1⋄⍎∊(⎕-2)⍴⊂'v←v,c←+/¯2↑v⋄b←b,((1+⌊2⍟c)⍴2)⊤c⋄'⋄2⊥b

Максимальная целочисленная точность APL + WIN равна 17, а целочисленный предел составляет порядка 10E300, поэтому максимальное входное число равно 55, и в результате получается: 1,2492739026634838E300



1

Желе , 6 байт

ḶÆḞBFḄ

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

owered диапазон -> п - й ÆḞibonacci номер -> от дес до BИнары -> Flatten -> от Инары в десятичную


Не понимал этот язык, но я думал, что вывод не всегда правильный. Например, ввод, 10и вы получите 16024033463, это неверно (правильный ответ 250375522).
Гоян Цинь



1

MATL , 21 байт

0li:"yy+]xx&h"@B]&hXB

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

объяснение

0l        % Push 0, then 1 (initial terms of the Fibonacci sequence)
i:"       % Do n times, where n is the input
  yy+     %   Duplicate top two numbers and push their sum
  ]       % End
xx        % Delete the last two results. The stack now contains the
          % first n Fibonacci numbers, starting at 0
&h        % Concatenate all numbers into a row vector
"         % For each
  @       %   Push current number
  B       %   Convert to binary. Gives a vector of 0 and 1
]         % End
&h        % Concatenate all vectors into a row vector
XB        % Convert from binary to decimal. Implicitly display

1

J , 25 байт

2(#.;)<@#:@(1#.<:!|.)\@i.

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

объяснение

2(#.;)<@#:@(1#.<:!|.)\@i.  Input: n
                       i.  Range [0, n)
                     \@    For each prefix
                  |.         Reverse
                 !           Binomial coefficient (vectorized)
               <:            Decrement
            1#.              Sum
        #:                   Convert to binary
      <                      Box
    ;                        Link. Join the contents in each box
2 #.                         Convert to decimal from base 2



1

PHP, 124 байта

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

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

Я нашел подход «округления» действительно интересным, и профессор недавно показал мне это.

Код

function f($n,$i=0,$b=''){ if($n>$i){$b.=
decbin(round(pow((sqrt(5)+1)/2,$i)/sqrt(5)));f($n,$i+1,$b);}else{echo bindec($b);}}

объяснение

function f($n,$i=0,$b=''){           #the function starts with $i=0, our nth-fib number
if($n>$i){                           #it stops once $n (the input) = the nth-fib
    $b.=decbin(                      #decbin returns an integer as bin, concatenates
        round(pow((sqrt(5)+1)/2,$i)/sqrt(5))    
                                       #the formula, basically roundign the expression
        );                           #it returns the (in this case) $i-th fib-number   
    f($n,$i+1,$b);                   #function is called again for the next index
}else{                               #and the current string for fibonacci

    echo bindec($b);                 #"echo" the result, bindec returns the base 10
                                     #value of a base 2 number
}
}

Также проверьте эту запись в стеке, лучший ответ относится к той же статье в Википедии.


Интересный способ сделать это!
Натан Вуд



1

Pyth, 27 байт

JU2V-Q2=aJ+eJ@J_2)is.BM<JQ2

Тестирование

Перевод Python 3:
Q=eval(input())
J=list(range(2))
for i in range(Q-2):
    J.append(J[-1]+J[-2])
print(int(''.join(map("{0:b}".format,J[:Q])),2))

37 байт

J[Z1)W<lJQ=aJ+eJ@J_2)Ig1QZ.?ijkm.BdJ2

Тестирование

Перевод Python 3:
Q=eval(input())
J=[0,1]
while len(J)<Q:
    J.append(J[-1]+J[-2])
if 1>=Q:
    print(0)
else:
    print(int(''.join(map("{0:b}".format,J)),2))



0

Йотлин , 59 байт

g(l(0,1)){l(a.sum(),a[0])}.take(this).j(""){a[0].s(2)}.i(2)

Тестовая программа

data class Test(val input: Int, val output: Long)

val tests = listOf(
    Test(1, 0),
    Test(2, 1),
    Test(3, 3),
    Test(4, 14),
    Test(5, 59),
    Test(6, 477),
    Test(7, 7640),
    Test(8, 122253),
    Test(9, 3912117),
    Test(10, 250375522)
)
fun Int.r() = g(l(0,1)){l(a.sum(),a[0])}.take(this).j(""){a[0].s(2)}.i(2)

fun main(args: Array<String>) {
    for (r in tests) {
        println("${r.input.r()} vs ${r.output}")
    }
}

Он поддерживает до 10, изменяя .i(2)для .toLong(2)будет поддерживать до 14 , если это необходимо


0

Python 2, 88 байт

def f(n):
 a,b,r=0,1,"0"
 for _ in range(n-1):a,b=b,a+b;r+=bin(a)[2:]
 print int(r,2)

0

R , 244 180 179 байт

i=ifelse;g=function(n)i(n<3,1,g(n-1)+g(n-2))
a=scan(,"");i(a==1,0,sum(2^(which(rev(unlist(sapply(g(2:a-1),function(x)(y=rev(as.numeric(intToBits(x))))[which(!!y)[1]:32]))>0))-1)))

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

Сохранение некоторых байтов путем объединения числовых векторов, а не строк. Кровавый особый случай для 0!


Функции приемлемы. Кроме того, гораздо эффективнее сместить результат влево на количество бит, чем использовать числовые векторы. Смотрите мой или ответ Дениса на питона. Это дает дополнительное преимущество при обработке случая 0.
qwr

codegolf.stackexchange.com/questions/4024/tips-for-golfing-in-r R Гольф - это слишком много для меня: /
qwr

@qwr Ответ не является функцией; Я создаю вспомогательную функцию, потому что она должна быть sapplyпреобразована в вектор из-за того, что она рекурсивная. Это не может быть все заключено в одну строку. Как видите, программа запрашивает ввод пользователя, а затем возвращает ответ. Один байт можно сохранить, создав ярлык для ifelse. И ... мы можем удалить ,""из scan, да.
Андрей Костырка,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.