Двоичное Двоичное Расширение

9

Обычно мы разбиваем число на двоичные числа, присваивая ему степени 2 с коэффициентом 0или 1для каждого члена:

25 = 1*16 + 1*8 + 0*4 + 0*2 + 1*1

Выбор 0и 1есть ... не очень бинарный. Мы выполним истинное двоичное расширение, расширяясь степенями 2, но с коэффициентом 1или -1вместо:

25 = 1*16 + 1*8 + 1*4 - 1*2 - 1*1

Теперь это выглядит бинарным.

Учитывая любое положительное число, должно быть тривиально видеть, что:

  • Каждое нечетное число имеет бесконечно много истинных двоичных разложений
  • Каждое четное число не имеет истинных двоичных разложений

Следовательно, для того, чтобы истинное двоичное разложение было правильно определено, мы требуем, чтобы разложение было наименьшим , то есть с самой короткой длиной.


При наличии любого положительного, нечетного целого числа nверните его истинное двоичное расширение от старшей к младшей (или в обратном порядке).

Правила:

  • Как это , вы должны стремиться сделать это как можно быстрее. Встроенные разрешены.
  • Любые выходные данные, которые могут представлять и перечислять коэффициенты, являются приемлемыми: массив, строка коэффициентов с разделителями и т.д ...
  • Применяются стандартные лазейки для игры в гольф.
  • Ваша программа должна работать для значений в пределах стандартного целочисленного размера вашего языка.

Тестовые случаи

25 -> [1,1,1,-1,-1]
47 -> [1,1,-1,1,1,1]
1 -> [1]
3 -> [1,1]
1234567 -> [1,1,-1,-1,1,-1,1,1,-1,1,-1,1,1,-1,1,-1,-1,-1,-1,1,1]
вуаль
источник
Связанные, но совсем другие.
Джузеппе
4
Простой алгоритм: конвертировать в базу 2, заменить 0 на -1, поставить LSD вперед.
Джозия Уинслоу
Вуаль: я не объяснял отрицательные голоса, я просто обрисовывал алгоритм для людей, у которых есть команды преобразования базы на их языке.
Джозия Уинслоу
Поскольку вы так сильно хотите быть по-настоящему двоичными, можем ли мы вернуть значение в виде упакованных битов с обычным значением-местом, но с новой интерпретацией двух состояний? то есть электрически, это просто высокое или низкое напряжение (или что-то еще), и я не виноват, что стандартные отладчики печатают 0вместо состояния -1низкого напряжения. Получатель битов знает, что они имеют в виду. (Это все еще нетривиальное упражнение по манипуляции с битами, поскольку право поворота работает только в том случае, если оно имеет 32 значащих бита. Например, для 5-битного числа требуется ширина поворота 5).
Питер Кордес
Нужно ли выводить разделители? Является 111-1-1действительным выходом для 25?
Оливер

Ответы:

7

Japt , 6 байт

¤é r0J

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

Объяснение:

¤é r0J  // Test input:                  25
¤       // Binary the input:            11001
 é      // Rotate 1 chars to the right: 11100
   r0J  // Replace 0s with -1:          111-1-1
Оливер
источник
1
Ах, вращение; что почему она не работает для меня.
Лохматый
2
Поворот ??? dagnabbit.
Джузеппе
3

Pyth ,  12  11 байтов

|R_1.>jQ2 1

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


Как?

| R_1.> JQ2 1 Полная программа.

      jQ2 Преобразование ввода в двоичный список.
     .> 1 Циклически поворачивайте список выше на 1 место справа.
| R_1 Заменить 0 на -1.
               Неявный вывод.

Прежде всего, мы замечаем, что задача состоит в том, чтобы просто «заменить 0s в двоичной записи на -1s и сдвинуть вправо на 1 место». - Это именно то, что мы должны сделать! Двоичное преобразование дает нам список 0s и 1s. Все , что мы должны сделать здесь , чтобы найти golfy способ преобразовать 0в -1. Побитовый оператор |(побитовое ИЛИ) - наш друг. Карта над двоичным представлением сдвинута на |и -1. Если текущее число есть 0, оно конвертируется в -1.

Мистер Xcoder
источник
Я не думаю, что есть лучший способ. ;)
Джозия Уинслоу
@JosiahWinslow я делаю ... Пытаюсь найти это
мистер Xcoder
Хм? Алгоритм кажется оптимальным, возможно, это потому, что я не знаю Пита.
Джозия Уинслоу
@JosiahWinslow Нашел лучший способ. Синтаксический лучший способ, а не алгоритмический лучший способ.
г-н Xcoder
@ Mr.Xcoder А теперь, по крайней мере, для меня это не так.
Эрик Outgolfer
2

Perl 6 , 72 байта

Есть, конечно, лучший способ, но это то, что у меня есть ...

->$a {grep {$a==[+] @^a.reverse Z+< ^∞},[X] (1,-1)xx $a.base(2).chars}

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

Объяснение : Это функция, которая принимает один аргумент ( ->$a). Сначала мы получаем необходимое количество коэффициентов ( $a.base(2).chars= количество символов в представлении базы 2), а затем делаем декартово произведение ( X) из этого числа пар (1,-1). ( [X]Значит: уменьшите следующий список с помощью X.) Таким образом, мы получаем список всех возможных комбинаций 1 и -1. Затем мы фильтруем ( grep) только те списки, которые кодируют данное число $a. Существует только один, поэтому мы получаем список из одного списка с коэффициентами.

Блок grep делает это: принимает свой аргумент как list ( @^a), переворачивает его и упаковывает в бесконечный список, 0,1,2,...используя оператор «сдвиг влево» +<. Застежка-молния прекращается, как только сокращается короткий список (это хорошо для нас!). Затем мы суммируем все результаты и сравниваем его с заданным числом. Нам пришлось использовать, .reverseпотому что ОП требует, чтобы коэффициенты были в порядке от наиболее значимого до наименее значимого.

Ramillies
источник
1

J 11 байт

1-~2*_1|.#:

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

Спасибо @JosiahWinslow за алгоритм.

Есть мысли о том, чтобы сделать конверсию короче? Мои мысли об использовании !.-fit (nvm, это просто меняет допуск конверсии).

Использование {-take длиннее на 1 символ.

_1 1{~_1|.#:
капуста
источник
1

Java 8, 101 байт

n->{String s=n.toString(n,2);return(s.charAt(s.length()-1)+s.replaceAll(".$","")).replace("0","-1");}

Порт ответа @Oliver на Japt , с еще несколькими байтами ..;)

Определенно можно играть в гольф, используя математический подход вместо этого подхода String.

Объяснение:

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

n->{                             // Method with Integer parameter and String return-type
  String s=n.toString(n,2);      //  Convert the Integer to a binary String
  return(s.charAt(s.length()-1)  //  Get the last character of the binary String
    +s.replaceAll(".$","")       //   + everything except the last character
   ).replace("0","-1");          //  Then replace all zeroes with -1, and return the result
}                                // End of method
Кевин Круйссен
источник
1

R , 90 88 46 байт

function(n)c((n%/%2^(0:log2(n))%%2)[-1],1)*2-1

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

Реализует алгоритм Оливера , но возвращает цифры в обратном порядке. Поскольку нам гарантировано, что nэто никогда не является четным, младший значащий бит (первый) всегда 1, поэтому мы удаляем его и добавляем 1конец до конца, чтобы имитировать вращение в R. Спасибо Шегги, за то, что он помог мне исправить математику .

Простое размещение rev( )вызовов функций в нижнем колонтитуле должно возвращать значения в том же порядке.

оригинальный ответ, 88 байт:

function(n,b=2^(0:log2(n)))(m=t(t(expand.grid(rep(list(c(-1,1)),sum(b|1))))))[m%*%b==n,]

Анонимная функция; возвращает значения в обратном порядке с прикрепленными именами столбцов.

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

Объяснение:

function(n){
 b <- 2^(0:log2(n))         # powers of 2 less than n
 m <- expand.grid(rep(list(c(-1,1)),sum(b|1))) # all combinations of -1,1 at each position in b, as data frame
 m <- t(t(m))               # convert to matrix
 idx <- m%*%b==n            # rows where the matrix product is `n`
 m[idx,]                    # return those rows
}
Giuseppe
источник
Я не считаю этот вывод действительным; предложите попросить автора запроса на подтверждение.
Лохматый
@ Шаговый обратный порядок явно разрешен: from the most significant digit to the least significant digit (or in reversed order).следовательно, это должно быть совершенно приемлемо.
Джузеппе
1
Обратный порядок , а не обратные знаки. Значение допустимого вывода для 25, например, будет [1,1,1,-1,-1]или [-1,-1,1,1,1].
Лохматый
1
@ Шэгги, ах, ты прав, я просто ошибся в математике! должно быть 2*bits - 1вместо 1-2*bits. Спасибо.
Джузеппе
0

CJam, 12 байт

Порт моего ответа на Golfscript.

qi2b{_+(}%)\
Джозия Уинслоу
источник
0

Golfscript, 14 13 14 байтов

-1 байт, потому что я забыл %существовать. +1 байт, потому что я также забыл, что ввод - это строка.

~2base{.+(}%)\
Джозия Уинслоу
источник
1
Если вы предполагаете, что входные данные представлены как целое число, вам следует обернуть код, {}чтобы сделать его блоком. Полные программы могут получать входные данные только в виде строк.
Питер Тейлор
Эм ... что? Я имел в виду, что число вводится как целое число, а не строка, содержащая число.
Джозия Уинслоу
В этом случае ваш ответ не является полной программой, и поэтому должен быть «функцией» , а в случае с GolfScript - блоком. Поэтому это {2base{.+(}%\}для 15 байтов. Точно так же ваш ответ CJam.
Питер Тейлор
Это полная программа. Входные данные в Golfscript неявно помещаются в стек в начале программы, а входные данные в CJam указываются перед выполнением и доступны с помощью команды q.
Джозия Уинслоу
Я немного знаком с GolfScript . ( И CJam ). Если вы хотите заявить, что это полная программа, вам нужно добавить к ней префикс ~.
Питер Тейлор