Преобразуйте числа в двоичные числа ... но вы также можете использовать двойки


20

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

правила

  • Код должен быть только функцией / методом, а не полной программой
  • Ввод - это целое число, переданное в качестве единственного параметра функции
  • Выходные данные - все допустимые изменения входного числа, преобразованного в двоичную запись, но с двойным
  • Выходные данные - это возвращаемое значение функции, но они могут быть в любом удобном для вас формате, если они очевидны (например, 3 дюйма, 3 строки, строка с разделителями-запятыми / пробелами, массив значений и т. Д.), Порядок не важен
  • В том маловероятном случае, если язык содержит встроенную функцию для достижения результата, он запрещен
  • Самый короткий код в байтах - победитель

Пояснения к выводу

Например, если вы передали число 9, вы можете преобразовать его в двоичное число как 1001, но если вы разрешите 2s в каждой позиции, вы также можете записать его как 201(т.е. 2*4 + 0*2 + 1*1) или 121(т.е. 1*4 + 2*2 + 1*1), как показано в этой таблице:

+----+----+----+----+
| 8s | 4s | 2s | 1s |
+----+----+----+----+
|  1 |  0 |  0 |  1 |
|  0 |  2 |  0 |  1 |
|  0 |  1 |  2 |  1 |
+----+----+----+----+

Поэтому, если она пройдена 9, ваша функция должна будет вернуть три числа 1001, 201и 121.

Формат и порядок не имеют значения, так долго , как это очевидно (то есть [121,201,1001], "0201 0121 1001", ("1001","121","201")являются действительными результаты , когда дается ввод 9).

Примеры

  • 2 => 10, 2
  • 9 => 1001, 201, 121
  • 10 => 1010, 210, 202, 1002, 122
  • 23 => 2111, 10111
  • 37 => 100101, 20101, 100021, 20021, 12101, 12021, 11221


1
Два? В двоичном виде? Это квантовые вычисления?
Мэтью Ро

Ответы:


10

GolfScript (25 байт) / CJam ( 19 17 байт)

GolfScript:

{:^.*,{3base}%{2base^=},}

Это создает анонимную функцию (см. Мета-обсуждение о допустимости анонимных функций ).

Онлайн демо

Прямой перевод на CJam (спасибо Мартину Бюттнеру за то, что он побрил пару персонажей)

{:X_*,3fb{2bX=},}

рассечение

{             # Function boilerplate
  :^          # Store parameter as variable ^
  .*          # Square parameter - see detailed explanation below
  ,{3base}%   # Produce an array of 0 to ^*^-1 in ternary
  {2base^=},  # Filter to those which evaluate to ^ in binary
}

Причина операции возведения в квадрат состоит в том, что нам нужно выполнить итерацию до максимально возможного значения, троичное представление которого, интерпретируемое в двоичном формате, равно ^. Поскольку 2 = 10«нормальное» двоичное представление ^является тем, которое имеет значение. Если мы конвертируем это в троичное, мы обнаружим, что «худшие» случаи - это степени 2. Оптимальным подходом было бы привести аргумент к силе ln 3/ln 2 ~= 1.585, но квадрат намного короче.


Бьюсь об заклад, перевод CJam будет намного меньше.
Оптимизатор

1
@Optimizer вперед ;-)
Джон Дворжак

GolfScript? человек, я такой нуб
pythonian29033

8

Python 2 (59 байт)

S=lambda n,B="":[B][n:]or~n%2*S(n/2-1,"2"+B)+S(n/2,`n&1`+B)

(Большое спасибо @grc, @xnor и @PeterTaylor за помощь в чате)

Простая рекурсия, вызов с S(23)или подобное.

объяснение

Общая идея заключается в том, что если nдвоичное разложение заканчивается на a 1, то любое псевдобинарное («двоичное, но с двойками») расширение также должно заканчиваться на a 1. В противном случае это может закончиться 0или 2.

Следовательно, мы смотрим на последний бит n, делим и разветвляем соответственно.

рассечение

S=lambda n,B="":           # Lambda expression
[B][n:]or                  # Short circuit, return [B] if n==0 else what follows
~n%2*                      # Keep next list result if n is even else turn into []
S(n/2-1,"2"+B)             # Add a "2" to B, recurse
+
S(n/2,`n&1`+B)             # Add "0" or "1" to B depending on n's last bit, recurse

Переменные:

  • n: Число, которое мы хотим найти псевдобинарные разложения
  • B: Псевдобинарная строка строится справа налево

5

Bash + coreutils, 77

f()(seq `dc -e2o$1p`|sed '/[3-9]/d;s/.*/&n9P2i&pAi/'|dc|grep -Po ".*(?= $1)")

(Это TABсимвол в выражении grep.)

Это немного изгибает это правило:

«В том маловероятном случае, когда язык содержит встроенную функцию для достижения результата, это запрещено»

Оказывается, это dcимеет обратную сторону того, что нам нужно встроить. Например, если мы установим для входной базы значение 2 и введем двоичное число с двойками, оно будет правильно проанализировано. (Точно так же, если режим ввода - база 10, AF анализируются как десятичные "цифры" 10-15).

seqсоздает список всех десятичных чисел вплоть до стандартного двоичного представления n, анализируемого как десятичное число. Затем все числа, которые содержат что-либо кроме {0,1,2}, отфильтровываются. Затем dcанализирует оставшиеся числа как двоичные, чтобы увидеть, какие из них вернутся к n.

Функции Bash могут «возвращать» только скалярные целые числа 0-255. Так что я позволю себе распечатать список в STDOUT как мой способ «возвращения». Это идиоматично для сценариев оболочки.

Выход:

$ f 2
2   
10  
$ f 9
121 
201 
1001    
$

4

Хаскелл, 82

t n=[dropWhile(==0)s|s<-mapM(\_->[0..2])[0..n],n==sum[2^(n-i)*v|(i,v)<-zip[0..]s]]

это просто перебор. это очень неэффективно, потому что ожидается, что он сократит до 3 ^ n возможностей.


3

Желе , 10 байт, языковые проблемы

ṗ@3Ḷ¤Ḅ=¥Ðf

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

Непрерывное решение до числа гипербитов, равного входному значению (этот формат известен как «гипербинарный»). Таким образом, это невероятно неэффективно, работает в O (3 n ).

объяснение

ṗ@3Ḷ¤Ḅ=¥Ðf
ṗ@            Construct all lists with the given length, and elements taken from
  3Ḷ¤         the list [0,1,2]
        Ðf    then take only those elements which
     Ḅ=¥      when interpreted as binary, equal {the original number}

2

PHP, 138 байт

function p($v,$i=0,$r=""){global$a;if($v==0)$a[]=$r?:0;elseif($v>0)for(;$l<3;)p($v-2**$i*$l,$i+1,+$l++.$r);}p($argv[1]);echo join(",",$a);

Сломать

function p($v,$i=0,$r=""){
    global$a;
    if($v==0)$a[]=$r?:0;  # fill result array
    elseif($v>0) # make permutations
        for(;$l<3;)
            p($v-2**$i*$l,$i+1,+$l++.$r); #recursive
}
p($argv[1]);
echo join(",",$a); # Output

1

C ++, 159 байт

void c(int x,string r){int i,t=0,s=r.size();if(s<8){if(r[0]>48){for(i=0;i<s;i++)t+=(r[s-i-1]-48)*1<<i;if(t==x)cout<<r<<" ";}for(char n=48;n<51;n++)c(x,r+n);}}

Проверьте это здесь


1

к, 21 байт

Использует тот же метод, что и в ответе Golfscript Питера Тейлора

{X@&x=2/:'X:3\:'!x*x}

Примеры:

k) {X@&x=2/:'X:3\:'!x*x}9
(1 2 1;2 0 1;1 0 0 1)
k) {X@&x=2/:'X:3\:'!x*x}10
(1 2 2;2 0 2;2 1 0;1 0 0 2;1 0 1 0)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.