Chuyển đổi nhị phân sang thập phân


32

Chuyển đổi nhị phân sang thập phân

Theo như tôi có thể thấy, chúng ta không có một thách thức chuyển đổi nhị phân sang thập phân đơn giản.


Viết chương trình hoặc hàm lấy số nguyên nhị phân dương và xuất giá trị thập phân của nó.

Bạn không được phép sử dụng bất kỳ chức năng chuyển đổi cơ sở dựng sẵn nào. Các hàm số nguyên đến thập phân (ví dụ: hàm biến 101010thành [1, 0, 1, 0, 1, 0]hoặc "101010") được miễn quy tắc này và do đó được cho phép.

Quy tắc:

  • Mã phải hỗ trợ các số nhị phân lên đến giá trị số cao nhất mà ngôn ngữ của bạn hỗ trợ (theo mặc định)
  • Bạn có thể chọn để có các số 0 đứng đầu trong biểu diễn nhị phân
  • Đầu ra thập phân có thể không có số 0 đứng đầu.
  • Các định dạng đầu vào và đầu ra là tùy chọn, nhưng không thể có bất kỳ dấu phân cách nào giữa các chữ số. (1,0,1,0,1,0,1,0)không phải là một định dạng đầu vào hợp lệ, nhưng cả hai 10101010(["10101010"])là.
    • Bạn phải lấy đầu vào theo hướng "bình thường". 111014không 7.

Các trường hợp thử nghiệm:

1
1

10
2

101010
42

1101111111010101100101110111001110001000110100110011100000111
2016120520371234567

Thử thách này có liên quan đến một vài thử thách khác, ví dụ thế này , thế nàythế này .



Là đầu ra phải được ký hoặc nó có thể được ký? Ngoài ra, nếu ngôn ngữ của tôi xảy ra tự động chuyển đổi giữa các số nguyên 32 bit và 64 bit tùy thuộc vào độ dài của giá trị, liệu đầu ra có thể được ký trong cả hai phạm vi không? Ví dụ: Có hai giá trị nhị phân sẽ chuyển đổi thành số thập phân -1( 32 1's64 1's)
sữa

Ngoài ra, đầu ra có thể nổi, có cần phải là một số nguyên không?
Carcigenicate

@Carcigenicate Nó phải là một số nguyên, nhưng nó có thể thuộc bất kỳ loại dữ liệu nào. Miễn là round(x)==xbạn ổn :) 2.000được chấp nhận đầu ra cho 10.
Stewie Griffin

Ôi ngọt ngào. Cảm ơn.
Carcigenicate

Câu trả lời:


56

Thạch , 5 byte

DḤ+¥/

Hãy thử trực tuyến!

Giải trình

nhập mô tả hình ảnh ở đây

Dàn diễn viên

  • Dlà một đơn nguyên (hàm đối số đơn): chữ số, biến 1234thành [1, 2, 3, 4].

  • là một đơn nguyên nhân đôi đối số của nó.

  • + là một dyad (hai hàm đối số) thêm các đối số trái và phải của nó.

Từ đó, nó có một chút khó khăn.

Đây là những gì xảy ra vào thời điểm phân tích

  • D, +được đọc. Chuỗi trông như thế [D, Ḥ, +].

  • Hai ký tự tiếp theo là nhanh , hoạt động giống như các toán tử postfix thời gian phân tích trên các liên kết (hàm) mà chúng ta đã đọc cho đến nay.

  • Khi ¥được đọc, hai liên kết cuối cùng sẽ xuất hiện và được thay thế bằng một liên kết hoạt động giống như đê được hình thành bằng cách soạn chúng. Vì vậy, bây giờ chuỗi trông như thế nào [D, dyad(Ḥ+)].

  • Khi /được đọc, liên kết cuối cùng (phải là một dyad) sẽ được bật lên và được thay thế bằng một đơn vị có thể gấp lại bằng cách sử dụng dyad này (theo trực giác: f/lấy một danh sách, thay thế dấu phẩy trong đó fvà đánh giá kết quả.)

  • Chuỗi cuối cùng trông giống như [D, fold(dyad(Ḥ+))], hai đơn nguyên.

Đây là những gì xảy ra trong thời gian chạy

  • Đầu vào (một số) được đọc ngầm vào giá trị làm việc (giả sử 101010).

  • Dđược thực thi, thay thế giá trị làm việc bằng các chữ số của nó ( [1,0,1,0,1,0]).

  • fold(dyad(Ḥ+))được thực thi, thay thế giá trị làm việc bằng 1∗0∗1∗0∗1∗0, dyad ở đâu Ḥ+.

Vậy x∗yđánh giá để làm gì?

  • Trong một định nghĩa dyadic, giá trị làm việc ban đầu là đối số bên trái , x.

  • , Các đôi đơn nguyên, tăng gấp đôi giá trị này. Giá trị làm việc bây giờ 2x.

  • +, dyad cộng , thiếu một đối số đúng, vì vậy đây là một hook : một mô hình cú pháp đặc biệt trong đó đối số đúng của dyad này được đưa vào +. Điều này mang lại 2x + ynhư là giá trị làm việc cuối cùng, được trả lại.

Vì vậy, toàn bộ biểu thức ước tính để:

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
Giải thích của bạn ngày càng tốt hơn :-)
Luis Mendo 6/12/2016

2
Heh, tôi đoán bạn làm điều đó từ bây giờ? Thật tuyệt vời, +1.
Erik the Outgolfer 6/12/2016

4
Tôi nghĩ rằng đây là phần đầu tiên của Jelly mà tôi từng hiểu. +1!
Xanh

Bravo. Tôi thực sự hiểu những gì tôi nghĩ ban đầu chỉ là một mớ hỗn độn của các nhân vật dường như ngẫu nhiên. Giải thích tuyệt vời.
cá heo

1
@Mark Jelly có codepage riêng để làm cho các chương trình trông như ahem, có thể đọc được, nhưng các chương trình cũng có thể chỉ là bytestrings.
Lynn

20

Python 2, 49 37 31 30 byte

Bây giờ điều này sẽ lấy một số nhị phân trong một biểu diễn thập phân, vì Python có thể xử lý các số nguyên lớn tùy ý.

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

cảm ơn xnor vì đã tiết kiệm một byte :)

Cách dễ nhất để xem cách thức hoạt động của nó là bằng cách xem một công thức cơ bản để chuyển đổi nhị phân thành thập phân:

= 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

Đây là một cách chuyển đổi 'tiêu chuẩn'. Bạn có thể mở rộng dòng thứ ba như vậy:

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

Và đây thực chất là những gì phương pháp đệ quy tôi đã thực hiện.

Giải pháp thay thế tôi đã có:

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
Bạn có thể làm n%5hoặc n%2thay vì n%10.
xnor

@xnor Ah, không chắc là tôi đã bỏ lỡ điều đó như thế nào! Cảm ơn :)
Kade

12

05AB1E , 6 byte

Mã số:

$¦v·y+

Để khám phá, hãy lấy ví dụ 101010 . Chúng tôi bắt đầu với số 1 (được biểu thị bằng chữ số đầu tiên). Sau đó, chúng tôi có hai trường hợp:

  • Nếu chữ số là 0 , nhân số đó với 2.
  • Nếu chữ số là 1 , nhân số đó với 2 và thêm 1.

Vì vậy, đối với trường hợp 101010 , sau đây được tính:

  • 1 01010, bắt đầu với số 1 .
  • 1 0 1010, nhân hai, kết quả thành 2 .
  • 10 1 010, nhân hai và thêm một, kết quả là 5 .
  • 101 0 10, nhân hai, kết quả thành 10 .
  • 1010 1 0, nhân với hai và thêm một, kết quả là 21 .
  • 10101 0 , nhân với hai, kết quả là 42 , đó là kết quả mong muốn.

Mã giải thích:

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

Sử dụng mã hóa CP-1252 . Hãy thử trực tuyến!


Đẹp quá (không hoạt động cho 0 mặc dù tôi chỉ nhận thấy)
Emigna

@Emigna Yep, may mắn là mã của bạn chỉ cần hoạt động cho các số nhị phân dương.
Ad Nam

Thậm chí không nhìn thấy phần đó. Rất đẹp rồi :)
Emigna

9

Haskell, 16 111 + 57 = 168 byte

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

57 byte cho cờ biên dịch -XOverloadedStrings, -XOverlappingInstances-XFlexibleInstances.

Thách thức có một số định dạng IO cồng kềnh , bởi vì nó phụ thuộc rất nhiều vào cách các loại dữ liệu được thể hiện trong mã nguồn. Phiên bản đầu tiên của tôi (16 byte), cụ thể là

foldl1((+).(2*))

lấy một danh sách các số nguyên, ví dụ [1,0,1,0,1,0]và được tuyên bố là không hợp lệ vì danh sách Haskell theo nghĩa đen xảy ra ,giữa các phần tử. Danh sách mỗi se không bị cấm. Trong phiên bản mới của tôi, tôi sử dụng chức năng rất giống nhau, bây giờ được đặt tên f, nhưng tôi quá tải "Trích dẫn chuỗi ký tự kèm theo". Hàm vẫn lấy danh sách các số nguyên như bạn có thể thấy trong chú thích loại [Int] -> Int, nhưng các danh sách có số nguyên một chữ số giờ có thể được viết như thế "1234", ví dụ

f "101010"

mà đánh giá 42. Không may mắn Haskell, vì định dạng danh sách gốc không phù hợp với quy tắc thách thức. Btw, f [1,0,1,0,1,0]vẫn hoạt động.


2
Thật không may, một danh sách không phải là một đầu vào hợp lệ.
Jonathan Allan

@Jonathan ALLan: Tại sao? Và nếu vậy, làm thế nào nó nên có đầu vào? Trong Haskell, một chuỗi chỉ là một danh sách các ký tự.
nimi

Tôi không biết tại sao ... nhưng tôi đã hỏi về điều này từ rất sớm và một chỉnh sửa đã được thực hiện để thêm " (1,0,1,0,1,0,1,0)không phải là một định dạng đầu vào hợp lệ, nhưng cả hai 10101010(["10101010"])đều được." hơn nữa một bình luận cho thấy mảng ký tự được chấp nhận nếu đó là cách diễn giải chuỗi đầu vào.
Jonathan Allan

1
@Jonathan ALLan: bất kỳ "số nguyên nhị phân" nào (đầu vào chúng ta phải lấy) vốn đã được tách riêng, đó là một chuỗi các quyền hạn của 2. Hạn chế là về các dấu tách rõ ràng (giữa các chữ số) chứ không phải về phân tách. Bằng cách nào đó tôi phải lấy các chữ số riêng biệt.
nimi

2
Op ở đây: nếu có thể nhập 10101010, "10101010"hoặc một cái gì đó tương tự và làm cho nó hoạt động thì việc gửi là hợp lệ. Bạn có thể gọi nó là một chuỗi, danh sách, số nguyên hoặc bất cứ điều gì. Nhập [1][0][1][0]hoặc [1,0,1,0]không ổn. Về cơ bản, có thể chỉ cần đánh một loạt các số không và số 0 liên tiếp ở đâu đó. Điều này có rõ ràng không?
Stewie Griffin

7

Võng mạc, 15 byte

Chuyển đổi từ nhị phân sang unary, sau đó unary thành thập phân.

1
01
+`10
011
1

Dùng thử trực tuyến


Bạn không được phép sử dụng bất kỳ chức năng chuyển đổi cơ sở dựng sẵn nào. ~ OP
Roman Gräf

10
@ RomanGräf Không có. Tôi chỉ đơn giản là mô tả quá trình giải pháp của tôi.
mbomb007

7

PHP, 44 byte

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

Tôi có thể đã thề rằng tôi đã nhìn thấy câu hỏi đó trước đây. Nhưng tốt

Đọc số từ trái sang phải, dịch chuyển sang trái và thêm bit hiện tại.


7

JavaScript (ES6), 33 31 byte

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

Chỉnh sửa: Ngắn hơn nhưng ít ngọt hơn: 2 byte được lưu nhờ @ETHproductions.


Như thường lệ, .mapngắn hơn:s=>[...s].map(c=>+c+r+r,r=0)|r
ETHproductions 6/12/2016

@ETHproductions Chức năng của bạn trả về bất cứ thứ gì khác 0?
Neil

Xin lỗi, nó phải làs=>[...s].map(c=>r+=+c+r,r=0)|r
ETHproductions

7

Mê cung , 17 15 byte

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

Hãy thử trực tuyến!

Hình ảnh của mã

Labyrinth là một ngôn ngữ hai chiều, dựa trên ngăn xếp. Trong mê cung, việc thực thi mã đi theo đường dẫn của mã giống như một mê cung với các không gian đóng vai trò như những bức tường và bắt đầu ở ký tự ngoài không gian trên cùng bên trái. Luồng mã được xác định bởi dấu hiệu của đỉnh ngăn xếp. Vì ngăn xếp có các số 0 ẩn ở phía dưới, bốn lệnh đầu tiên ( -+:+) không có hiệu lực.

Vòng lặp bắt đầu tại ,

  • , Đẩy giá trị mã ascii của ký tự đầu vào tiếp theo đến điểm dừng của ngăn xếp hoặc đẩy -1 nếu EOF.
  • _48 đẩy 48 lên đỉnh của ngăn xếp
  • -Pop y, pop x, đẩy x-y. Các hướng dẫn trước có tác dụng trừ 48 từ đầu vào mang lại 0 cho "0" và 1 cho "1".
  • +Pop y, pop x, đẩy x+y.
  • : Nhân đôi đỉnh của ngăn xếp
  • + Điều này và hướng dẫn trước có tác dụng nhân giá trị hiện tại với 2

Vì vậy, phần tròn của mã, thực tế, nhân số hiện tại với 2 và thêm 1 hoặc 0 tùy thuộc vào việc ký tự 1 hoặc 0 được nhập vào.

Đuôi

Nếu đỉnh của ngăn xếp là âm (có nghĩa là EOF đã được tìm thấy), mã sẽ rẽ trái tại đường giao nhau (đi về phía dấu chấm phẩy).

  • `` `Phủ định đỉnh của ngăn xếp để lấy 1
  • ) Lặp lại đỉnh của ngăn xếp để có được 2
  • /Pop y, pop x, đẩy x / y (chia số nguyên). Điều này có tác dụng hoàn tác cuối cùng*2 từ vòng lặp.
  • !Xuất đại diện số nguyên của đỉnh ngăn xếp. Tại thời điểm này, chương trình quay vòng vì nó đi vào ngõ cụt và sau đó thoát ra một lỗi vì nó cố gắng chia cho số không.

Cảm ơn @Martin Ender đã tiết kiệm cho tôi 2 byte (và dạy tôi cách suy nghĩ tốt hơn trong Labyrinth).


Thay vì _48-bạn chỉ có thể làm #%nhưng thật không may, tôi không thấy nó có thể giúp như thế nào với số byte.
Martin Ender

Bạn có thể lưu một byte `)thay vì ;_2mặc dù.
Martin Ender

@MartinEnder, tôi không hiểu bình luận của bạn về #%. Bạn có thể giải thích cách nó hoạt động như một sự thay thế _48-để chuyển đổi từ ascii sang int. Cảm ơn vì tiền )boa. Tôi sẽ thực hiện thay đổi đó.
Robert Hickman

Tại thời điểm đó trong chương trình của bạn luôn có hai giá trị trên ngăn xếp, vì vậy #chỉ là viết tắt của _2. Mặc dù _2%không phải là phương thức chuyển đổi chung cho ASCII sang số nguyên, nhưng nó hoạt động ở đây vì bạn chỉ quan tâm đến hai chữ số đầu tiên có thể. Một sự thay thế sẽ là _1&(vì modulo 2 chỉ đơn giản trích xuất bit có ý nghĩa nhỏ nhất).
Martin Ender

Oh. Thật tuyệt vời. Nhưng vâng tôi không chắc chắn làm thế nào để sử dụng sự thay thế đó ( #%) để rút ngắn tổng thể mã.
Robert Hickman

6

Brain-Flak , 46 , 28 byte

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

Hãy thử trực tuyến!

Nhiều byte được lưu nhờ @Riley!

Vì bộ não không thể lấy đầu vào nhị phân, đầu vào là danh sách '0' và '1'.

Giải trình:

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

Yêu lời giải thích! Thật khó để đọc bộ não mà không có nó :)
Emigna

2
^. Tôi thậm chí không thể đọc các chương trình của riêng mình nếu tôi không để lại cho mình một vài bình luận.
Riley

Bạn có thể giảm xuống còn 32 byte bằng cách loại bỏ toàn bộ phần if và đối với bước "thêm số vào ngăn xếp khác" chỉ cần thêm nó vào (ngăn xếp khác) * 2. ([]){({}[()]<({}<>({}){})><>)}<>
Riley

Và bạn có thể tiết kiệm thêm 4 bằng cách chỉ bật vào lúc bắt đầu và đẩy chiều cao trở lại vào cuối. ([]){{}({}<>({}){})<>([])}<>
Riley

@Riley Ôi trời ơi, thật là thiên tài. Cảm ơn nhiều!
DJMcMayhem

6

Java, 84 79 46 48 byte

  • Phiên bản 3.1

Đã thay đổi thành long/ 48 byte:

s->{long x=0;for(char c:s)x=c-48l+x*2;return x;}
  • Phiên bản 3.0

Đã chơi golf / 46 byte:

s->{int x=0;for(char c:s)x=c-48+x*2;return x;}
  • Phiên bản 2.0

Cảm ơn @Geobits! / 79 byte:

s->{int i=Math.pow(2,s.length-1),j=0;for(char c:s){j+=c>48?i:0;i/=2;}return j;}
  • Phiên bản 1.0

84 byte:

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
đoán tôi nên đã thực hiện một giải pháp lặp đi lặp lại. lulz. làm tốt lắm
Chọc

Là loại đầu vào của bạn Danh sách <Ký tự> hoặc Chuỗi? Nếu đó là cái sau, tôi không biết Java8 có thể làm điều đó! Nếu đó là trước đây được cho phép bởi thách thức?
Chọc

snên char[]. Tôi hy vọng điều đó được cho phép ...
Roman Gräf

Loại trả lại ở đây là gì? Tôi nghĩ rằng nó phải dài bởi vì "Mã phải hỗ trợ các số nhị phân lên đến giá trị số cao nhất mà ngôn ngữ của bạn hỗ trợ" cho mỗi OP nhưng đối với các giá trị nhỏ hơn tôi sẽ nghĩ nó trả về một int
Poke

1
Có lẽ tốt về loại đầu vào cho mỗi này . Có thể muốn thực hiện lần truy cập 2 byte cho đầu ra imo
Chọc

4

Befunge-98, 12 byte

2j@.~2%\2*+

Hãy thử trực tuyến!

Đọc một char tại một thời điểm từ đầu vào, chuyển đổi nó thành 0 hoặc 1 bằng cách lấy giá trị modulo 2 (0 là char (48), 1 là char (49)), sau đó sử dụng thuật toán thông thường là nhân đôi giá trị hiện tại và thêm chữ số mới mỗi lần.

Phần thưởng: Điều này hoạt động với bất kỳ loại chuỗi đầu vào nào, tôi đã cố gắng một thời gian để tìm thấy bất kỳ kết hợp đầu vào vui nhộn nào - nhưng tôi không thể tạo ra bất cứ điều gì (đáng buồn thay, "answer" = 46). Bạn có thể?


LOL. Tôi đã chơi cùng một trò chơi với câu trả lời của tôi. Con số thú vị nhất tôi có thể tạo ra là 666 .
James Holdiness

Đẹp quá Tôi đã không tìm thấy bất cứ điều gì phù hợp cho 666: D Sẽ dễ dàng hơn rất nhiều nếu việc viết hoa có ảnh hưởng đến các giá trị ...
Leo

@James Holdiness - Tôi cũng đã làm như vậy và tôi chỉ tìm thấy 'theleapyear' để mang về 366, bạn thực sự rất tốt.
Teal pelican

4

Javascript (ES7) 41 40 36 byte

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

lấy một chuỗi làm đầu vào

Cạo một byte nhờ vào 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
Sự kết hợp từ phải sang trái của **là kỳ lạ, nhưng công việc tốt đẹp sử dụng nó ở đây. 1<<b.lengthsẽ làm điều tương tự, nhưng nó sẽ yêu cầu dấu ngoặc đơn để không bị phân tích cú pháp như (c*1)<<(b.length+...). Tôi nghĩ bạn có thể lưu một byte bằng cách thay thế b[0]bằng b+b( xem tại đây ).
Sản xuất ETH

4

C # 6, 85 37 36 byte

long b(long n)=>n>0?n%2+2*b(n/10):0;
  • Cảm ơn Kade vì đã tiết kiệm được 41 byte!
  • Thay đổi thành C # 6 đã lưu thêm 7 byte.

Có lẽ điều này có thể cung cấp một số cảm hứng? ;)
Kade

@Kade Nó, cảm ơn! Tôi đã xem xét câu trả lời của Python sử dụng cùng một kỹ thuật tại cùng thời điểm bạn liên kết rằng: DI có thể còn ngắn hơn nữa với C # 6.
Yytsi


3

C, 53

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

Giống như câu trả lời javascript của tôi

Kiểm tra Ideone


Bạn có thể lưu 4 byte bằng cách khai báo vcdưới dạng các biến toàn cục (mặc dù bạn cần thay đổi tên của v, vì nó đã là tên của hàm) như thế này:w=0;c;v(char*s){while(c=*s++)w+=w+c-48;return w;}
Steadybox 6/12/2016

@Steadybox có thể w,c;nhưng tôi không muốn sử dụng toàn cầu khi câu trả lời là một chức năng (ngay cả trong môn đánh gôn)
edc65

@Steadybox Globals mặc định là 0, vì vậy bạn có thể thả =0.
algmyr

3

Perl, 25 byte

-3 byte nhờ @Dom Hastings.

24 byte mã + 1 byte cho -pcờ.

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

Để chạy nó:

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

Giải thích:

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

Đẩy , 10 byte

Lấy đầu vào là danh sách 0/1 trên dòng lệnh : $ pushy binary.pshy 1,0,1,0,1,0.

L:vK2*;OS#

Thuật toán thực sự cho thấy vẻ đẹp của việc có một ngăn xếp thứ hai:

            \ 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

Phương pháp này hoạt động vì ngăn xếp sẽ được nhân đôi số stack length - nlần trước khi đạt số n, sau đó được đổ vào ngăn xếp thứ hai cho lần sau. Đây là những gì quá trình trông giống như cho đầu vào 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 byte

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

Trường hợp kiểm tra cuối cùng có lỗi làm tròn (vì double ), vì vậy nếu bạn cần độ chính xác đầy đủ:

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

với 47 byte.


Tôi không thể kiểm tra điều này, nhưng tôi tin rằng @(x)sum(2.^(find(flip(x)-48)-1))sẽ cho kết quả chính xác cho tất cả các trường hợp cho 32 byte. fliphoạt động như fliplrnếu xlà một chiều.
Stewie Griffin

Giải pháp tốt đẹp! Tôi cũng gặp phải lỗi làm tròn, nhờ sửa lỗi. Định dạng của x là gì? Gọi lật hoặc fliplr trên một số chỉ trả về số đó.
MattWH

x là chuỗi nhị phân, vì vậy hãy gọi nó bằng f=@(x)..; f('1111001010').
Jonas

3

Võng mạc , 12 byte

Số lượng byte giả định mã hóa ISO 8859-1.

+%`\B
¶$`:
1

Hãy thử trực tuyến!

Giải pháp thay thế:

+1`\B
:$`:
1

Giải trình

Điều này có lẽ sẽ dễ giải thích hơn dựa trên phiên bản cũ, ít chơi gôn của tôi và sau đó cho thấy cách tôi rút ngắn nó. Tôi đã sử dụng để chuyển đổi nhị phân thành thập phân như thế này:

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

Cách hợp lý duy nhất để xây dựng một số thập phân trong Retina là bằng cách đếm các thứ (vì Retina có một vài tính năng cho phép nó in một số thập phân đại diện cho một số tiền). Vì vậy, thực sự cách tiếp cận duy nhất có thể là chuyển đổi nhị phân thành đơn nguyên, và sau đó đếm số chữ số đơn nguyên. Dòng cuối cùng thực hiện đếm, vì vậy bốn dòng đầu tiên chuyển đổi nhị phân thành đơn nguyên.

làm sao chúng ta làm việc đó bây giờ? Nói chung, để chuyển đổi từ danh sách các bit thành số nguyên, chúng tôi khởi tạo kết quả 0và sau đó đi qua các bit từ hầu hết đến đáng kể nhất, nhân đôi giá trị chúng tôi đã có và thêm bit hiện tại. Ví dụ: nếu số nhị phân là 1011, chúng tôi thực sự sẽ tính toán:

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

Nơi tôi đã đánh dấu các bit riêng lẻ cho rõ ràng.

Bí quyết để thực hiện điều này một cách đơn giản là a) nhân đôi đơn giản có nghĩa là lặp lại số và b) vì chúng ta đang đếm số 1s ở cuối, chúng ta thậm chí không cần phân biệt giữa 0s và1 s trong quá trình. Điều này sẽ trở nên rõ ràng hơn trong một giây.

Những gì chương trình làm là trước tiên nó thêm dấu phẩy vào đầu làm điểm đánh dấu cho bao nhiêu đầu vào mà chúng tôi đã xử lý:

^
,

Bên trái điểm đánh dấu, chúng ta sẽ có giá trị chúng ta tích lũy (được khởi tạo chính xác thành biểu diễn đơn nhất bằng 0) và bên phải của giá trị sẽ là bit tiếp theo để xử lý. Bây giờ chúng tôi áp dụng thay thế sau trong một vòng lặp:

,(.)
$`$1,

Chỉ cần nhìn vào ,(.)$1,, điều này di chuyển điểm đánh dấu một chút sang bên phải mỗi lần. Nhưng chúng tôi cũng chèn $`, đó là tất cả mọi thứ ở phía trước điểm đánh dấu, tức là giá trị hiện tại, chúng tôi đang nhân đôi. Dưới đây là các bước riêng lẻ khi xử lý đầu vào 1011, trong đó tôi đã đánh dấu kết quả của việc chèn $`phía trên mỗi dòng (nó trống cho bước đầu tiên):

,1011

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

Bạn sẽ thấy rằng chúng tôi đã giữ lại và nhân đôi số 0 cùng với mọi thứ khác, nhưng vì cuối cùng chúng tôi không quan tâm đến họ, nên chúng tôi có thường xuyên nhân đôi số đó không, miễn là số lượng 1là chính xác. Nếu bạn đếm chúng, có 11chúng, chỉ là những gì chúng ta cần.

Vì vậy, điều đó đặt ra câu hỏi làm thế nào để đánh golf này xuống còn 12 byte. Phần đắt nhất của phiên bản 18 byte là phải sử dụng điểm đánh dấu. Mục tiêu là để thoát khỏi điều đó. Chúng tôi thực sự muốn tăng gấp đôi tiền tố của mỗi bit, vì vậy một ý tưởng đầu tiên có thể là:

.
$`$&

Vấn đề là những sự thay thế này xảy ra đồng thời, vì vậy bit đầu tiên không được nhân đôi cho mỗi bit, nhưng nó chỉ được sao chép một lần mỗi lần. Đối với đầu vào, 1011chúng tôi sẽ nhận được (đánh dấu phần được chèn $`):

 _ __ ___
1101011011

Chúng ta vẫn cần xử lý đệ quy đầu vào để tiền tố đầu tiên được nhân đôi được nhân đôi lần thứ hai, v.v. Một ý tưởng là chèn các điểm đánh dấu ở mọi nơi và liên tục thay thế chúng bằng tiền tố:

\B
,
+%`,
¶$`

Sau khi thay thế mỗi điểm đánh dấu bằng tiền tố lần đầu tiên, chúng ta cần nhớ nơi bắt đầu của đầu vào, vì vậy chúng tôi cũng chèn nguồn cấp dữ liệu và sử dụng %tùy chọn để đảm bảo rằng lần tiếp theo$` chỉ chọn mọi thứ lên nguồn cấp dữ liệu gần nhất.

Điều này không hoạt động, nhưng nó vẫn quá dài (16 byte khi đếm 1s ở cuối). Làm thế nào về chúng ta xoay chuyển mọi thứ? Những nơi chúng tôi muốn chèn các điểm đánh dấu được xác định bởi \B(một vị trí giữa hai chữ số). Tại sao chúng ta không chỉ cần chèn tiền tố vào các vị trí đó? Điều này gần như hoạt động, nhưng sự khác biệt là trong giải pháp trước đó, chúng tôi thực sự đã loại bỏ một điểm đánh dấu trong mỗi lần thay thế và điều đó rất quan trọng để làm cho quá trình chấm dứt. Tuy nhiên,\B nhân vật không chỉ là vị trí, vì vậy không có gì bị xóa. chúng ta có thểTuy nhiên dừng\Bthay vì khớp bằng cách chèn một ký tự không có chữ số vào vị trí này. Điều đó biến ranh giới không từ thành ranh giới từ, tương đương với việc loại bỏ ký tự đánh dấu trước đó. Và đó là những gì giải pháp 12 byte thực hiện:

+%`\B
¶$`:

Để hoàn thiện, đây là các bước xử lý riêng lẻ 1011, với một dòng trống sau mỗi bước:

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

Một lần nữa, bạn sẽ thấy rằng kết quả cuối cùng chứa chính xác 11 1giây.

Là một bài tập cho người đọc, bạn có thể thấy cách khái quát này khá dễ dàng đối với các cơ sở khác (đối với một vài byte bổ sung cho mỗi mức tăng trong cơ sở) không?


2

T-SQL, 202 byte

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 byte

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

Chúng tôi đảo ngược số nhị phân của chúng tôi, chia nó thành các chữ số thành phần của nó và tính tổng chúng dựa trên vị trí.


2

Tiện ích Bash + GNU, 29 byte

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

I / O qua stdin / stdout.

Các sedbiểu hiện chia tách lên nhị phân vào mỗi chữ số và xây dựng một biểu thức RPN cho dcđể đánh giá.


2

PowerShell v2 +, 55 byte

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

Cảm thấy quá dài ... Dường như không thể đánh gôn nó xuống - những lời khuyên được đánh giá cao.

Giải trình

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 byte

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

Đệ quy tiết kiệm trong ngày một lần nữa! Mặc dù việc tham số hóa có vẻ hơi dài ...


Vì đó là một "đối số" duy nhất, nên có [...n]cần được đặt trong ngoặc đơn không?
Cyoce

@Cyoce Thật không may, có, hoặc JS ném SyntaxError.
Sản xuất ETH

2

Toán học, 27 13 11 byte

Fold[#+##&]

Chấp nhận một Listbit như là đầu vào (ví dụ {1, 0, 1, 1, 0}- Mathematica 's biểu diễn nhị phân của số 22)


Theo dõi từ nhận xét về câu trả lời của Greg, làm thế nào "chia tất cả các chữ số trong đầu vào" không phải là một hàm chuyển đổi cơ sở?
Martin Ender

@MartinEnder Tôi đang sử dụng nó như Characterschức năng.
JungHwan tối

@MartinEnder Trên thực tế, như đã thấy trong câu trả lời của @ nimi , tôi chỉ có thể chấp nhận danh sách 1 và 0 vì đó là cách duy nhất để biểu thị số nhị phân trong Mathicala , nghĩa là tôi không cần IntegerDigitsở vị trí đầu tiên.
JungHwan tối

Giả định rằng cơ sở 10 là biểu diễn "tự nhiên" của một số nguyên. Một giá trị số nguyên thực tế không có cơ sở ưa thích nào được đính kèm với nó (Tôi đoán bạn có thể nói cách nó được lưu trữ có lẽ là cơ sở 256 hoặc thậm chí có thể là cơ sở 2 nhưng đó là một chi tiết triển khai). Chỉ vì chúng tôi (thông thường) sử dụng cơ sở 10 để viết các số nguyên không có nghĩa là các giá trị nguyên đã có trong cơ sở 10.
Martin Ender

@MartinEnder @ Lynn's Jelly code sử dụng D, hoạt động tương tự nhưIntegerDigits
JungHwan Min

2

Clojure, 114 105 63 41 byte

V4: 41 byte

-22 byte nhờ @cliffroot. Vì digitlà một ký tự, nó có thể được chuyển đổi thành mã thông qua int, sau đó trừ 48 để lấy số thực tế. Bản đồ cũng được bao thanh toán. Tôi không biết tại sao nó có vẻ cần thiết.

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

V3: 63 byte

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

-42 byte (!) Bằng cách nhìn trộm các câu trả lời khác. "Zipping" của tôi rõ ràng là rất ngây thơ. Thay vì tăng 2 lên sức mạnh của vị trí hiện tại, sau đó nhân nó với chữ số hiện tại và thêm kết quả vào bộ tích lũy, nó chỉ cần nhân số tích lũy lên 2, thêm vào chữ số hiện tại, sau đó thêm nó vào bộ tích lũy. Cũng chuyển đổi chức năng khử thành macro để cạo đi một chút.

Cảm ơn @nimi và @Ad Nam!

Ung dung:

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

V2: 105 byte

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

-9 byte bằng cách đảo ngược chuỗi vì vậy tôi không cần phải tạo phạm vi giảm dần khó xử.

V1: 114 byte

Chà, tôi chắc chắn không chiến thắng! Để bảo vệ tôi, đây là chương trình đầu tiên tôi từng viết chuyển đổi giữa các căn cứ, vì vậy tôi phải học cách làm. Nó cũng không giúp Math/powtrả lại gấp đôi yêu cầu chuyển đổi từ và Integer/parseIntkhông chấp nhận một ký tự, vì vậy chữ số cần được bọc trước khi chuyển.

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

Kéo khóa chuỗi với chỉ số giảm dần đại diện cho số vị trí. Giảm trên danh sách kết quả.

Ung dung:

(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 %)Phiên bản cải tiến. Đã chuyển mapmột phần mã trực tiếp vào reduce, thay đổi phương pháp phân tích số nguyên, tạo hàm ngoài với cú pháp lambda tốc ký.
vách đá

@cliffroot intcó thể dùng để phân tích!? Điều đó sẽ hạ gục 10 byte trong mọi thử thách tôi đã thực hiện ở đây lol.
Carcigenicate

Ồ, tôi thấy những gì bạn đang làm. Lấy mã ascii, sau đó trừ đi để lấy giá trị. Tôi đoán điều này sẽ chỉ làm việc trong các trường hợp chọn lọc mà thôi. Oh tốt, cảm ơn vì tiền boa.
Carcigenicate

2

Perl, 21 19 16 + 4 = 20 byte

-4 byte nhờ @Dada

Chạy với -F -p(bao gồm cả không gian thêm sau F). Giá trị ống cho hàm sử dụngecho -n

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

Chạy như echo -n "101010" | perl -F -pE '$\+=$_+$\for@F}{'

Tôi cảm thấy điều này đủ khác với câu trả lời của @ Dada rằng nó xứng đáng với mục nhập riêng của nó.

Giải trình:

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

Điều này sử dụng thuật toán lựa chọn cá nhân của tôi để chuyển đổi nhị phân sang thập phân. Cho một số nhị phân, bắt đầu tích lũy của bạn ở 0 và lần lượt đi qua các bit của nó. Nhân đôi số tích lũy mỗi bit, sau đó thêm chính bit đó vào bộ tích lũy của bạn và kết thúc bằng giá trị thập phân. Nó hoạt động vì mỗi bit cuối cùng được nhân đôi số lần thích hợp cho vị trí của nó dựa trên số lượng bit còn lại trong số nhị phân ban đầu.


Thậm chí ngắn hơn:perl -F -pE '$\+=$_+$\for@F}{'
Dada

Tôi thành thật cười vào lúc này ngắn như thế nào. Cảm ơn bạn.
Gabriel Benamy

Phải, nó khá gọn gàng, được thực hiện tốt!
Dada

2

R (32-bit), 64 byte

Đầu vào cho chức năng nên được đưa ra dưới dạng ký tự. Các chức năng cơ bản của R hỗ trợ số nguyên 32 bit.

Đầu vào:

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

Đầu ra:

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

R (64-bit), 74 byte

Đầu vào cho chức năng nên được đưa ra dưới dạng ký tự. Góibit64 phải được sử dụng cho số nguyên 64 bit.

Đầu vào:

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

Đầu ra:

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

2
Bạn có thể làm: el(strsplit(x,""))thay vì strsplit(x,split="")[[1]]để lưu một vài byte.
Billywob

Cảm ơn rất nhiều! Đặc biệt là đối với elchức năng - tôi đã không nhận thức được nó.
djhurio

2

APL Dyalog , 12 byte

(++⊢)/⌽⍎¨⍞

nhận chuỗi đầu vào

⍎¨ chuyển đổi từng ký tự thành số

đảo ngược

(... )/chèn hàm sau vào giữa các số

++⊢ tổng của các đối số cộng với các đối số đúng


ngn cạo 2 byte.


1

k, 8 byte

Phương pháp tương tự như câu trả lời của Haskell ở trên.

{y+2*x}/

Thí dụ:

{y+2*x}/1101111111010101100101110111001110001000110100110011100000111b
2016120520371234567
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.