Послідовність Баума-солодкого


21

Послідовність Баума-солодкого (A086747 з поворотом)

Візьміть натуральне ціле число nі надрукуйте цілі числа від 1 до n, для яких послідовність Баума-Солодкого повертає істину. Послідовність Баума-Солодкого повинна повертатися помилково, якщо двійкове представлення числа містить непарне число послідовних нулів в будь-якому місці числа, а правда - в іншому випадку. Для отримання додаткової інформації натисніть посилання. Ось кілька прикладів:

1 -> 1 -> Truthy
2 -> 10 -> Falsy
3 -> 11 -> Truthy
4 -> 100 -> Truthy (Even run of zeros)

Ось наведений приклад n=32

Крок 1: Візуалізація послідовності Baum-Sweet для n=32

1               1 (1)
1 0             0 (2)
11              1 (3)
1 00            1 (4)
1 0 1           0 (5)
11 0            0 (6)
111             1 (7)
1 000           0 (8)
1 00 1          1 (9)
1 0 1 0         0 (10)
1 0 11          0 (11)
11 00           1 (12)
11 0 1          0 (13)
111 0           0 (14)
1111            1 (15)
1 0000          1 (16)
1 000 1         0 (17)
1 00 1 0        0 (18)
1 00 11         1 (19)
1 0 1 00        0 (20)
1 0 1 0 1       0 (21)
1 0 11 0        0 (22)
1 0 111         0 (23)
11 000          0 (24)
11 00 1         1 (25)
11 0 1 0        0 (26)
11 0 11         0 (27)
111 00          1 (28)
111 0 1         0 (29)
1111 0          0 (30)
11111           1 (31)
1 00000         0 (32)

Отже, обчисливши послідовність Баума-Солодкого для n, візьміть числа, які були правдоподібними для послідовності, і збирайте їх для кінцевого результату. Бо n=32ми мали б:

[1, 3, 4, 7, 9, 12, 15, 16, 19, 25, 28, 31]

Як остаточну відповідь.


Це , виграє найкоротший байт.


а) чи важливо друк, чи ми можемо просто повернути рядок або масив? б) чи мають бути результати у порядку зростання?
Ерресен

@Erresen, поки цифри відображаються, я добре з тим, що є найкращим у вашій мові.
Чарівна урва восьминога

2
"Для отримання додаткової інформації натисніть посилання." Ні. Поставте це питання.
кіт

Відповіді:


7

05AB1E , 10 9 байт

Збережено байт завдяки Аднану

ƒNb00¡SP–

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

Пояснення

ƒ          # for N in [0 ... input]
 Nb        # convert N to binary
   00¡     # split at "00"
      S    # convert to list of digits
       P   # product of list
        –  # if 1, print N

Чи ƒпрацює замість >G?
Аднан

1
@Adnan: Так, звичайно. Я не використовував його, щоб уникнути N = 0, але оскільки він містить непарне число нулів, це не має значення. Дурний мене. Дякую :)
Емінья

@Emigna сподівався побачити використаний;).
Чарівна восьминога урна

@carusocomputing: Я вважав це, але, на жаль, я його ніколи не скорочував.
Емінья

8

JavaScript (ES6), 70 68 63 байт

g=n=>n?g(n-1).concat(/0/.test(n.toString(2).split`00`)?[]:n):[]

console.log(g(1000).join(", "))

Трохи цікавіше рекурсивне рішення:

n=>[...Array(n+1).keys()].filter(f=n=>n<2?n:n%4?n&f(n>>1):f(‌​n/4))

67 байт завдяки @Neil.

g - це функція для виклику.


Це цікавий підхід, ви робили це раніше?
Чарівна восьминога урна

@carusocomputing Не ця конкретна послідовність, але я робив такий тип рекурсії кілька разів у минулому. fсхожа на функцію, яку я періодично використовую для підрахунку кількості 1-бітів у числі.
ETHproductions

Не виходить, fколиn=0 ? Крім того, що fповертається лише 0 або 1, ви можете голити два байти за допомогою n&f(n>>1).
Ніл

@Neil "друкувати цілі числа від 1 до n", n = 0це не випадок;).
Чарівна урва восьминога

Я поголив подальший байт від вашого рекурсивного рішення, перейшовши на filter:n=>[...Array(n+1).keys()].filter(f=n=>n<2?n:n%4?n&f(n>>1):f(n/4))
Ніл

4

Python 2, 62 байти

g=lambda n:n*[0]and g(n-1)+[n]['0'in`bin(n)[1:].split('00')`:]

Перевіряє непарні пробіли значень 1 у двійковому представленні, розбиваючи на них 00і перевіряючи, чи залишаються нулі в рядковому поданні результуючого списку. Прикро, двійкові числа починаються з того 0b, що має нуль, який потрібно видалити, щоб уникнути помилкового додатного.

Перерахування проводиться шляхом повторного зменшення вниз.


4

Bash, 58, 46 байт

ЗМІНИ:

  • Замінено до н.е. з постійним струмом (Thx @Digital Травма!)
  • Почніть з 1;

Гольф

seq $1|sed 'h;s/.*/dc -e2o&p/e;s/00//g;/0/d;x'

Тест

>./baum 32
1 
3
4
7 
9
12
15
16
19
25
28
31

Пояснив

оболонки

seq $1 #generate a sequence of integers from 1 to N, one per line
|sed   #process with sed

sed

h                #Save input line to the hold space
s/.*/dc -e2o&p/e #Convert input to binary, with dc
s/00//g          #Remove all successive pairs of 0-es
/0/d             #If there are still some zeroes left
                 #(i.e. there was at least one odd sequence of them)
                 #drop the line, proceed to the next one
x                #Otherwise, exchange the contents of the hold 
                 #and pattern spaces and (implicitly) print

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


3

Пакет, 143 байти

@for /l %%i in (1,1,%1)do @call:c %%i
@exit/b
:c
@set/ai=%1
:l
@if %i%==1 echo %1&exit/b
@set/ar=%i%%%4,i/=4-r%%2*2
@if %r% neq 2 goto l

3

Perl 6 , 40 байт

{grep {.base(2)!~~/10[00]*[1|$]/},1..$_}

Спробуй це

{
  grep            # find all of them
  {
    .base(2)      # where the binary representation
    !~~           # does not match
    /
      10          # 「10」
      [ 00 ]*     # followed by an even number of 「0」s
      [ 1 | $ ]   # either at end or before a 「1」
    /
  }, 1 .. $_      # from one to the input
}

( []використовуються для групування, що не фіксує, з <[]>класами символів)


2

PowerShell , 79 61 байт

1..$args[0]|?{0-notin([convert]::ToString($_,2)-split'1|00')}

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

Сьогодні вранці у мене було натхнення змінити те, як я виконую -splitоперацію, а потім побачити, що це схоже на те, як , як будується відповідь xnor , так що, я думаю, чудові розуми думають однаково?

Ми робимо цикл від 1вводу до вводу $args[0]та використовуємо Where-Objectоператор, щоб витягнути відповідні числа |?{...}. Стаття - це просте булеве значення - ми гарантуємо, що 0це -notinрезультати (...).

Всередині паронів ми позначаємо [convert]::поточне число $_ ToStringз базою 2(тобто перетворюємо його у двійковий рядок). Тоді ми наводимо -splitрядок на регулярному виразі 1|00- це жадібна відповідність і призводить до масиву рядків (наприклад, 100010перетвориться на '','','0','','0'тощо).

Таким чином, якщо кожен запуск 0s у двійковому рядку є парним (значить, регулярний вираз розділив їх на порожні рядки), то результат 0буде -notinрезультатом, тож Whereдодаток є істинним, і вибрано число. Ці цифри залишаються на конвеєрі, і вихід неявний.


2

Python 2 , 67 47 байт

f=lambda n,k=1:n/k*[1]and[k]+f(n,k-~k)+f(n,4*k)

Завдяки @xnor виграв 20 (!) Байт!

Повертає не упорядкований список. Це досить ефективно: введення 100000 займає приблизно 40 мс на TIO.

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


Гарний метод! Я думаю, ви можете зробити базовий випадок як [1][n:]or. Також x-~xдля 2*x+1.
xnor

Це дає дуже чисте рішення, якщо ви замість цього повторите дерево: f=lambda n,k=1:n/k*[1]and[k]+f(n,k-~k)+f(n,4*k)якщо припустити, що вихід може бути в будь-якому порядку.
xnor

@xnor Це божевільно коротко. Спасибі!
Денніс


1

MATL , 12 11 байт

:"@BY'og)?@

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

Пояснення

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

:       % Take input n implicitly. Push range [1 2 ... n]
"       % For each k in [1 2 ... n]
  @     %   Push k
  B     %   Convert to binary
  Y'    %   Run-length encoding. Pushes array of values and array of run-lengths
  o     %   Parity. Gives array that contains 0 for even lengths, 1 for odd
  g)    %   Convert to logical and use index into the array of values
  ?     %   If the result does not contain zeros
    @   %     Push k
        %   End
        % End
        % Implicitly display stack 

Редагувавши питання для уточнення, я подумав, що деякі люди просто натиснуть на OEIS і пітимуть звідти, не читаючи; P. Це те, що я роблю іноді занадто га.
Чарівна урва восьминога

@carusocomputing Так, я завжди читаю занадто швидко :)
Луїс Мендо

1

R, 75 байт

for(i in 1:scan()){x=rle(miscFuncs::bin(i));if(!any(x$l%%2&!x$v))cat(i,"")}

Читає вхід з stdin і використовує binфункцію з miscFuncsпакету для перетворення з десяткового в двійковий вектор. Отже, виконує кодування довжини пробігу, щоб перевірити значення == 0і довжини непарних.


1

Зіставлено , 69 байт

Спробуйте тут!

:>1+[bits{e.b:e b 0#=}chunkby[0 has]filter$sizemap 2%0 eq all]"filter

Або без конкуренції в 67 байт:

:>1+[bits{e.b:e b 0#=}chunkby[0 has]filter$sizemap even all]"filter

І, ще більше, не конкуруючи з 49 байтами:

:>1+[bits rle{k:k 0=}filter values even all]fkeep

Усі приймають дані як TOS і залишають вихід на TOS.

Пояснення

:>1+[...]"filter   input: n
:>                 range from [0, n)
  1+               range from [1, n]
    [...]          a function
         "filter   apply to each cell and filter

Функція:

bits{e.b:e b 0#=}chunkby[0 has]filter$sizemap 2%0 eq all  input: c
bits                                                      convert c to binary
    {e.b:e b 0#=}chunkby                                  split into chunks of contiguous 0s
                        [0 has]filter                     take only chunks with 0s
                                     $sizemap             map each chunk to its size
                                              2%          vectorized modulus 2
                                                0 eq      vectorized equality with 0
                                                     all  all of them are of even lengths

Пояснення неконкурентоспроможних:

Це те саме, що вище, з кількома ключовими відмінностями:

:>1+[bits rle{k:k 0=}filter values even all]fkeep   input: y
          rle                                       run length encode y
             {k:k 0=}filter                         keep keys that = 0
                            values                  get those values
                                            fkeep   like `filter`, but is implemented with
                                                    taking `f` as a boolean mask

Складене виглядає так, що з ним можна було б весело грати!
ElPedro

@ElPedro дякую: D це дійсно так
Conor O'Brien

1

Befunge, 84 51 49 байт

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

<v::\<&1
:_v#:/+2*2!%2:_v#-2%4
:$<@_v#!:-1\+1$<:.

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

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

Якщо модуль 4 не дорівнює 2, нам потрібно продовжити тестування решти бітів, тому ми зміщуємо біти, які вже були протестовані. Це робиться діленням значення, давайте називати його n , до 2+2*!(n%2). Це означає, що якщо перший біт був 1, ми ділимо на 2 (скидаючи цей 1 біт), але якщо це було 0, ми ділимо на 4, тому ми завжди будемо скидати пари нулів.

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


1

Visual Basic (.net 4.5) 163 байти

Перш за все тут відповідь, так що я впевнений, що я щось накрутив. Дайте мені знати, і я виправлю. Чи дозволені навіть лямбди Visual Basic?

Завдяки MamaFunRoll за ідею видалення послідовних нулів

Dim R=Sub(m)System.Console.WriteLine(String.Join(",",System.Linq.Enumerable.Range(1, m).Where(Function(s) Not Convert.ToString(s,2).Replace("00","").Contains(0))))

R (32) виходів

1,3,4,7,9,12,15,16,19,25,28,31

1

Java, 144 130 128 байт

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

Гольф:

static String a(int n){String s="";for(Integer i=0;i++<n;)if(i.toString(i,2).replaceAll("00|1","").isEmpty())s+=i+" ";return s;}

Безголівки:

static String a(int n){
    String s="";                      //Cheaper than using a list/array
    for(Integer i=0;i++<n;)           //Loop n times
        if(i.toString(i,2)            //Convert int to base 2 string
                .replaceAll("00|1","")//Find and remove ones and consecutive zeroes
                .isEmpty())           //If any chars remain, i is truthy
            s+=i+" ";                 //Append i to the storage string
    return s;                         //Return all values
}

Редагувати: мені вдалося зберегти 14 байт, зробивши регулярний вираз 00 | 1 замість 00 та видаливши ".replace (" 1 "," ")" міжAll і isEmpty! "

Редагувати 2: Мені вдалося зберегти 2 байти, зробивши i Integer і посилаючи Integer.toString з i.toString.


@JamesHolderness Дякую за те, що це зрозумів! Я кілька разів помилявся з гольфом і розмахував ним, коли я вперше писав це, так що, мабуть, так воно і прокралося.
Завада

0

Clojure, 103 байти

Я не думаю, що це найкоротший шлях ...

#(remove(fn[v]((set(map(fn[s](mod(count s)2))(re-seq #"0+"(Integer/toString v 2))))1))(range 1(inc %)))

Використовує re-seqдля пошуку послідовних нулів, відображає їх довжину по модулю-2 на a set, відкидає їх, якщо число 1знайдено з набору.


0

Диво , 38 байт

@(!>@=1len iO0Rstr#["00"]bn#0)rng1+1#0

Використання:

(@(!>@=1len iO0Rstr#["00"]bn#0)rng1+1#0) 32

Пояснення

Більш зрозумілі:

@(
  fltr@
    = 1 
      len 
        iO 0 
          Rstr #["00"] 
            bn #0
) rng 1 +1 #0

rng 1 +1 #0: Діапазон від 1 до входу.

fltr@ ...: Діапазон фільтра з наступним предикатом.

bn #0: Перетворити поточний елемент у двійковий. (Це матиме провідну роль 0b).

Rstr #["00"]: Рекурсивно обрізати будь-які події 00в рядку.

len iO 0: Порахуйте кількість 0s у рядку.

=1: Перевірте, чи сума дорівнює 1. Якщо в 0обрізку залишилося лише ліворуч після обрізки 0b, то це повертає справжнє значення; в іншому випадку це повертається помилково.


0

Рубі, 78 69 68 байт

->n{(1..n).select{|m|m.to_s(s=2).split(?1).map{|i|s|=i.size};s&1<1}}

Старіші версії:

->n{(1..n).select{|m|m.to_s(2).split(?1).select{|i|i.size%2>0}[0].!}}
->n{(1..n).select{|m|b=z=0;(m.to_s(2)+?1).each_char{|i|z+=i>?0?b|=z:1};b&1<1}}

0

Математика, 81 байт

Select[Range@#,FreeQ[Union@#+Mod[Length@#,2,1]&/@Split[#~IntegerDigits~2],{1}]&]&

Обчислює для кожного запуску послідовних цифр число: {загальна цифра в цьому пробіті плюс (1, якщо довжина непарна, 2, якщо довжина парна)}; якщо будь-яка з відповідей {1}, то число не в послідовності.


0

Математика, 75 байт

Select[Range@#,And@@EvenQ/@Length/@Cases[Split[#~IntegerDigits~2],{0..}]&]&

#~IntegerDigits~2обчислює список двійкових цифр вводу #. Splitцей список складається в однакові елементи, беруть Casesвідповідність {0..}, беруть Lengthкожен з них, беруть EvenQдовжини, а потім повертають Andрезультати.


1
Один байт економії ви можете взяти з мого рішення:!Or@@OddQ/@...
Мартін Ендер

0

Python 3, 86 82 байт

Робота в гольф ...

lambda n:[x for x in range(1,n+1)if 1-any(i%2for i in map(len,bin(x).split('1')))]

Полез у 4 байти, змінивши bin(x)[2:]на просто bin(x)- це залишається 0bна початку рядка, але я зрозумів, що це фактично не впливає на розрахунки :)


0

Пітон, 142 байти

Це в основному лише для того, щоб займатися гольфом на моєму Python.

def o(n):
 r=0
 for i in bin(n)[2:]:
  if i=='1':
   if r&1:return 0
   r=0
  else:r+=1
 return ~r&1
lambda n:[i for i in range(1,n+1)if o(i)]


0

Рубі, 54 53 48 байт

->n{(1..n).reject{|x|x.to_s(2)=~/10(00)*(1|$)/}}

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

редагувати 1: переключено на відхилення, щоб позбутися заперечення для -1.

редагувати 2: перемкнено matchна =~-5.


0

C # 159 157 155 байт

Збережено 2 х два байти завдяки TuukkaX.

Примітка: друкує вставки у зворотному порядку.

void B(int n){var b=Convert.ToString(n,2);int c=0,i=0;for(;i<b.Length;){if(b[i++]<49)c++;else if(c%2>0)break;}if(c%2<1)Console.WriteLine(n);if(n>1)B(--n);}

Пояснення:

void B(int n)
{
    // convert our int to a binary string
    var b = Convert.ToString(n, 2);

    // set our '0' counter 'c' and our indexer 'i' 
    int c = 0, i = 0;

    // loop over the binary string, without initialisation and afterthought
    for (; i < b.Length;)
    {
        // check for '0' (48 ASCII) and increment i. increment c if true
        if (b[i++] < 49)
            c++;

        // otherwise check if c is odd, and break if it is
        else if (c%2 > 0)
            break;
    }

    // print the int if c is even
    if (c%2 < 1)
        Console.WriteLine(n);

    // recursively call B again with the next number
    if (n > 1)
        B(--n);
}

На перший погляд, c%2==0могло бути c%2<1.
Yytsi

О, зачекайте, це навіть не дійсне подання. Він повинен надрукувати правильні результати від 1 до N.
Yytsi

@TuukkaX, мабуть, неправильно прочитав питання ... переглядаючи відповідь зараз.
Ерресен

@TuukkaX Відредаговано та зараховано
Ерресен

1
b[i++] == '0'може бути b[i++]==48, але оскільки інший можливий символ - "1" (ASCII 49), ви можете просто перевірити, чи є b[i++]<49.
Yytsi

0

Математика, 69 байт

Select[Range@#,FreeQ[#~IntegerDigits~2//.{x___,0,0,y___}:>{x,y},0]&]&

Та ж довжина:

Select[Range@#,#~IntegerString~2~StringDelete~"00"~StringFreeQ~"0"&]&


0

Желе, 15 13 10 байт

зберегли два байти після перегляду інших відповідей, ще 3 байти завдяки Деннісу

Bœṣ0,0Ȧµ€T

Пояснення

Bœṣ0,0Ȧµ€T -Helper link: argument K (integer): ex. 24
B          -Convert K to a list of its binary digits: 24 -> [1,1,0,0,0]
   0,0     -Create a list of two 0's: [0,0]
 œṣ        -Split the binary digits on instances of the sublist: [1,1,0,0,0]-> [[1,1],[0]]
      Ȧ    -Any and All: Check if our list has any falsy values or is empty
       µ   -Take all our previous atoms and wrap them into one monad.
        €  -Map this new monad over a list. Since our input is an integer, this implicitly maps it over the range [1..N] (Like the 'R' atom)
         T -Get the indices of all truthy values (1's)

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