Бінарний до десятковий перетворювач


32

Бінарний до десятковий перетворювач

Наскільки я бачу, у нас немає простої задачі на перетворення двійкових у десяткову.


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

Вам заборонено використовувати будь-які вбудовані функції перетворення базових даних. Цілі до десяткових функцій (наприклад, функція, яка перетворюється 101010на [1, 0, 1, 0, 1, 0]або "101010"), виключаються з цього правила і таким чином дозволені.

Правила:

  • Код повинен підтримувати двійкові числа до максимального числового значення, яке підтримує ваша мова (за замовчуванням)
  • Ви можете вибрати, щоб у двійковому поданні були нульові нулі
  • Десятковий вихід може не мати провідних нулів.
  • Формати введення та виведення необов’язкові, але між цифрами не може бути жодного роздільника. (1,0,1,0,1,0,1,0)не є коректним форматом введення, але і те, 10101010і (["10101010"])є.
    • Ви повинні взяти вхід у "нормальному" напрямку. не 1110є .147

Тестові приклади:

1
1

10
2

101010
42

1101111111010101100101110111001110001000110100110011100000111
2016120520371234567

Ця проблема пов'язана з декількома іншими проблемами, наприклад , це , це і це .



Чи повинен підпис не бути підписаний або він може бути підписаний? Крім того, якщо моя мова автоматично перемикається між 32-бітними та 64-бітовими цілими числами залежно від довжини значення, чи можна підписати вихід в обох діапазонах? Напр. Є два двійкових значення, які перетворяться на десяткові -1( 32 1'sі 64 1's)
молоко

Крім того, чи може виводити плаваючий, чи потрібно це бути цілим числом?
Carcigenicate

@Carcigenicate Це має бути ціле число, але воно може бути будь-якого типу даних. До тих пір, поки у round(x)==xвас все в порядку :) 2.000приймається вихід 10.
Стюі Гріффін

О солодкий. Спасибі.
Carcigenicate

Відповіді:


56

Желе , 5 байт

DḤ+¥/

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

Пояснення

enter image description here

Акторський склад

  • Dє монадою (функція єдиного аргументу): цифри, перетворюючись 1234на [1, 2, 3, 4].

  • це монада, яка подвоює свій єдиний аргумент.

  • + - діада (дві функції аргументу), яка додає її лівий і правий аргументи.

Звідти це стає трохи хитро.

Ось що відбувається під час розбору

  • D, і +читаються. Ланцюжок виглядає так [D, Ḥ, +].

  • Наступні два символи - це квітки , які діють як оператори постфіксу для розбору часу у прочитаних нами посиланнях (функціях).

  • Коли ¥читається, останні два посилання вискакують і замінюються посиланням, яке діє як діада, утворена їх складанням. Тож тепер ланцюжок виглядає так [D, dyad(Ḥ+)].

  • Коли /читається, остання посилання (яка повинна бути діадою) отримує спливання і замінюється монадою, яка складається з цього діада (інтуїтивно: f/бере список, замінює коси в ньому fта оцінює результат.)

  • Кінцевий ланцюг виглядає так [D, fold(dyad(Ḥ+))], два монади.

Ось що відбувається під час виконання

  • Введення (число) неявно зчитується в робоче значення (скажімо, 101010).

  • Dвиконується, замінюючи робоче значення його цифрами ( [1,0,1,0,1,0]).

  • fold(dyad(Ḥ+))виконується, замінюючи робоче значення на 1∗0∗1∗0∗1∗0, де діада Ḥ+.

Отже, що x∗yоцінює?

  • У диадического визначенні, робоча величина спочатку лівий аргумент x.

  • , подвійна монада подвоює це значення. Зараз працює робоча вартість 2x.

  • +, плюс- діаді не вистачає правильного аргументу, тому це гак : особливий синтаксичний зразок, де правильний аргумент цієї діади вводиться +. Це дає 2x + yкінцеву робочу вартість, яка повертається.

Отже, весь вираз оцінюється так:

1∗0∗1∗0∗1∗0 = 2×(2×(2×(2×(2×1+0)+1)+0)+1)+0
            = 32×1 + 16×0 + 8×1 + 4×0 + 2×1 + 1×0
            = 42

10
Ваші пояснення стають все кращими та кращими :-)
Луїс Мендо

2
Хе, я думаю, ви це робите відтепер? Це приголомшливо, +1.
Ерік Атголфер

4
Я думаю, що це перший твір Желе, який я коли-небудь зрозумів. +1!
Синій

Браво. Я насправді розумію, що я спочатку вважав просто безладом наче випадкових персонажів. Чудове пояснення.
свиняча риба

1
@Mark Jelly має власну кодову сторінку, щоб зробити програми виглядними, ага , читабельними, але програми також могли бути просто біст-весняними.
Лінн

20

Пітон 2, 49 37 31 30 Байт

Тепер це займе двійкове число у десятковому поданні, оскільки Python може обробляти довільно великі цілі числа.

b=lambda n:n and n%2+2*b(n/10)

завдяки xnor за збереження байта :)

Найпростіший спосіб зрозуміти, як це працює, побачивши основну формулу перетворення двійкового в десятковий:

= 101010 
= 1*(2^5) + 0*(2^4) + 1*(2^3) + 0*(2^2) + 1*(2^1) + 0*(2^0)
= 1*32 + 0*16 + 1*8 + 0*4 + 1*2 + 0*1
= 42

Це "стандартний" спосіб перетворення. Ви можете розширити третій рядок так:

= ((((1*2 + 0)*2 + 1)*2 + 0)*2 + 1)*2 + 0

І це, по суті, те, що я робив рекурсивний метод.

Альтернативні рішення у мене були:

b=lambda n:n and n%10+2*b(n/10)
b=lambda n:n%10+2*(n and b(n/10))
b=lambda n:0if n<1else n%10+2*b(n/10)
b=lambda n:0**(n/10)or n%10+2*b(n/10)
b=lambda n,o=0:o*(n<'0')or b(n[1:],2*o+int(n[0]))
lambda j:sum(int(b)*2**a for a,b in enumerate(j,1))

6
Можна робити n%5або n%2замість цього n%10.
xnor

@xnor Ах, не впевнений, як я пропустив це! Дякую :)
Каде

12

05AB1E , 6 байт

Код:

$¦v·y+

Для пояснення візьмемо приклад 101010 . Почнемо з числа 1 (яке представлено першою цифрою). Після цього у нас є два випадки:

  • Якщо цифра дорівнює 0 , число помножте на 2.
  • Якщо цифра дорівнює 1 , помножте число на 2 і додайте 1.

Отже, для випадку 101010 обчислюється наступне:

  • 1 01010, почніть з числа 1 .
  • 1 0 1010, помножте на два, у результаті чого виходить 2 .
  • 10 1 010, помножте на два і додайте одне, у результаті чого 5 .
  • 101 0 10 помножте на два, в результаті чого на 10 .
  • 1010 1 0, помножте на два і додайте одне, у результаті чого виходить 21 .
  • 10101 0 , помножте на два, в результаті чого на 42 , що є бажаним результатом.

Пояснення коду:

$         # Push 1 and input
 ¦        # Remove the first character
  v       # For each character (starting with the first)
   ·      #   Multiply the carry number by two
    y+    #   Add the current character (converted automatically to a number)

Використовує кодування CP-1252 . Спробуйте в Інтернеті!


Хороший! (не працює за 0, хоча я щойно помітив)
Emigna

@Emigna Так, на щастя, ваш код повинен працювати лише для позитивних двійкових чисел.
Аднан

Навіть не бачив цієї частини. Дуже приємно тоді :)
Emigna

9

Haskell, 16 111 + 57 = 168 байт

import Data.String
instance IsString[Int]where fromString=map((-48+).fromEnum)
f::[Int]->Int
f=foldl1((+).(2*))

+57 байт для прапорів компіляції -XOverloadedStrings, -XOverlappingInstancesі -XFlexibleInstances.

Завдання має дещо громіздкий формат вводу-виводу , оскільки він сильно залежить від того, як типи даних виражаються у вихідному коді. Моя перша версія (16 байт), а саме

foldl1((+).(2*))

приймає список цілих чисел, наприклад, [1,0,1,0,1,0]і був оголошений недійсним, оскільки ,між елементами є випадкові списки Haskell . Списки самі по собі не заборонені. У своїй новій версії я використовую ту саму функцію, яку тепер називають f, але я перевантажую "Цитувати додані послідовності символів". Функція все ще приймає список цілих чисел, як ви бачите в анотації типу [Int] -> Int, але списки з одноцифровими цілими числами тепер можна записати як "1234", наприклад,

f "101010"

який оцінює до 42. Не пощастило Haskell, оскільки формат рідного списку не відповідає правилам виклику. Btw, f [1,0,1,0,1,0]як і раніше працює.


2
На жаль, список не є коректним вводом.
Джонатан Аллан

@JonathanAllan: Чому? І якщо так, то як він взагалі повинен брати участь? У Haskell рядок - це лише список символів.
німі

Не знаю, чому ... але я поцікавився цим питанням на початку та було зроблено редагування, щоб додати " (1,0,1,0,1,0,1,0)не допустимий формат введення, але і те, 10101010і (["10101010"])є". Крім того, коментар говорить про те, що масив символів є прийнятним, якщо таким чином інтерпретується рядок.
Джонатан Аллан

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

2
Op тут: якщо це можна ввести 10101010, "10101010"або щось подібне , і зробити його роботу , то уявлення є дійсним. Ви можете назвати це рядком, списком, цілим числом чи будь-яким іншим. Введення [1][0][1][0]або [1,0,1,0]це не нормально. В основному, слід було б десь вдарити по купі одиниць і нулів підряд. Це ясно?
Стюі Гріффін

7

Сітківка, 15 байт

Перетворює з двійкового в одинарне, потім унарного до десяткового.

1
01
+`10
011
1

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


Вам заборонено використовувати будь-які вбудовані функції перетворення базових даних. ~ OP
Роман Ґраф

10
@ RomanGräf Немає таких. Я просто описував процес свого рішення.
mbomb007

7

PHP, 44 байти

for(;""<$c=$argv[1][$i++];)$n+=$n+$c;echo$n;

Я міг би присягнути, що раніше бачив це питання. Але добре.

Читає число зліва направо, зміщує ліворуч і додає поточний біт.


7

JavaScript (ES6), 33 31 байт

s=>[...s].map(c=>r+=+c+r,r=0)|r

Редагувати: коротше, але менш солодке: 2 байти збережено завдяки @ETHproductions.


Як це часто буває, .mapвін коротший:s=>[...s].map(c=>+c+r+r,r=0)|r
ETHproductions

@ETHproductions Як ваша функція повертає щось, крім 0?
Ніл

Вибачте, так і повинно бутиs=>[...s].map(c=>r+=+c+r,r=0)|r
ETHproductions

7

Лабіринт , 17 15 байт

-+:
8 +
4_,`)/!

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

Image of the code

Лабіринт - це двовимірна мова, основана на стеках. У лабіринті виконання коду йде шляхом коду, як лабіринт, з пробілами, що виступають як стіни і починаються вгорі ліворуч від самого простору. Потік коду визначається знаком верхньої частини стека. Оскільки стек має неявні нулі внизу, перші чотири інструкції ( -+:+) не мають ефекту.

Петля, що починається на ,

  • , Натисніть значення коду ascii наступного символу вводу до зупинки стека або натисніть -1, якщо EOF.
  • _48 штовхає 48 до вершини стека
  • -Поп у, поп х, поштовх x-y. Попередні вказівки впливають на віднімання 48 із вхідного виходу 0 для "0" та 1 для "1".
  • +Pop y, pop x, push x+y.
  • : Дублюйте верхню частину стека
  • + Ця та попередня інструкція впливають на множення поточного значення на 2

Таким чином, кругла частина коду, по суті, множує поточне число на 2 і додає або 1, або 0 залежно від того, чи було введено символ 1 або 0.

Хвіст

Якщо вершина стека від’ємна (тобто EOF знайдено), код поверне ліворуч на стику (йде у напрямку до крапки з комою).

  • `` `Обв’яжіть верхню частину стека, щоб отримати 1
  • ) Збільшити верхню частину стека, щоб отримати 2
  • /Pop y, pop x, push x / y (ціле ділення). Це призводить до відміни останнього *2з циклу.
  • !Виведіть ціле подання верхньої частини стека. У цей момент програма обертається, тому що потрапила в глухий кут, а потім виходить з помилкою, тому що намагається ділити на нуль.

Дякую @Martin Ender, що врятував мене 2 байти (і навчав мене, як краще думати в Лабіринті).


Замість цього _48-ви можете просто зробити, #%але, на жаль, я не бачу, як це може допомогти підрахунку байтів.
Мартін Ендер

Ви можете зберегти байт за допомогою, `)а не ;_2хоч.
Мартін Ендер

@MartinEnder, я не розумію твій коментар #%. Чи можете ви пояснити, як це працює як заміна для _48-перетворення з ascii в int. Дякую за )пораду. Я зроблю цю зміну.
Роберт Хікман

На той момент у вашій програмі завжди є два значення на стеку, тому #це просто коротко _2. Хоча _2%це не загальний метод перетворення ASCII в ціле число, він працює тут, оскільки вас цікавлять лише перші дві цифри, як можливі введення. Альтернативою може бути _1&(оскільки модуль 2 просто витягує найменш значущий біт).
Мартін Ендер

Ой. Це геніально. Але так, я не впевнений, як використовувати цю заміну ( #%) для скорочення коду в цілому.
Роберт Хікман

6

Мозок-Флак , 46 , 28 байт

([]){{}({}<>({}){})<>([])}<>

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

Багато збережених байтів завдяки @Riley!

Оскільки головний мозок не може приймати двійковий вхід, введення - це список "0" та "1".

Пояснення:

#Push the height of the stack
([])

#While true:
{

 #Pop the height of the stack
 {}

 #Push this top number to (the other stack * 2)
 ({}<>({}){})

 #Toggle back on to the main stack
 <>

 #Push the new height of the stack
 ([])

#endwhile
}

#Toggle back to the other stack, implicitly display.
<>

Любіть пояснення! Настільки важко читати мозковий
флекс

2
^. Я навіть не можу читати власні програми, якщо не залишаю собі декілька коментарів.
Райлі

Ви можете зменшити його до 32 байтів, позбувшись цілого, якщо частина, а для кроку "додати число до іншого стека" просто додайте його до (інший стек) * 2. ([]){({}[()]<({}<>({}){})><>)}<>
Райлі

І ви можете зберегти ще 4, просто натиснувши на початку часу і знову натиснувши висоту в кінці. ([]){{}({}<>({}){})<>([])}<>
Райлі

@ Райлі О боже, це геній. Велике спасибі!
DJMcMayhem

6

Java, 84 79 46 48 байт

  • Версія 3.1

Змінено на long/ 48 байт:

s->{long x=0;for(char c:s)x=c-48l+x*2;return x;}
  • Версія 3.0

Зробив трохи гольфу / 46 байт:

s->{int x=0;for(char c:s)x=c-48+x*2;return x;}
  • Версія 2.0

Завдяки @Geobits! / 79 байт:

s->{int i=Math.pow(2,s.length-1),j=0;for(char c:s){j+=c>48?i:0;i/=2;}return j;}
  • Версія 1.0

84 байти:

s->{for(int i=-1,j=0;++i<s.length;)if(s[i]>48)j+=Math.pow(2,s.length-i+1);return j;}

1
Гадаю, я мав би зробити ітеративне рішення. lulz. хороша робота
Poke

Ваш тип вводу Список <Характер> або Рядок? Якщо це останнє, я не знав, що Java8 може це зробити! Якщо це колишній, що дозволено викликом?
Пік

sповинно бути char[]. Я сподіваюся, що це дозволено ...
Роман Греф

Який тут тип повернення? Я думаю, що це повинно бути довгим, оскільки "Код повинен підтримувати двійкові числа до найвищого числового значення, яке підтримує ваша мова" за ОП, але для менших значень я думаю, що він повертає int
Poke

1
Можливо, добре за типом вводу для цього . Можливо, хочете взяти 2-байтовий хіт для виводу imo
Poke

4

Befunge-98, 12 байт

2j@.~2%\2*+

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

Читає по одному знаку за один раз від введення, перетворює його на 0 або 1, приймаючи його значення за модулем 2 (0 - char (48), 1 - char (49)), потім використовує звичайний алгоритм подвоєння поточного значення та додавання нова цифра кожного разу.

Бонус: Це працює з будь-яким видом рядка введення, я вже деякий час намагаюся знайти будь-яку смішну комбінацію вводу-виводу, але мені нічого не вдалося створити (на жаль, "відповідь" = 46). Ти можеш?


ЛОЛ. Я грав у ту саму гру зі своєю відповіддю. Найцікавіше число, яке я міг генерувати, було 666 .
Джеймс Холдернесс

Хороший! Мені не вдалося знайти нічого підходящого для 666: D Було б набагато простіше, якби капіталізація вплинула на значення ...
Лев

@James Holderness - Я робив те саме, і я лише знайшов "theleapyear", щоб повернути 366, ваш справді хороший.
Тіл пелікан

4

Javascript (ES7) 41 40 36 байт

f=([c,...b])=>c?c*2**b.length+f(b):0

приймає рядок як вхідний

Поголив байт завдяки ETHproductions

f=([c,...b])=>c?c*2**b.length+f(b):0
document.write([
    f('101010'),
    f('11010'),
    f('10111111110'),
    f('1011110010110'),
].join("<br>"))


1
Асоціативність справа-наліво **дивна, але приємна робота, використовуючи її тут. 1<<b.lengthзробить те саме, але це вимагатиме дужок, щоб вони не були розібрані (c*1)<<(b.length+...). Я думаю , що ви можете зберегти байти, замінюючи b[0]з b+b( дивіться тут ).
ETHproductions

4

C # 6, 85 37 36 байт

long b(long n)=>n>0?n%2+2*b(n/10):0;
  • Дякуємо Kade за збереження 41 байта!
  • Змінившись на C # 6, збережено ще 7 байт.

Може, це могло б дати певне натхнення? ;)
Каде

@Kade Це, дякую! Я дивився на відповідь Python, яка використовує ту саму техніку в той самий момент, коли ви пов’язали це: DI може стати ще коротшим із C # 6.
Yytsi


3

С, 53

v(char*s){int v=0,c;while(c=*s++)v+=v+c-48;return v;}

Те саме, що і моя відповідь на javascript

Тест Ideone


Ви можете зберегти 4 байти, оголосивши vі cяк глобальні змінні (хоча вам потрібно змінити ім’я v, оскільки це вже ім'я функції) так:w=0;c;v(char*s){while(c=*s++)w+=w+c-48;return w;}
Steadybox

@Steadybox це могло бути, w,c;але я не хочу використовувати глобали, коли відповідь є функцією (навіть у коді-гольф)
edc65

@Steadybox Глобали за замовчуванням також до 0, так що ви можете скинути =0.
algmyr

3

Perl, 25 байт

-3 байти завдяки @Dom Hastings

24 байти коду + 1 байт для -pпрапора.

$\|=$&<<$v++while s/.$//

Щоб запустити його:

perl -pe '$\|=$&<<$v++while s/.$//' <<< 101010

Пояснення:

$\|=$&<<$v++  # Note that: we use $\ to store the result
              # at first $v=0, and each time it's incremented by one
              # $& contains the current bit (matched with the regex, see bellow)
              # So this operation sets a $v-th bit of $\ to the value of the $v-th bit of the input
while         # keep doing this while...
s/.$//        #  ... there is a character at the end of the string, which we remove.
         # $\ is implicitly printed thanks to -p flag

3

Пуш , 10 байт

Приймає вхідний сигнал у вигляді списку 0/1 в командному рядку: $ pushy binary.pshy 1,0,1,0,1,0.

L:vK2*;OS#

Алгоритм дійсно показує красу наявності другого стека:

            \ Implicit: Input on stack
L:    ;     \ len(input) times do:
  v         \   Push last number to auxiliary stack
   K2*      \   Double all items
       OS#  \ Output sum of auxiliary stack

Цей метод працює, тому що стек буде вдвічі stack length - nперевищуватися до досягнення числа n, який потім скидається у другий стек для подальшого. Ось як виглядає процес введення даних101010 :

1: [1,0,1,0,1,0]
2: []

1: [2,0,2,0,2]
2: [0]

1: [4,0,4,0]
2: [2]

1: [8,0,8]
2: [2,0]

1: [16,0]
2: [2,0,8]

1: [32]
2: [2,0,8,0]

1: []
2: [2,0,8,0,32]

2 + 8 + 32 -> 42

3

Матлаб, 30 байт

@(x)sum(2.^find(flip(x)-48)/2)

Останній тестовий випадок має помилки округлення (через double), тому якщо вам потрібна повна точність:

@(x)sum(2.^uint64(find(flip(x)-48))/2,'native')

з 47 байтами.


Я не можу перевірити це, але я вважаю @(x)sum(2.^(find(flip(x)-48)-1)), що дасть правильний результат для всіх випадків на 32 байти. flipпрацює як fliplrби xодновимірний.
Стюі Гріффін

Приємне рішення! Я також зіткнувся з помилкою округлення, дякую за виправлення. Який формат x? Виклик flip або fliplr на номер просто повертає це число.
MattWH

x - двійковий рядок, тому називайте його f=@(x)..; f('1111001010').
Йонас

3

Сітківка , 12 байт

Кількість байтів передбачає кодування ISO 8859-1.

+%`\B
¶$`:
1

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

Альтернативне рішення:

+1`\B
:$`:
1

Пояснення

Це, мабуть, буде простіше пояснити на основі моєї старої, менш гольф-версії, а потім показати, як я її скоротив. Я використовував для перетворення двійкового в десятковий так:

^
,
+`,(.)
$`$1,
1

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

Як ми це робимо? Загалом, для перетворення зі списку бітів у ціле число ми ініціалізуємо результат на, 0а потім проходимо через біти від найбільшого до найменш значущого, подвоюємо значення, яке ми вже маємо, і додаємо поточний біт. Наприклад, якщо двійкове число є 1011, ми б дійсно обчислили:

(((0 * 2 + 1) * 2 + 0) * 2 + 1) * 2 + 1 = 11
           ^        ^        ^        ^

Де я позначив окремі шматочки для наочності.

Хитрість робити це в уніру полягає в тому, що подвоєння просто означає повторення числа і b) оскільки ми підраховуємо 1s в кінці, нам навіть не потрібно розрізняти 0s і 1s в процесі. Це стане зрозумілішим через секунду.

Програма робить те, що вона спочатку додає коду до початку як маркер для того, яку частину входу ми вже обробили:

^
,

Зліва від маркера, ми отримаємо значення, яке ми накопичуємо (яке правильно ініціалізовано до одинарного представлення нуля), а право значення буде наступним бітом, який слід обробити. Тепер ми застосовуємо таку заміну в циклі:

,(.)
$`$1,

Просто дивлячись на, ,(.)і $1,це переміщує маркер один раз праворуч. Але ми також вставляємо $`, що є все перед маркером, тобто поточне значення, яке ми подвоюємо. Ось окремі кроки при обробці вводу 1011, де я позначив результат вставки $`над кожним рядком (це перший крок порожній):

,1011

1,011
 _
110,11
   ___
1101101,1
       _______
110110111011011,

Ви побачите, що ми зберегли і подвоїли нуль разом із усім іншим, але оскільки ми їх ігноруємо в кінці, не має значення, як часто ми їх подвоювали, доки кількість 1s правильно. Якщо порахувати їх, є11 їх, саме те, що нам потрібно.

Отже, це залишає питання про те, як пограти в гольф до 12 байт. Найдорожча частина 18-байтової версії - використання маркера. Мета - позбутися цього. Ми дуже хочемо подвоїти префікс кожного біта, тому перша ідея може бути такою:

.
$`$&

Проблема полягає в тому, що ці заміни відбуваються одночасно, тому перший біт не подвоюється за кожен біт, а просто копіюється один раз кожен раз. Для введення 1011ми отримаємо (маркування вставленого $`):

 _ __ ___
1101011011

Нам ще потрібно обробити введення рекурсивно, щоб подвоєний перший префікс знову подвоївся другим тощо. Одна ідея - вставити маркери скрізь і кілька разів замінити їх префіксом:

\B
,
+%`,
¶$`

Після першої заміни кожного маркера префіксом нам потрібно запам'ятати, де був початок введення, тому ми також вставляємо лінійку передач і використовуємо %параметр, щоб переконатися, що наступний $`лише підбирає речі до найближчого рядкового рядка.

Це працює, але це все ще занадто довго (16 байт під час підрахунку 1s в кінці). Як щодо того, як ми перевертаємо речі? Місця, де ми хочемо вставити маркери, позначаються \B(позиція між двома цифрами). Чому ми просто не вставимо префікси в ці позиції? Це майже працює, але різниця полягає в тому, що в попередньому рішенні ми фактично видаляли один маркер у кожній заміні, і це важливо, щоб процес припинився. Однак \Bце не характер, а просто позиції, тому нічого не знімається. Однак ми можемо зупинити це\Bвід збігу, замість того, щоб замість цього вставити нецифровий символ у це місце. Це перетворює неслововий кордон у межу слова, що є еквівалентом попереднього видалення символу маркера. І ось що робить 12-байтне рішення:

+%`\B
¶$`:

Ось лише для повноти, ось окремі етапи обробки 1011з порожнім рядком після кожного кроку:

1
1:0
10:1
101:1

1
1:0
1
1:0:1
1
1:0
10:1:1

1
1:0
1
1:0:1
1
1:0
1
1:0:1:1

Знову ви побачите, що останній результат містить рівно 11 1с.

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


2

T-SQL, 202 байти

DECLARE @b varchar(max)='1',@ int=1 declare @l int=LEN(@b)declare @o bigint=CAST(SUBSTRING(@b,@l,1)AS bigint)WHILE @<@l BEGIN SET @o=@o+POWER(CAST(SUBSTRING(@b,@l-@,1)*2AS bigint),@)SET @=@+1 END PRINT @o

2

PHP, 64 байти

foreach(str_split(strrev($argv[1]))as$k=>$v)$t+=$v*2**$k;echo$t;

Ми перевертаємо наше двійкове число, ділимо його на його складові цифри і підсумовуємо їх, виходячи з позиції.


2

Утиліти Bash + GNU, 29 байт

sed 's/./2*&+/g;s/.*/K&p/'|dc

I / O через stdin / stdout.

sedВираз розбиває виконавчі вгору в кожну цифру і будує вираз RPN для dcоцінки.


2

PowerShell v2 +, 55 байт

param($n)$j=1;$n[$n.length..0]|%{$i+=+"$_"*$j;$j*=2};$i

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

Пояснення

param($n)$j=1;$n[$n.length..0]|%{$i+=+"$_"*$j;$j*=2};$i
param($n)$j=1;                                          # Take input $n as string, set $j=1
              $n[$n.length..0]                          # Reverses, also converts to char-array
                              |%{                  };   # Loop over that array
                                 $i+=+"$_"*$j;          # Increment by current value of $j times current digit
                                              $j*=2     # Increase $j for next loop iteration
                                                     $i # Leave $i on pipeline
                                                        # Implicit output

2

JavaScript (ES6), 32 байти

f=([...n])=>n+n&&+n.pop()+2*f(n)

Рекурсія знову врятує день! Хоча параметризація здається трохи довгою ...


Оскільки це єдиний "аргумент", чи [...n]потрібно оточувати їх в дужках?
Кіос

@Cyoce На жаль, так, або JS кидає SyntaxError.
ETHproductions

2

Математика, 27 13 11 байт

Fold[#+##&]

Приймає Listбіт як вхідний (наприклад {1, 0, 1, 1, 0}- двійкове представлення числа Mathematica22 )


Випливаючи з коментаря до відповіді Грега, як "розділення всіх цифр на вході" не є базовою функцією перетворення?
Мартін Ендер

@MartinEnder Я використовую його як Charactersфункцію.
JungHwan Min

@MartinEnder Насправді, як видно з відповіді @ nimi , я міг би просто прийняти список 1s і 0s, тому що це єдиний спосіб представити двійкове число в Mathematica , тобто IntegerDigitsв першу чергу мені це не потрібно .
JungHwan Min

Це передбачає, що база 10 - це "природне" подання цілого числа. Фактичне ціле значення не має прикріпленої до нього бажаної бази (я думаю, ви могли б сказати, що спосіб його зберігання - це, ймовірно, база 256 або, можливо, навіть база 2, але це деталізація реалізації). Просто тому, що ми (як правило) використовуємо базу 10 для запису цілих літералів, це не означає, що цілі значення вже є в базі 10.
Мартін Ендер

@MartinEnder @ Lynn's Jelly використовує кодD , який робить те саме, щоIntegerDigits
JungHwan Min

2

Clojure, 114 105 63 41 байт

V4: 41 байт

-22 байти завдяки @cliffroot. Оскільки digitце символ, його можна перетворити в його код за допомогою int, а потім у нього відняти 48, щоб отримати фактичне число. Карта також була розроблена фактурою. Я не знаю, чому це здавалося необхідним.

#(reduce(fn[a d](+(* a 2)(-(int d)48)))%)

V3: 63 байти

(fn[s](reduce #(+(* %1 2)%2)(map #(Integer/parseInt(str %))s)))

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

Дякуємо @nimi та @Adnan!

Безголівки:

(defn to-dec [binary-str]
  (reduce (fn [acc digit]
            (+ (* acc 2) digit))
          (map #(Integer/parseInt (str %)) binary-str)))

V2: 105 байт

#(reduce(fn[a[p d]](+ a(*(Integer/parseInt(str d))(long(Math/pow 2 p)))))0(map vector(range)(reverse %)))

-9 байтів, перевернувши рядок, тому мені не потрібно створювати незручний діапазон низхідних.

V1: 114 байт

Ну, я точно не виграю! На мій захист, це перша програма, яку я коли-небудь писав, яка конвертує між базами, тому мені довелося навчитися це робити. Це також не допомагає Math/powповертати дубль, який вимагає перетворення, і Integer/parseIntне приймає символ, тому цифру потрібно обернути перед передачею.

#(reduce(fn[a[p d]](+ a(*(Integer/parseInt(str d))(long(Math/pow 2 p)))))0(map vector(range(dec(count %))-1 -1)%))

Перетягує рядок зі спадним індексом, що представляє номер місця. Зменшується над отриманим списком.

Безголівки:

(defn to-dec [binary-str]
  (reduce (fn [acc [place digit]]
            (let [parsed-digit (Integer/parseInt (str digit))
                  place-value (long (Math/pow 2 place))]
              (+ acc (* parsed-digit place-value))))
          0
          (map vector (range (dec (count binary-str)) -1 -1) binary-str)))

#(reduce(fn[a b](+(* a 2)(-(int b)48)))0 %)вдосконалена версія. Переміщено mapчастину коду безпосередньо в reduce, змінив метод розбору цілого числа, зробіть зовнішню функцію за допомогою скороченого синтаксису лямбда.
скеля

@cliffroot intможна використовувати для розбору !? Це збиватиметься як 10 байт у кожному завданні, що я робив тут, хаха.
Carcigenicate

О, я бачу, що ти робиш. Беручи код ascii, потім віднімаючи, щоб отримати значення. Я думаю, що це спрацювало б лише у певних обставинах. Ну добре, дякую за пораду.
Carcigenicate

2

Perl, 21 19 16 + 4 = 20 байт

-4 байти завдяки @Dada

Бігайте з -F -p (включаючи додатковий простір після F). Значення труби до функції за допомогоюecho -n

$\+=$_+$\for@F}{

Виконати як echo -n "101010" | perl -F -pE '$\+=$_+$\for@F}{'

Я вважаю, що це досить відрізняється від відповіді @ Дади про те, що вона заслуговує власного вступу.

Пояснення:

-F                              #Splits the input character by character into the @F array
-p                              #Wraps the entire program in while(<>){ ... print} turning it into
while(<>){$\+=$_+$\for@F}{print}
                   for@F        #Loops through the @F array in order ($_ as alias), and...
          $\+=$_+$\             #...doubles $\, and then adds $_ to it (0 or 1)...
while(<>){              }       #...as long as there is input.
                         {print}#Prints the contents of $_ (empty outside of its scope), followed by the output record separator $\

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


Ще коротше:perl -F -pE '$\+=$_+$\for@F}{'
Дада

Я чесно сміявся з того, як зараз це коротко. Дякую.
Габріель Бенамі

Так, це дуже акуратно, молодець!
Дада

2

R (32-бітний), 64 байт

Вхід для функції повинен бути заданий як символ. Основні функції R підтримують 32-бітні цілі числа.

Вхід:

# 32-bit version (base)
f=function(x)sum(as.double(el(strsplit(x,"")))*2^(nchar(x):1-1))
f("1")
f("10")
f("101010")
f("1101111111010101100101110111001110001000110100110011100000111")

Вихід:

> f("1")
[1] 1
> f("10")
[1] 2
> f("101010")
[1] 42
> f("1101111111010101100101110111001110001000110100110011100000111")
[1] 2.016121e+18

R (64-бітний), 74 байт

Вхід для функції повинен бути заданий як символ. Пакет bit64повинен використовуватися для 64-бітних цілих чисел.

Вхід:

# 64-bit version (bit64)
g=function(x)sum(bit64::as.integer64(el(strsplit(x,"")))*2^(nchar(x):1-1))
g("1")
g("10")
g("101010")
g("1101111111010101100101110111001110001000110100110011100000111")

Вихід:

> g("1")
integer64
[1] 1
> g("10")
integer64
[1] 2
> g("101010")
integer64
[1] 42
> g("1101111111010101100101110111001110001000110100110011100000111")
integer64
[1] 2016120520371234567

2
Можна зробити: el(strsplit(x,""))замість того, strsplit(x,split="")[[1]]щоб зберегти пару байтів.
Billywob

Дуже дякую! Спеціально для elфункції - я її не усвідомлював.
dhhurio

2

Діалог APL , 12 байт

(++⊢)/⌽⍎¨⍞

отримати рядок введення

⍎¨ перетворити кожен символ у число

реверс

(... )/вставити наступну функцію між числами

++⊢ сума аргументів плюс правильний аргумент


ngn поголений 2 байти.


1

k, 8 байт

Той самий метод, що і відповідь Хаскелла вище.

{y+2*x}/

Приклад:

{y+2*x}/1101111111010101100101110111001110001000110100110011100000111b
2016120520371234567
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.