Tổng các chất nền nhị phân


16

Thử thách này rất đơn giản, được đưa ra một số thập phân, chuyển đổi thành nhị phân và tính tổng các chuỗi con của số nhị phân, có độ dài ngắn hơn số gốc. Đây là một ví dụ:

Input:
  11
Binary:
  11 -> 1011
Substrings:
  101 = 5
  011 = 3
  10  = 2
  01  = 1
  11  = 3
  1   = 1
  0   = 0
  1   = 1
  1   = 1
Sum:
  5+3+2+1+3+1+0+1+1=17
Output:
  17

Chương trình của bạn nên lấy một số nguyên thập phân duy nhất làm đầu vào và đầu ra tổng của các chuỗi con nhị phân, như đã thấy ở trên. Bạn có thể cho rằng đầu vào sẽ luôn có nhiều hơn hai chữ số trong biểu diễn nhị phân của nó và rằng đầu vào sẽ không gây ra bất kỳ lỗi nào trong quá trình thực hiện chương trình của bạn.

Đây là , mã ngắn nhất tính bằng byte thắng!

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

2  => 1
3  => 2
4  => 3
5  => 5
6  => 7
7  => 9
8  => 7
9  => 10
10 => 14
11 => 17

4
Thật kỳ lạ, việc loại trừ chuỗi con có độ dài đầy đủ là một thách thức bổ sung đáng kể.
Peter Taylor

Câu trả lời:


12

Thạch, 10 7 byte

BṡRḄFS_

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

Làm thế nào nó hoạt động

BṡRḄFS_  Main link. Input: n

B        Convert n to base 2.
  R      Yield [1, ..., n].
 ṡ       Get all overlapping slices of lengths 1 to n.
         This yields empty arrays if the slice size is longer than the binary list.
   Ḅ     Convert each binary list to integer.
    F    Flatten the resulting, nested list.
     S   Compute the sum of the result.
      _  Subtract n from the sum.

Mã hóa nào cung cấp cho bạn 1 byte / char cho chương trình đó?
Toby Speight

1
@TobySpeight Jelly sử dụng trang mã riêng của mình.
một spaghetto

8

Bình thường, 10

sPiR2.:.BQ

Dùng thử trực tuyến hoặc chạy Test Suite

Giải trình:

sPiR2.:.BQ    ##   Q = eval(input())
       .BQ    ##   get binary string of Q
     .:       ##   get all substrings of that
  iR2         ##   convert them all to base 10
sP            ##   sum all but the last element, which is the input number


5

Python 3, 111 ký tự

N=bin(int(input()))[2:];L=len(N);r=range;print(sum(int(n,2)for n in[N[j:j+i]for i in r(1,L)for j in r(L-i+1)]))

EDIT : Giải thích:

N=bin(int(input()))[2:]

Chuyển đổi chuỗi đầu vào thành int, sau đó int thành chuỗi nhị phân và xóa hai ký tự đầu tiên của nó, vì binphương thức trả về một chuỗi theo định dạng0b...

Lấy tất cả các chuỗi con của chuỗi nhị phân, chuyển đổi chúng thành số thập phân bằng cách sử dụng int(n, 2)và tính tổng chúng.

[N[j:j+i]for i in r(1,L)for j in r(L-i+1)]

là một danh sách của tất cả các chuỗi con. Phiên bản bị đánh cắp:

def all_substrings(N):
    result = []
    for i in range(1, len(N)):
        for j in range(len(N) - i + 1):
            result.append(N[j:j+i])
    return result

Hi vọng điêu nay co ich.


4

CJam (22 byte)

Đây là một byte dài hơn câu trả lời tốt nhất hiện tại của CJam, nhưng cách tiếp cận có thể được điều chỉnh theo một số ngôn ngữ khác khá có lợi.

3,ri_2b_,,:).*\+fbW%:-

Bản demo trực tuyến

Phân tích

Giả sử rằng câu hỏi là

tính tổng các chuỗi con của số nhị phân

không có một chút

có độ dài ngắn hơn số gốc

Sau đó, nó không phải là quá khó để chứng minh rằng các bit quan trọng nhất xảy ra với tổng trọng lượng 1*(2^B-1)Blà số bit; bit đáng kể thứ hai xảy ra với tổng trọng lượng 2*(2^(B-1)-1); xuống đến bit đáng kể nhất Bth, xảy ra với tổng trọng lượng B*(2^1-1).

Bây giờ tính đến số trừ của số ban đầu x, chúng tôi kết thúc bằng tổng

sum_i (x & 2^i) * 2^i * 2*(B-i)  -  sum_i (x & 2^i) * (B-i)  -  x

Mổ xẻ

3,        e# Put [0 1 2] on the stack - we'll need it later
ri_       e# Get the input x and copy it
2b        e# Convert the copy to base 2
_,,:).*   e# Pointwise multiply by 1 plus the index
\+        e# Append x to the resulting array, giving A
fb        e# Map a base conversion
W%:-      e# Reverse and fold a subtraction

Việc chuyển đổi sang cơ sở 2 cung cấp phần đầu tiên của tổng cộng chính x; đến cơ sở 1 cho phần thứ hai cộng x; và với cơ sở 0 chỉ cung cấp x, vì vậy, trừ cơ sở-1 khỏi cơ sở-2 x, hủy bỏ s và trừ cơ sở-0 cho kết quả mong muốn.


3

JavaScript (ES6), 78 byte

n=>[...n.toString(2)].map(c=>[...s+=c].map((_,i)=>n-='0b'+s.slice(i)),s='')|-n

Bên ngoài mapxây dựng các chuỗi con hàng đầu của nbiểu diễn nhị phân; một bên trong trích xuất các chuỗi con của các chuỗi con hàng đầu, do đó bao gồm tất cả các chuỗi con có thể, bao gồm cả biểu diễn nhị phân ban đầu.

Mỗi chuỗi con được chuyển đổi từ nhị phân trở lại thập phân và được trừ khỏi đầu vào ban đầu vì điều này ngắn hơn một chút so với việc thêm chúng lại với nhau và trừ đi đầu vào ban đầu.


2

Toán học, 73 70 byte

Tr[FromDigits[#,2]&/@StringCases[#~IntegerString~2,__,Overlaps->All]]&

Chức năng. Số nguyên-> Số nguyên


1
Một toán học đáng tiếc không có công cụ tuyệt vời để xử lý danh sách con.
Một Simmons

1

Võng mạc , 64

.*
$*
+`(1+)\1
$1a
a1
1
r&!M`.*
&!M`.*
^.*

+`1(a*)\b
a$.1$*1;
;

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

Một giai đoạn cấp cao theo mô tả giai đoạn: chuyển đổi số thập phân thành đơn vị, unary thành nhị phân, nhận tiền tố, nhận hậu tố của tiền tố, kết xuất số gốc, chuyển đổi nhị phân thành đơn vị, đếm trở lại. Tôi sẽ viết một mô tả chi tiết hơn một khi tôi đã chơi golf, rất nhiều giai đoạn có vẻ đáng ngờ ...


1

C, 71 byte

f(n){int a=0,m=0,i;for(;++m<n;m+=m)for(i=n;i+i>m;i/=2)a+=i&m;return a;}

Chúng tôi duy trì một tích lũy avà mặt nạ m. Mặt nạ bắt đầu từ 1 và dài hơn một chút mỗi lần xung quanh vòng ngoài. Trong vòng lặp bên trong, một bản sao icủa đầu vào được dịch liên tiếp sang phải cho đến khi nó ngắn hơn mặt nạ, tích lũy giá trị mặt nạ mỗi lần.

Chương trình kiểm tra

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
    while (*++argv) {
        int n = atoi(*argv);
        printf("%d -> %d\n", n, f(n));
    }
    return 0;
}

Đầu ra thử nghiệm

./73793 $(seq 0 11)
0 -> 0
1 -> 0
2 -> 1
3 -> 2
4 -> 3
5 -> 5
6 -> 7
7 -> 9
8 -> 7
9 -> 10
10 -> 14
11 -> 17

1

C #, 148 byte

int x(int i){int s,r=0,j=i,p=System.Convert.ToString(i,2).Length+1,k;for(;--p>-1;){k=j;s=-1;for(;++s<p;)r+=(k>>=1);j=(i&((1<<p-1)-1))<<1;}return r;}

Hoặc, nếu tôi thêm Nhập "bằng cách sử dụng hệ thống tĩnh.Math;" sau đó 138 với

int x(int i){int s,r=0,j=i,p=(int)Round(Log(i,2)+1.49,0),k;for(;--p>-1;){k=j;s=-1;for(;++s<p;)r+=(k>>=1);j=(i&((1<<p-1)-1))<<1;}return r;}

Các ngôn ngữ OOP như C # sẽ không giành chiến thắng trong cuộc đua như vậy, nhưng dù sao tôi cũng muốn thử. Dưới đây là một phiên bản + thử nghiệm đẹp hơn.

class Program
{
    // Tester: 50 bytes
    static void Main(string[] args)
    {
        int i=2;
        do System.Console.WriteLine($"{i} -> {x(i++)}"); while (i < 12);
        System.Console.Read();
    }
    // Function: 65 bytes (size according to ILDASM.exe)
    static int x(int iOrg)
    {
        int pos, shift, retVal=0, iPrev=iOrg, iTemp;
        pos = System.Convert.ToString(iOrg, 2).Length;
        do {
            iTemp = iPrev; shift = 0;
            do retVal += (iTemp >>= 1); while (++shift < pos);
            iPrev = (iOrg & ((1 << pos - 1) - 1)) << 1;
        } while (--pos > -1); 
        return retVal;
    }
}

Do-while lồng nhau thêm giá trị dịch chuyển phải của iTemp (sau khi gán nó) miễn là shift + 1 nhỏ hơn thì pos. Dòng tiếp theo tính toán giá trị dịch chuyển tiếp theo của iPrev

x1 = 1 << p -1; // 1 << 4 -1 = 8 [1000]
x2 = x1 - 1;    // 8 -  1 = 7    [0111]
x3 = i & x2;    // 1011 & 0111 = 0011 
x4 = x3 << 1;   // 0011 << 1 = 00110
i2 = x4;

x1 und x2 tính toán mặt nạ, x3 áp dụng nó và sau đó dịch chuyển trái, vì chữ số cuối cùng luôn bị loại bỏ. Đối với 11, nó trông như thế này:

START -> _1011[11]
101
10
1   -->  X0110[6], r=0+5+2+1=8
 011
 01
 0  -->  XX110[6], r=8+4=12
  11
  1 -->  XXX10[2], r=12+4=16
   1 ->  XXXX0[X], r=16+1=17

Tôi biết, hầu hết các câu trả lời trong C cũng hoạt động liền mạch trong C # (@ Tony-Speight hoạt động không có vấn đề), nhưng tôi sẽ bất chấp mục đích. Ngoài ra, tôi đã không xem xét các bình luận (tốt, ngoại trừ các tiêu đề Bold) cho đến khi tôi tự hoàn thành, do đó không có nguy cơ làm điều đó "như C".
DW.com

0

PowerShell v2 +, 138 byte

param($a)$a=[convert]::ToString($a,2);(($b=$a.length-1)..1|%{$l=$_;0..($b-$l+1)|%{[convert]::ToInt32($a.substring($_,$l),2)}})-join'+'|iex

Ôi. Chuyển đổi sang / từ nhị phân là tốn kém.

Nhận đầu vào $a, sau đó sử dụng lệnh gọi .NET[convert]::ToString($a,2) để biến nó thành biểu diễn nhị phân. Từ đó, chúng ta trải qua hai vòng lặp - lần đầu tiên đếm ngược từ cuối chuỗi xuống 1và lần thứ hai đếm ngược từ trên xuống 0. (Đầu tiên là thời gian của một chuỗi con kéo ra và thứ hai là chỉ số của vị trí trong chuỗi để bắt đầu chuỗi con.) Chúng tôi đặt một trình trợ giúp $ldọc theo đường đi để đi qua vòng lặp bên trong.

Bên trong vòng lặp bên trong, chúng tôi sử dụng một lệnh gọi .NET[convert]::ToInt32() khác để chuyển đổi số thích hợp .substring()từ cơ sở 2thành số nguyên. Mỗi người sau đó được để lại trên đường ống. Chúng tôi gói gọn tất cả những thứ đó bằng parens ()-joinchúng cùng với một +, sau đó đưa nó ra iex(viết tắt Invoke-Expressionvà tương tự-ish to eval).

Tôi nghĩ rằng về mặt kỹ thuật này đòi hỏi v2 hoặc mới hơn để gọi đúng các cuộc gọi .NET.

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.