ผลรวมของสารตั้งต้นไบนารี


16

ความท้าทายนี้เป็นเรื่องง่ายกำหนดตัวเลขทศนิยมให้แปลงเป็นเลขฐานสองและคำนวณผลรวมของสตริงย่อยของเลขฐานสองซึ่งความยาวจะสั้นกว่าหมายเลขเดิม นี่คือตัวอย่าง:

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

โปรแกรมของคุณควรใช้จำนวนเต็มทศนิยมเดียวเป็นอินพุตและเอาต์พุตผลรวมของสตริงย่อยไบนารีดังที่เห็นด้านบน คุณอาจสมมติว่าอินพุตจะมีตัวเลขมากกว่าสองหลักเสมอในการแทนค่าไบนารี่ของมันและในอินพุตจะไม่ทำให้เกิดข้อผิดพลาดใด ๆ ระหว่างการทำงานของโปรแกรมของคุณ

นี่คือรหัสที่สั้นที่สุดในหน่วยไบต์ชนะ!

กรณีทดสอบ:

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

4
อยากรู้อยากเห็นการยกเว้นซับสตริงเต็มความยาวเป็นสิ่งที่ท้าทายอย่างมาก
Peter Taylor

คำตอบ:


12

เยลลี่10 7 ไบต์

BṡRḄFS_

ลองออนไลน์!

มันทำงานอย่างไร

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.

การเข้ารหัสใดที่ให้ 1 ไบต์ / อักขระสำหรับโปรแกรมนั้น
Toby Speight



6

CJam, 27 21 ไบต์

ตะโกนถึง Dennis ที่ช่วยฉันประหยัด 6 ไบต์!

q~:Q{)Q2bew2fb~}%1bQ-

ใช้งานได้กับ CJam เวอร์ชันล่าสุดเท่านั้น (มีให้ใน TIO) ลองออนไลน์ !

เวอร์ชั่นเก่า:

qi2b_,,0-\f{ew}{{2b}%}%e_:+

ลองมันออนไลน์


5

Python 3, 111 ตัวอักษร

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)]))

แก้ไข : คำอธิบาย:

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

แปลงอินพุตสตริงเป็น int จากนั้น int เป็นสตริงไบนารีและลบอักขระสองตัวแรกเนื่องจากbinวิธีการส่งคืนสตริงในรูปแบบของ0b...

ใช้สตริงย่อยทั้งหมดของสตริงไบนารีแปลงเป็นทศนิยมโดยใช้int(n, 2)และหาผลรวม

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

เป็นรายการของสตริงย่อยทั้งหมด เวอร์ชันที่ไม่ถูกปรับแต่ง:

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

หวังว่านี่จะช่วยได้


4

CJam (22 ไบต์)

นี่คือหนึ่งไบต์ที่ยาวกว่าคำตอบ CJam ที่ดีที่สุดในปัจจุบัน แต่วิธีนี้สามารถปรับให้เข้ากับภาษาอื่นได้บ้าง

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

การสาธิตออนไลน์

การวิเคราะห์

สมมติว่าคำถามคือ

คำนวณผลรวมของสตริงย่อยของเลขฐานสอง

โดยไม่ต้องบิต

ความยาวสั้นกว่าหมายเลขเดิม

จากนั้นไม่ยากเกินไปที่จะแสดงว่าบิตที่สำคัญที่สุดเกิดขึ้นกับน้ำหนักรวม1*(2^B-1)ซึ่งBเป็นจำนวนบิต บิตสองมากที่สุดอย่างมีนัยสำคัญเกิดขึ้นกับน้ำหนักรวม2*(2^(B-1)-1); ลงไปที่บิตที่สำคัญที่สุดของ Bth ซึ่งเกิดขึ้นกับน้ำหนักรวมB*(2^1-1)มากที่สุดอย่างมีนัยสำคัญซึ่งเกิดขึ้นกับน้ำหนักรวม

เมื่อคำนึงถึงการลบจำนวนเดิมxเราก็จะได้จำนวนรวม

sum_i (x & 2^i) * 2^i * 2*(B-i)  -  sum_i (x & 2^i) * (B-i)  -  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

การแปลงไปยังฐาน 2 จะช่วยให้ส่วนแรกของผลรวมบวกหลักx; ไปที่ฐาน 1 ให้ส่วนที่สองบวกx; และฐาน 0 ให้เพียงแค่xลบฐาน 1 จากฐาน -2 xลบ s และลบฐาน 0 ให้ผลลัพธ์ที่ต้องการ


3

JavaScript (ES6), 78 ไบต์

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

ชั้นนอกmapสร้างซับสเตรตชั้นนำของnเป็นตัวแทนไบนารี ด้านในจะแยกสตริงย่อยที่ต่อท้ายของสตริงย่อยชั้นนำดังนั้นจึงครอบคลุมซับสตริงทั้งหมดที่เป็นไปได้รวมถึงการแสดงไบนารีดั้งเดิม

สตริงย่อยแต่ละอันจะถูกแปลงจากไบนารีกลับเป็นทศนิยมและลบออกจากอินพุตต้นฉบับเนื่องจากสั้นกว่าการรวมเข้าด้วยกันเล็กน้อยและลบอินพุตต้นฉบับ


2

Mathematica, 73 70 ไบต์

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

ฟังก์ชัน Integer-> จำนวนเต็ม


1
นักคณิตศาสตร์น่าสงสารไม่มีเครื่องมือที่ยอดเยี่ยมสำหรับการจัดการกับรายการย่อย
Simmons

1

เรติน่า 64

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

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

ลองออนไลน์!

สเตจระดับสูงโดยคำอธิบายสเตจ: แปลงทศนิยมให้เป็นเอกภาพ, เป็นเอกเทศเป็นไบนารี, รับส่วนนำหน้า, รับส่วนต่อท้ายของคำนำหน้า, ถ่ายโอนหมายเลขเดิม, แปลงไบนารีเป็นเอกภาพ, ส่งกลับจำนวน ฉันจะเขียนคำอธิบายโดยละเอียดเพิ่มเติมเมื่อฉันเล่นกอล์ฟเสร็จแล้วขั้นตอนเหล่านี้ดูน่าสงสัย ...


1

C, 71 ไบต์

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;}

เรายังคงสะสมและหน้ากากa mหน้ากากเริ่มต้นที่ 1 และยาวขึ้นหนึ่งรอบในแต่ละรอบนอก ในลูปด้านในสำเนาiของอินพุตจะเลื่อนไปทางขวาอย่างต่อเนื่องจนกระทั่งมันสั้นกว่ามาสก์และสะสมค่ามาสก์ในแต่ละครั้ง

โปรแกรมทดสอบ

#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;
}

ทดสอบผลลัพธ์

./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 ไบต์

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;}

หรือถ้าฉันเพิ่มการนำเข้า "using Static System.Math;" จากนั้น 138 กับ

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;}

ภาษา OOP เช่น C # จะไม่ชนะการแข่งขัน แต่ฉันต้องการลองต่อไป นี่คือรุ่นทดสอบที่สวยงามมากขึ้น

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;
    }
}

สิ่งที่ซ้อนกันทำในขณะนั้นเพิ่มมูลค่าที่ถูกกะขวาของ iTemp (หลังจากกำหนดมัน) ตราบใดที่การ Shift + 1 มีขนาดเล็กลงจะทำให้เกิด POS บรรทัดถัดไปจะคำนวณค่าที่เลื่อนถัดไปของ 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 และ x2 คำนวณหน้ากาก, x3 ใช้กับมันแล้วเลื่อนไปทางซ้ายเนื่องจากหลักสุดท้ายจะลดลงเสมอ สำหรับ 11 ดูเหมือนว่า:

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

ฉันรู้ว่าคำตอบส่วนใหญ่ใน C ทำงานได้อย่างราบรื่นใน C # เช่นกัน (@ Tony-Speight ทำงานได้โดยไม่มีปัญหา) แต่ฉันว่าจะท้าทายวัตถุประสงค์ นอกจากนี้ฉันไม่ได้ดูความคิดเห็น (ดียกเว้นส่วนหัวที่เป็นตัวหนา) จนกว่าฉันจะทำตัวเองให้เสร็จดังนั้นจึงไม่มีอันตรายที่จะทำเช่น "C"
DW.com

0

PowerShell v2 +, 138 ไบต์

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

Ooof การแปลงไปเป็น / จากไบนารีนั้นมีราคาแพง

รับอินพุต$aจากนั้นใช้การเรียก. NET[convert]::ToString($a,2)เพื่อเปลี่ยนเป็นการแสดงแบบไบนารี จากนั้นเราจะไปผ่านสอง loops - นับถอยหลังแรกจากสิ้นลงสตริงไปและข้อหาที่สองเพิ่มขึ้นจาก1 0(อันแรกคือระยะเวลาของสตริงย่อยที่จะดึงออกและอันที่สองคือดัชนีของตำแหน่งในสตริงที่จะเริ่มซับสตริง) เราตั้งค่าตัวช่วย$lตามวิธีการส่งผ่านไปยังวงใน

ภายในลูปด้านในเราใช้การเรียก. NET[convert]::ToInt32()อีกครั้งเพื่อแปลงค่าที่เหมาะสม.substring()จากฐาน2เป็นจำนวนเต็ม แต่ละอันจะถูกทิ้งไว้บนท่อ เราแค็ปซูลทั้งหมดที่มี parens ()และ-joinพวกเขาพร้อม+แล้วโยนออกว่าiex(สั้นInvoke-Expressionและคล้าย-ish ไปeval)

ฉันคิดว่านี่เป็นเทคนิคที่ต้องใช้ v2 หรือใหม่กว่าเพื่อเรียกการโทร. NET อย่างถูกต้อง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.