Перетворити числа у двійкові ... але вам також дозволяється використовувати двійки


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? man Я такий noob
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

k, 21 байт

Використовується той же метод, що і у відповіді Гольфскрипта Пітера Тейлора

{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.