Ondalık dönüştürücü için ikili


32

Ondalık dönüştürücü için ikili

Görebildiğim kadarıyla, ondalık dönüşüm mücadelesinde basit bir ikili dosyaya sahip değiliz.


Pozitif bir ikili tamsayı alan ve ondalık değerini veren bir program veya işlev yazın.

Herhangi bir yerleşik temel dönüştürme işlevini kullanamazsınız. Tam sayıdan ondalık sayıya kadar olan işlevler (örneğin, 101010içine giren [1, 0, 1, 0, 1, 0]veya dönüşen bir işlev "101010") bu kuraldan muaf tutulur ve böylece izin verilir.

Kurallar:

  • Kod, dilinizin desteklediği en yüksek sayısal değere kadar ikili sayıları desteklemelidir (varsayılan olarak).
  • İkili gösterimde baştaki sıfırlara sahip olmayı seçebilirsiniz.
  • Ondalık çıktıda baştaki sıfırlar olmayabilir.
  • Giriş ve çıkış formatları isteğe bağlıdır, ancak rakamlar arasında herhangi bir ayırıcı olamaz. (1,0,1,0,1,0,1,0)Geçerli bir giriş biçimi değil, ama her ikisi de 10101010ve (["10101010"])vardır.
    • Girişi "normal" yönde almalısınız. 1110olduğu 14değil 7.

Test durumları:

1
1

10
2

101010
42

1101111111010101100101110111001110001000110100110011100000111
2016120520371234567

Bu zorluk, örneğin bu , bu ve bu gibi diğer birkaç zorluk ile ilgilidir .



Çıktının imzası mı var yoksa imzalanabilir mi? Ayrıca, eğer dilim değerin uzunluğuna bağlı olarak otomatik olarak 32 bit ve 64 bit tam sayılar arasında geçiş yaparsa, çıkış her iki alanda da imzalanabilir mi? EG-ondalık dönüşecektir iki ikili değerler var -1( 32 1'sve 64 1's)
Sütün

Ayrıca, çıktı değişken olabilir, bir tamsayı olması gerekiyor mu?
Carcigenicate

@Carcigenicate Bir tamsayı olmalıdır, ancak herhangi bir veri türünde olabilir. İyi olduğunuz sürece round(x)==x:) 2.000için çıktı kabul edilir 10.
Stewie Griffin,

Oh tatlı. Teşekkürler.
Carcigenicate

Yanıtlar:


56

Jöle , 5 bayt

DḤ+¥/

Çevrimiçi deneyin!

açıklama

enter image description here

Döküm

  • Dbir monad (tek bir argüman işlevi): basamağa 1234dönüşür [1, 2, 3, 4].

  • tek argümanını iki katına çıkaran bir monad.

  • + sol ve sağ argümanlarını ekleyen bir dyad (iki argüman işlevi) 'dir.

Oradan, biraz zor alır.

İşte ayrıştırma zamanında ne olur

  • D, ve +okunur. Zincir benziyor [D, Ḥ, +].

  • Sonraki iki karakter şimdiye kadar okuduğumuz linklerde (fonksiyonlar) ayrıştırma zamanı postfix operatörleri gibi davranan hızlı karakterlerdir .

  • Okunduğunda ¥, son iki link bir araya getirilir ve bunları bir araya getirerek oluşturulan perdeye benzeyen bir link alır. Şimdi zincir benziyor [D, dyad(Ḥ+)].

  • Ne zaman /okunur, son halkası (ki bir gayenin olmalı) attı ve bir monad yerini alır kıvrımlar bu dyad kullanarak (sezgisel: f/bir liste alır ile onun içinde virgül değiştirir fve sonucu değerlendirir.)

  • Son zincir [D, fold(dyad(Ḥ+))]iki monad gibi gözüküyor .

İşte çalışma zamanında ne olur

  • Girdi (sayı), çalışma değerine dolaylı olarak okunur (say, 101010).

  • Dçalışma değerini haneleriyle ( [1,0,1,0,1,0]) değiştirerek yürütülür .

  • fold(dyad(Ḥ+))çalışma değeri yerine yürütülür 1∗0∗1∗0∗1∗0, iki atomlu olduğu Ḥ+.

Peki neye değer x∗yveriyor?

  • İkilik bir tanımda, çalışma değeri başlangıçta soldaki argümandır x.

  • , Çift monad, bu değeri iki katına çıkar. Çalışma değeri şimdi 2x.

  • +, artı dyad, doğru bir argümandan yoksundur, bu yüzden bu bir kancadır : bu dyadın doğru argümanının enjekte edildiği özel bir sözdizimsel kalıp +. Bu 2x + y, döndürülen son çalışma değeri olarak gelir.

Yani tüm ifade değerlendirir:

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
Açıklamaların gittikçe daha da güzelleşiyor :-)
Luis Mendo

2
Heh, bundan böyle mi yapıyorsun? Bu harika, +1.
Outgolfer Erik

4
Sanırım bu şimdiye dek anladığım ilk Jelly. 1!
Mavi 19

Bravo. Aslında başlangıçta ne düşündüğümü, sadece görünüşte rastgele karakterlerden oluşan bir karmaşa olarak anladım. Harika açıklama.
domuz balığı

1
@Mark Jelly, programların görünmesini sağlamak için kendi kod sayfasını içerir, ahem, okunabilir durumdadır, ancak programlar da yalnızca denetleyici olabilir.
Lynn,

20

Python 2, 49 37 31 30 Bayt

Şimdi bu, Python'un keyfi olarak büyük tam sayılarla başa çıkabilmesi için onlu bir gösterimde ikili sayı alacaktır.

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

Bir bayt tasarrufu için xnor sayesinde :)

Bunun nasıl çalıştığını görmenin en kolay yolu, ikiliyi ondalık sayıya dönüştürmek için temel bir formül görmektir:

= 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

Bu, 'standart' bir dönüştürme yöntemidir. Üçüncü satırı şu şekilde genişletebilirsiniz:

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

Ve bu esasen yaptığım özyinelemeli yöntem yapıyor.

Sahip olduğum alternatif çözümler:

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
Yapabilir n%5veya n%2yerine n%10.
xnor

@xnor Ah, bunu nasıl özlediğimden emin değilim! Thanks :)
Kade

12

05AB1E , 6 bayt

Kod:

$¦v·y+

Patlama için, 101010 örneğini ele alalım . 1 numara ile başlıyoruz (birinci rakam ile temsil edilir). Ondan sonra iki vakamız var:

  • Rakam 0 ise , sayıyı 2 ile çarpın.
  • Rakam 1 ise , sayıyı 2 ile çarpın ve 1 ekleyin.

Böylece 101010 durum için aşağıdakiler hesaplanır:

  • 1 01010, sayı ile başlar 1 .
  • 1 0 halinde ortaya çıkan iki ile çarpın 1010, 2 .
  • 10 1 iki ile çarpın 010 ve içine çıkan bir ekleme, 5 .
  • 101 0 10, iki ile çarparak 10'a dönüşür .
  • 1010 10 , iki ile çarpın ve 21 ekleyin .
  • 10101 0 , iki ile çarparak , istenen sonuç olan 42'ye yol açar .

Kod açıklaması:

$         # 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 kodlamasını kullanır . Çevrimiçi deneyin!


Güzel bir! (Yeni fark
etsem de

@Emigna Yep, neyse ki kodunuzun sadece pozitif ikili sayılar için çalışması gerekiyor.
Adnan

O kısmı görmedim bile. Çok güzel sonra :)
Emigna

9

Haskell, 16 111 + 57 = 168 bayt

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

57 derleme Bayraklar için bayt -XOverloadedStrings, -XOverlappingInstancesve -XFlexibleInstances.

Zorluk bazı hantal IO formatlarına sahiptir , çünkü büyük ölçüde veri türlerinin kaynak kodda nasıl ifade edildiğine bağlıdır. İlk versiyonum (16 bayt), yani

foldl1((+).(2*))

tamsayıların bir listesini alır, mesela tam [1,0,1,0,1,0]anlamıyla Haskell listelerinin ,elementler arasında olması nedeniyle geçersiz olarak ilan edildi . Kendi başına listeler yasaktır. Yeni versiyonumda, şimdi isimlendirilen aynı işlevi kullanıyorum f, fakat "Eklenmiş karakter dizilerini alıntıla " olarak aşırı yüklüyorum. Tür ek açıklaması görebileceğiniz gibi işlev hala tamsayılar listesini alır [Int] -> Int, ancak tek haneli rakamlarla aran listeleri artık gibi yazılabilir "1234", ör

f "101010"

hangi için değerlendirir 42. Şanssız Haskell, çünkü yerel liste formatı meydan okuma kurallarına uymuyor. BTW, f [1,0,1,0,1,0]hala çalışıyor.


2
Maalesef bir liste geçerli bir giriş değil.
Jonathan Allan,

@ JonathanAllan: Neden? Ve eğer öyleyse, nasıl girdi almalı? Haskell'de bir dize sadece bir karakter listesidir.
nimi

Ben neden bilmiyorum ... ama erken bu konuda sordu ve bir düzenleme eklemek için yapıldı " (1,0,1,0,1,0,1,0)geçerli bir giriş biçimi değil, ama her ikisi de 10101010ve (["10101010"])vardır." ayrıca bir yorum , bir dizge girişinin bu şekilde yorumlanması halinde karakter dizisinin kabul edilebilir olduğunu gösterir.
Jonathan Allan,

1
@JonathanAllan: Herhangi bir "ikili tamsayı" (almamız gereken girdi) içsel olarak ayrılır, 2'nin bir güçler dizisidir. Kısıtlama, açık ayırıcılar (rakamlar arasında) ve ayırma ile ilgili değildir. Her nasılsa, ayrı sayıları almak zorundayım.
nimi

2
Op burada: giriş yapmak mümkün ise 10101010, "10101010" ya da benzer bir şey verin ve bu gönderme geçerlidir ardından çalışırlar. Bir dize, liste, tamsayı veya her neyse diyebilirsiniz. Giriliyor [1][0][1][0]veya [1,0,1,0]tamam değil. Temel olarak, bir yerde üst üste bir sürü gruba ve sıfıra çarpmak mümkün olmalıdır. Bu açık mı?
Stewie Griffin,

7

Retina, 15 bayt

İkili sistemden tekli, ardından tekli ve ondalık sayıya dönüştürür.

1
01
+`10
011
1

Çevrimiçi deneyin


Herhangi bir yerleşik temel dönüştürme işlevini kullanamazsınız. ~ OP
Roman Gräf

10
@ RomanGräf Hiç yok. Çözümümün sürecini basitçe anlatıyordum.
mbomb007

7

PHP, 44 bayt

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

Bu soruyu daha önce gördüğüme yemin edebilirdim. Ama iyi.

Sayıyı soldan sağa okur, sola kayar ve geçerli biti ekler.


7

JavaScript (ES6), 33 31 bayt

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

Düzenleme: Daha kısa fakat daha az tatlı: @ETHproductions sayesinde 2 bayt kurtarıldı.


Sık sık olduğu gibi .map, daha kısadır:s=>[...s].map(c=>+c+r+r,r=0)|r
ETHproductions

@ETHproductions İşleviniz 0'dan başka bir şeyi nasıl döndürür?
Neil

Üzgünüm, olması gerektiğis=>[...s].map(c=>r+=+c+r,r=0)|r
ETHproductions 7:16 '

7

Labirent , 17 15 bayt

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

Çevrimiçi deneyin!

Image of the code

Labirent, iki boyutlu, yığın tabanlı bir dildir. Labirentte, kod çalıştırma, duvarlar gibi hareket eden ve boşluk bırakmayan en üst karakterden başlayarak boşlukları olan bir labirent gibi kodun yolunu izler. Kod akışı, yığının tepesinin işaretiyle belirlenir. Yığın altta sıfırlar olduğu için ilk dört komut (-+:+ ) etkisi yoktur.

Başlayan döngü ,

  • , Bir sonraki giriş karakterinin ascii kod değerini yığının sonuna kadar itin veya EOF ise -1'e basın.
  • _48 48'i yığının üstüne iter
  • -Pop y, pop x, bas x-y. Önceki talimatlar, "0" için 0 ve "1" için 1 veren girişten 48 çıkarma etkisine sahiptir.
  • +Pop y, pop x, bas x+y.
  • : Yığının tepesini çoğalt
  • + Bu ve önceki talimat mevcut değeri 2 ile çarpma etkisine sahiptir.

Bu nedenle, kodun dairesel kısmı, geçerli sayıyı 2 ile çarpar ve karakterin 1 veya 0'ın girilip girilmediğine bağlı olarak 1 veya 0 ekler.

Kuyruk

Yığının üstü negatifse (yani EOF bulundu), kod birleşimde sola döner (noktalı virgül yönünde).

  • `` `Almak için yığının en üstünü 1
  • ) 2 elde etmek için yığının en üst kısmını artırın
  • /Pop y, pop x, x / y (tam sayı bölümü) tuşlarına basın. Bu, son *2döngüden geri alma etkisine sahiptir .
  • !Yığının tepesinin tamsayı gösterimini verin. Bu noktada program geri döner, çünkü bir çıkmaza girer ve sonra bir hata ile çıkar çünkü sıfıra bölmeye çalışır.

@Martin Ender'a 2 bayt kazandırdığın için teşekkürler (ve Labirent'te daha iyi düşünmeyi öğretti).


_48-Sizin yerine basitçe yapabilirsiniz #%ama ne yazık ki bayt sayısı ile nasıl yardımcı olabileceğini anlamıyorum.
Martin Ender

Sen edebilir bir byte kaydetmek `)yerine ;_2gerçi.
Martin Ender

@MartinEnder, hakkındaki yorumunuzu anlamıyorum #%. _48-Ascii'den int'ye dönüştürmenin yerine nasıl geçeceğini açıklayabilir misiniz? Bahşiş için teşekkürler ). Bu değişikliği yapacağım.
Robert Hickman,

Programınızın bu noktasında her zaman yığında iki değer vardır, bu yüzden #sadece kısadır _2. ASCII'nin _2%tamsayıya dönüştürülmesi için genel bir dönüştürme yöntemi olmasa da, burada çalışır, çünkü yalnızca ilk iki hane ile mümkün girdi olarak ilgilenirsiniz. Bir alternatif olabilir _1&(çünkü modulo 2 basitçe en az anlamlı biti çıkarır).
Martin Ender

Ah. Bu harika. Ama evet #%, kodun genel olarak kısaltılması için bu ikame yönteminin ( ) kullanıldığından emin değilim .
Robert Hickman,

6

Brain-Flak , 46 , 28 bayt

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

Çevrimiçi deneyin!

@Riley sayesinde çok sayıda bayt kaydedildi!

Brain-flak ikili girişi alamadığından, giriş '0 ve' 1 'in bir listesidir.

Açıklama:

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

Açıklama seviyorum! Beyin-
lafı

2
^. Birkaç yorum yapmazsam kendi programlarımı bile okuyamıyorum.
Riley,

Eğer bütün parçalardan kurtularak 32 byte'a kadar alabilirsiniz ve "diğer yığına numara ekle" adımı için sadece (diğer yığına) * 2 'ye ekleyin. ([]){({}[()]<({}<>({}){})><>)}<>
Riley,

Ve sadece bir süre önce patlatarak ve sonunda tekrar yüksekliği iterek başka 4 kurtarabilirsiniz. ([]){{}({}<>({}){})<>([])}<>
Riley,

@Riley Aman Tanrım, bu dahi. Çok teşekkür ederim!
DJMcMayhem

6

Java, 84 79 46 48 bayt

  • Sürüm 3.1

Değiştirildi long/ 48 bayt:

s->{long x=0;for(char c:s)x=c-48l+x*2;return x;}
  • Sürüm 3.0

Bazı golf / 46 bayt yaptım :

s->{int x=0;for(char c:s)x=c-48+x*2;return x;}
  • Sürüm 2.0

@Geobits! / 79 bayt sayesinde:

s->{int i=Math.pow(2,s.length-1),j=0;for(char c:s){j+=c>48?i:0;i/=2;}return j;}
  • Sürüm 1.0

84 bayt:

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
Sanırım yinelemeli bir çözüm yapmalıydım. lulz. iyi iş
Poke

Giriş türünüz List <Character> veya String mi? İkincisi ise, Java8'in yapabileceğinin farkında değildim! Eski ise, bu meydan okumaya izin veriliyor mu?
Poke

solmalı char[]. Umarım buna izin verilir ...
Roman Gräf

Buradaki iade türü nedir? Ben OP başına "kod en yüksek sayısal değer dil destekleri kadar ikili sayılar desteklemesi gerekir" ama düşünürdüm küçük değerler için bir int döndüren çünkü uzun olması gerektiğini düşünüyorum
Poke

1
Muhtemelen bunun başına giriş tipinde gayet iyi . İmo çıkış için 2 bayt hit almak isteyebilirsiniz
Poke

4

Befunge-98, 12 bayt

2j@.~2%\2*+

Çevrimiçi deneyin!

Girişten bir defada bir char okur, modulo 2 değerini alarak 0 veya 1 değerine dönüştürür (0, char (48), 1, char (49)), ardından geçerli değerin iki katına çıkması ve eklenmesinin normal algoritmasını kullanır. her seferinde yeni rakam.

Bonus: Bu herhangi bir giriş dizesiyle çalışır, bir süredir herhangi bir komik girdi-> çıktı kombinasyonu bulmak için uğraşıyorum, ancak bir şey üretemedim (ne yazık ki, "cevap" = 46). Yapabilir misin?


LOL. Cevabımla aynı oyunu oynuyordum. Üretebileceğim en ilginç sayı 666 idi .
James Holderness

Güzel bir! 666: D için uygun bir şey bulamadım: Büyük harflerin değerler üzerinde bir etkisi olsaydı daha kolay olurdu ...
Leo

@James Holderness - Ben de aynısını yapıyorum ve sadece 366'yı geri getirmek için 'seansı' buldum, seninki gerçekten iyi.
Peal Pelikan

4

Javascript (ES7) 41 40 36 bayt

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

girdi olarak bir dize alır

ETHproductions sayesinde bir bayt tıraş etti

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


1
Sağdan sola birliktelik **tuhaf ama burada kullanmak hoş iş. 1<<b.lengthaynı şeyi yapardı, ancak parantezlerin aynen ayrılmasını engellemek isterdi (c*1)<<(b.length+...). Sana değiştirerek byte kurtarabilir miyiz b[0]ile b+b( burada bakınız ).
ETHProductions

4

C # 6, 85 37 36 bayt

long b(long n)=>n>0?n%2+2*b(n/10):0;
  • 41 byte tasarruf ettiğin için Kade'ye teşekkürler !
  • C # 6'ya geçmek başka bir 7 byte kaydetti.

Belki bu biraz ilham verebilir? ;)
Kade

@Kade It does, thanks! I was looking at the Python answer which uses the same technique at the same moment you linked that :D I can get even shorter with C# 6.
Yytsi


3

C, 53

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

Same as my javascript answer

Test Ideone


You can save 4 bytes by declaring v and c as global variables (though you need to change the name of v, since it's already the name of the function) like this: w=0;c;v(char*s){while(c=*s++)w+=w+c-48;return w;}
Steadybox

@Steadybox it could be w,c; but I don't want use globals when the answer is a function (even in code-golf)
edc65

@Steadybox Globals defaults to 0 as well, so you can drop the =0.
algmyr

3

Perl, 25 bytes

-3 bytes thanks to @Dom Hastings.

24 bytes of code + 1 byte for -p flag.

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

To run it:

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

Explanations:

$\|=$&<<$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

Pushy, 10 bytes

Takes input as a list of 0/1 on the command line: $ pushy binary.pshy 1,0,1,0,1,0.

L:vK2*;OS#

The algorithm really shows the beauty of having a second stack:

            \ 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

This method works because the stack will be doubled stack length - n times before reaching number n, which is then dumped into the second stack for later. Here's what the process looks like for input 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

Matlab, 30 Bytes

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

The last test case has rounding errors (because of double), so if you need full precision:

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

with 47 Bytes.


I can't test this, but I believe @(x)sum(2.^(find(flip(x)-48)-1)) will give the correct result for all cases for 32 bytes. flip works like fliplr if x is one dimensional.
Stewie Griffin

Nice solution! I also ran into the rounding error, thanks for the fix. What is the format of x? Calling flip or fliplr on a number just returns that number.
MattWH

x is the binary string, so call it with f=@(x)..; f('1111001010').
Jonas

3

Retina, 12 bytes

Byte count assumes ISO 8859-1 encoding.

+%`\B
¶$`:
1

Try it online!

Alternative solution:

+1`\B
:$`:
1

Explanation

This will probably be easier to explain based on my old, less golfed, version and then showing how I shortened it. I used to convert binary to decimal like this:

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

The only sensible way to construct a decimal number in Retina is by counting things (because Retina has a couple of features that let it print a decimal number representing an amount). So really the only possible approach is to convert the binary to unary, and then to count the number of unary digits. The last line does the counting, so the first four convert binary to unary.

How do we do that? In general, to convert from a list of bits to an integer, we initialise the result to 0 and then go through the bits from most to least significant, double the value we already have and add the current bit. E.g. if the binary number is 1011, we'd really compute:

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

Where I've marked the individual bits for clarity.

The trick to doing this in unary is a) that doubling simply means repeating the number and b) since we're counting the 1s at the end, we don't even need to distinguish between 0s and 1s in the process. This will become clearer in a second.

What the program does is that it first adds a comma to the beginning as marker for how much of the input we've already processed:

^
,

Left of the marker, we'll have the value we're accumulating (which is correctly initialised to the unary representation of zero), and right of the value will be the next bit to process. Now we apply the following substitution in a loop:

,(.)
$`$1,

Just looking at ,(.) and $1,, this moves the marker one bit to the right each time. But we also insert $`, which is everything in front of the marker, i.e. the current value, which we're doubling. Here are the individual steps when processing input 1011, where I've marked the result of inserting $` above each line (it's empty for the first step):

,1011

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

You'll see that we've retained and doubled the zero along with everything else, but since we're disregarding them at the end, it doesn't matter how often we've doubled them, as long as the number of 1s is correct. If you count them, there are 11 of them, just what we need.

So that leaves the question of how to golf this down to 12 bytes. The most expensive part of the 18-byte version is having to use the marker. The goal is to get rid of that. We really want to double the prefix of every bit, so a first idea might be this:

.
$`$&

The problem is that these substitutions happen simultaneously, so first bit doesn't get doubled for each bit, but it just gets copied once each time. For input 1011 we'd get (marking the inserted $`):

 _ __ ___
1101011011

We do still need to process the input recursively so that the doubled first prefix is doubled again by the second and so on. One idea is to insert markers everywhere and repeatedly replace them with the prefix:

\B
,
+%`,
¶$`

After replacing each marker with the prefix for the first time, we need to remember where the beginning of the input was, so we insert linefeeds as well and use the % option to make sure that the next $` only picks up things up the closest linefeed.

This does work, but it's still too long (16 bytes when counting 1s at the end). How about we turn things around? The places where we want to insert markers are identified by \B (a position between two digits). Why don't we simply insert prefixes into those positions? This almost works, but the difference is that in the previous solution, we actually removed one marker in each substitution, and that's important to make the process terminate. However, the \B aren't character but just positions, so nothing gets removed. We can however stop the \BBunun yerine rakam olmayan bir karakter ekleyerek eşleştirmeden. Bu, kelime olmayan sınırı, daha önce marker karakterini kaldırmaya eşdeğer olan bir kelime sınırına dönüştürür. Ve 12 baytlık çözümün yaptığı şey:

+%`\B
¶$`:

Sadece bütünlük için, işte her işlemden 1011sonra boş bir satır olacak şekilde ayrı işlem adımları :

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

Yine, son sonucun tam olarak 11 1sn içerdiğini göreceksiniz .

Okuyucu için bir alıştırma olarak, bunun diğer tabanlara nasıl kolayca yayıldığını görebiliyor musunuz (tabandaki artış başına birkaç ek bayt için)?


2

T-SQL, 202 Bytes

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 bytes

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

We reverse our binary number, split it into its component digits, and sum them based on position.


2

Bash + GNU utilities, 29 bytes

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

I/O via stdin/stdout.

The sed expression splits the binary up into each digit and builds a RPN expression for dc to evaluate.


2

PowerShell v2+, 55 bytes

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

Feels too long ... Can't seem to golf it down any -- tips appreciated.

Explanation

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 bytes

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

Recursion saves the day again! Though the parameterization seems a little long...


Since it's a single "argument", does [...n] need to be surrounded in parentheses?
Cyoce

@Cyoce Unfortunately, yes, or JS throws a SyntaxError.
ETHproductions

2

Mathematica, 27 13 11 bytes

Fold[#+##&]

Accepts a List of bits as input (e.g. {1, 0, 1, 1, 0} -- Mathematica's binary representation of the number 22)


Following up from the comment on Greg's answer, how is "splitting all the digits in the input" not a base conversion function?
Martin Ender

@MartinEnder I'm using it like the Characters function.
JungHwan Min

@MartinEnder Actually, as seen in @nimi's answer, I could just accept a list of 1s and 0s because that is the only way to represent a binary number in Mathematica, meaning I don't need IntegerDigits in the first place.
JungHwan Min

That assumes that base 10 is the "natural" representation of an integer. An actual integer value has no preferred base attached to it (I guess you could say the way it's stored is probably base 256 or maybe even base 2 but that's an implementation detail). Just because we (normally) use base 10 to write integer literals there doesn't mean integer values are already in base 10.
Martin Ender

@MartinEnder @Lynn's Jelly code uses D, which does the same thing as IntegerDigits
JungHwan Min

2

Clojure, 114 105 63 41 bytes

V4: 41 bytes

-22 bytes thanks to @cliffroot. Since digit is a character, it can be converted to it's code via int, then have 48 subtracted from it to get the actual number. The map was also factored out. I don't know why it seemed necessary.

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

V3: 63 bytes

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

-42 bytes (!) by peeking at other answers. My "zipping" was evidently very naïve. Instead of raising 2 to the current place's power, then multiplying it by the current digit and adding the result to the accumulator, it just multiplies the accumulator by 2, adds on the current digit, then adds it to the accumulator. Also converted the reducing function to a macro to shave off a bit.

Thanks to @nimi, and @Adnan!

Ungolfed:

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

V2: 105 bytes

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

-9 bytes by reversing the string so I don't need to create an awkward descending range.

V1: 114 bytes

Well, I'm certainly not winning! In my defense, this is the first program I've ever written that converts between bases, so I had to learn how to do it. It also doesn't help that Math/pow returns a double that requires converting from, and Integer/parseInt doesn't accept a character, so the digit needs to be wrapped prior to passing.

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

Zips the string with a descending index representing the place number. Reduces over the resulting list.

Ungolfed:

(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 %) improved version. Moved map part of code directly into reduce, changed integer parsing method, make external function with shorthand lambda syntax.
cliffroot

@cliffroot int can be used to parse!? That'll knock off like 10 bytes in every challenge I've done here lol.
Carcigenicate

Oh, I see what you're doing. Taking the ascii code, then subtracting to get the value. I guess this would only work in select circumstances only. Oh well, thanks for the tip.
Carcigenicate

2

Perl, 21 19 16 + 4 = 20 bytes

-4 bytes thanks to @Dada

Run with -F -p (including the extra space after the F). Pipe values to the function using echo -n

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

Run as echo -n "101010" | perl -F -pE '$\+=$_+$\for@F}{'

I feel this is sufficiently different from @Dada's answer that it merits its own entry.

Explanation:

-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 $\

This uses my personal algorithm of choice for binary-to-decimal conversion. Given a binary number, start your accumulator at 0, and go through its bits one by one. Double the accumulator each bit, then add the bit itself to your accumulator, and you end up with the decimal value. It works because each bit ends up being doubled the appropriate number of times for its position based on how many more bits are left in the original binary number.


Even shorter : perl -F -pE '$\+=$_+$\for@F}{'
Dada

I honestly laughed at how short this is now. Thank you.
Gabriel Benamy

Yea, it's pretty neat, well done!
Dada

2

R (32-bit), 64 Bytes

Input for the function should be given as character. The base functions of R support 32-bit integers.

Input:

# 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")

Output:

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

R (64-bit), 74 Bytes

Input for the function should be given as character. The package bit64 has to be used for 64-bit integers.

Input:

# 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")

Output:

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

2
You can do: el(strsplit(x,"")) instead of strsplit(x,split="")[[1]] to save a couple of bytes.
Billywob

Thanks a lot! Especially for the el function - I was not aware of it.
djhurio

2

Dyalog APL, 12 bytes

(++⊢)/⌽⍎¨⍞

get string input

⍎¨ convert each character to number

reverse

(...)/ insert the following function between the numbers

++⊢ the sum of the arguments plus the right argument


ngn shaved 2 bytes.


1

k, 8 bytes

Same method as the Haskell answer above.

{y+2*x}/

Example:

{y+2*x}/1101111111010101100101110111001110001000110100110011100000111b
2016120520371234567
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.