Розведені цілі суми


26

Позитивне ціле число можна розбавити , вставивши 0між двома бітами в його бінарне розширення. Це означає, що nчисло -біт має n-1розрідження, які не обов'язково є усіма різними.

Наприклад, для 12(або 1100в двійкових) розведення є

11000 = 24
   ^

11000 = 24
  ^

10100 = 20
 ^

У цьому виклику ми беремо суму всіх розбавлень, виключаючи початкове число. Бо 12, якщо взяти суму 24, 24, 20результатів 68, таким 68повинен бути результат для 12.

Виклик

Враховуючи додатне ціле число n > 1як вхід, виведіть / поверніть розведену суму, як пояснено вище.

Приклади

in    out
---   ---
2       4
3       5
7      24
12     68
333  5128
512  9216

Правила

  • Можна вважати, що вхід і вихід відповідають цілому цілому типу вашої мови.
  • Введення та вихід можуть бути задані у будь-якому зручному форматі .
  • Прийнятна або повна програма, або функція. Якщо функція, ви можете повернути вихід, а не надрукувати його.
  • Стандартні лазівки заборонені.
  • Це тому діють усі звичайні правила гольфу, і найкоротший код (у байтах) виграє.

Чи містить "будь-який зручний формат" двійковий рядок?
Кудлатий

1
@Shaggy "Будь-який зручний формат" призначений включати методи введення / виводу, а не формат . Тому я хочу сказати "ні". Ви повинні приймати введення як ціле число або рядок, що представляє це ціле число.
AdmBorkBork

Приємний виклик!
Маніш Кунду

1
Ця послідовність на даний момент (30 січня 2018 року) не в OEIS
Джузеппе

Відповіді:


12

Python 2 , 43 39 байт

f=lambda n,i=2:n/i and n*2-n%i+f(n,i*2)

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


Як?

Кожен виклик рекурсивної функції обчислює одне розведення. Положення вставленого 0є log2(i). Функція повторюється, поки не iстане більшою, ніж nі вставка буде ліворуч від числа. Якщо i>n, n/iоцінює до 0, що є хибним значенням у Python.

n*2зміщує всю двійкову цифру наліво наліво n%iабо n % 2**(position of insertion)обчислює значення частини, яка не повинна зміщуватися вліво. Це значення віднімається від зміщеного числа.

Приклад (n = 7)

call       n/i          bin(n)  n*2     n%i   dilution       return value

f(7, i=2)  3 => truthy  0b111   0b1110  0b1   0b1101 = 13    13 + f(7, 2*2) = 13 + 11 = 24
f(7, i=4)  1 => truthy  0b111   0b1110  0b11  0b1011 = 11    11 + f(7, 4*2) = 11 + 0 = 11
f(7, i=8)  0 => falsy                                        0

7

Желе , 11 байт

BJṖ2*ɓdḅḤ}S

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

Як це працює

BJṖ2*ɓdḅḤ}S  Main link. Argument: n (integer)

B            Binary; convert n to base 2. This yields a digit array A.
 J           Indices; yield [1, ..., len(A)].
  Ṗ          Pop; remove the last element, yielding [1, 2, ..., len(A)-1].
   2*        Elevate 2 to these powers, yielding [2, 4, ..., 2**(len(A)-1)].
             Let's call the result B.
     ɓ       Begin a new, dyadic chain, with left argument n and right argument B.
      d      Divmod; yield [n/b, n%b], for each b in B.
        Ḥ}   Unhalve right; yield 2b for each b in B, i.e., [4, 8, ..., 2**len(A)].
       ḅ     Unbase; convert each [n/b, n%b] from base 2b to integer, yielding
             (2b)(n/b) + (n%b).
          S  Take the sum.

5

MATL , 13 байт

tZl:W&\5ME*+s

Спробуйте в MATL Online! Або перевірити всі тестові випадки .

Пояснення

Розглянемо вклад 12як приклад.

t     % Implicit input. Duplicate
      % STACK: 12, 12
Zl    % Binary logarithm
      % STACK: 12, 3.584962500721156
:     % Range (rounds down)
      % STACK: 12, [1 2 3]
W     % Power with base 2, element-wise
      % STACK: 12, [2 4 8]
&\    % 2-output modulus, element-wise: pushes remainders and quotients
      % STACK: [0 0 4], [6 3 1]
5M    % Push array of powers of 2, again
      % STACK: [0 0 4], [6 3 1], [2 4 8]
E     % Multiply by 2
      % STACK: [0 0 4], [6 3 1], [4 8 16]
*     % Multiply, element-wise
      % STACK: [0 0 4], [24 24 16]
+     % Add, element-wise
      % STACK: [24 24 20]
s     % Sum of array. Implicit display
      % STACK: 68

4

C,  58  56 байт

Дякуємо @Dennis за збереження двох байтів!

s,k;f(n){for(s=0,k=2;k<=n;k*=2)s+=n/k*k*2+n%k;return s;}

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

C (gcc) , 50 байт

s,k;f(n){for(s=0,k=2;k<=n;)s+=n%k+n/k*(k+=k);k=s;}

Повернення k=s;не визначеним поведінкою, але працює з gcc, коли оптимізація відключена. Крім того, n%k+n/k*(k+=k)має невказану поведінку , але, схоже, добре працює з gcc.

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


s,k;f(n){for(s=0,k=2;k<=n;)s+=n%k+n/k*(k*=2);return s;}(55 байт)
Кевін Кройсейсен

1
Немає відомостей, хто з них оцінюється першим n%kабо n/k*(k*=2).
Steadybox

1
@KevinCruijssen Яка сторона оцінюється першою, залишається не визначеною. C - це так ...
Steadybox

2
Ах, я бачу, ви дійсно додали це у своїй відповіді. Я не знав, що така не визначена поведінка трапилася в C. У мене є три години досвіду роботи в С, тому я ледве нічого про це не знаю. TIL :) У Java for(s=0,k=2;k<=n;)s+=n%k+n/k*(k*=2);return s;це абсолютно добре, і n%kвін завжди буде оцінюватися раніше, n/k*(k*=2)а n/kтакож буде оцінюватися раніше k*=2. Дякую за пояснення. (Я зараз
видалю

Я люблю використовувати UB в якості функції. А гольф з кодом на мові реального життя все одно повинен бути в іншій категорії :)
Regis Portalez

4

Желе , 9 8 байт

BḊḄÐƤạḤS

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

B                        to binary          42 -> 1 0 1 0 1 0
 Ḋ                       drop first                 0 1 0 1 0
  ḄÐƤ                    each suffix to decimal   10 10 2 2 0
      Ḥ                  double the input                  84
     ạ                   absolute difference   74 74 82 82 84
       S                 add them up                      396

І навпаки B¹ƤṖ+BḄS: отримайте префікси, залиште останні, додайте їх до введення та підсумовуйте.


4

J , 20 15 14 байт

+/@}:@:+[\&.#:

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

15 байт

1#.-,+:-#.\.@#:

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

     +:             Input×2
       -            Subtract
        #.\.@#:     The list of binary suffixes of input (in decimal)
   -,               Append negative input
1#.                 Add them up

чому працює формула подвійний мінус? чому це рівнозначно розведенням?
Йона

1
Розведення @Jonah - це додавання до числа певного двійкового префіксу (число «округлене вниз»), яке еквівалентно додаванню цілого числа до себе (і префікса, і решти), а потім віднімання залишку.
FrownyFrog

4

Japt , 12 11 байт

¢¬£¢iYTÃÅxÍ

Спробуй це


Пояснення

                 :Implicit input of integer U
¢                :Convert to base-2 string
 ¬               :Split to an array of individual characters/digits
  £    Ã         :Map over the elements, with Y being the current 0-based index
   ¢             :  Convert U to a base-2 string
    iYT          :  Insert a 0 in that string at index Y
        Å        :Slice off the first element of the array
          Í      :Convert each element to a base-10 integer
         x       :Reduce by addition

3

JavaScript (ES6), 41 40 байт

Збережено 1 байт завдяки Mr.Xcoder

f=(n,k=1)=>k<n&&(n&k)+2*(n&~k)+f(n,k-~k)

Тестові справи


3

Сітківка , 53 50 47 байт

.+
*
+`(_+)\1
$1O
O_
_
L$`\B
$`O$'
+%`\B
¶$`¶
_

Спробуйте в Інтернеті! Посилання включає тестові випадки. Редагувати: збережено 3 байти завдяки @MartinEnder. Пояснення:

.+
*
+`(_+)\1
$1O
O_
_

Перетворіть з десяткової в двійкову, але використовуючи O для подання 0, оскільки це не цифра, а _ для представлення 1, оскільки це символ повторення за замовчуванням у Retina 1.

L$`\B
$`O$'

Вставте O між кожною парою цифр і отримайте результати у вигляді списку.

+%`\B
¶$`¶

Перетворити з бінарного в одинарне. (Ця конверсія створює додаткові Os, але нас це не хвилює.)

_

Підсумовуйте та конвертуйте в десяткові.


Перетворення двійкового в десяткове в 12 байтів (збереження 3): tio.run/##K0otycxLNPz/… Дивіться цю відповідь, як це працює.
Мартін Ендер

@MartinEnder Спасибі, я продовжую забувати про це. (Я також трохи розчарувався, що альтернативна версія працює лише на одне число.)
Ніл,

Ну, у випадку, коли у вас є кожен номер у своєму рядку, ви можете змусити його працювати з додатковим %. Якщо це складніше, вам знадобиться щось на кшталт /[O_]+/_.
Мартін Ендер

2

Pyth , 13 байт

smiXd.BQZ2Ssl

Спробуйте тут!

Пояснення

smiXd.BQZ2Ssl | Повна програма.

           сл | Логарифм бази-2 вхідного сигналу, введений у ціле число.
          S | Створіть цілий діапазон [1 ... флогаризований логарифм].
 м | І відобразити функцію над нею.
------------ + - + ----------------------------------- ------------------
  iXd.BQZ2 | Функція для відображення (використовує змінну d).
     .BQ | У двійковому поданні вхідних даних ...
   XZ | ... Вставте нуль ...
    d | ... За індексом d.
  i 2 | І перетворити результат з бази 2 в ціле число.
------------ + - + ----------------------------------- ------------------
s | Підсумуйте отриманий список.

2

Желе , 10 байт

BµLḤ_J’×µḄ

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

Наразі не найкоротший, але це може бути, якщо є шлях Bµ µḄ...

Пояснення

BµLḤ_J’×µḄ    Main link. Argument: n (integer)
B             Binary; convert n to an binary of binary digits. Call this A.
 µ            Start a new monadic link with argument A.
  L           Length; yield len(A). We'll call this l.
   Ḥ          Unhalve; yield l * 2.
     J        Length range; yield [1, 2, ..., l].
    _         Subtract; yield [l*2 - 1, l*2 - 2, ..., l].
      ’       Decrement; subtract one from each item.
       ×      Multiply each item by the corresponding item in A. Call this B.
        µ     Start a new monadic link with argument B.
         Ḅ    Unbinary; convert from a binary array to a decimal.

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

1111

Як пояснено викликом, він хоче, щоб ми отримали суму цих двійкових чисел:

10111  = 2^4 + 2^2 + 2^1 + 2^0
11011  = 2^4 + 2^3 + 2^1 + 2^0
11101  = 2^4 + 2^3 + 2^2 + 2^0

Однак нам насправді не потрібно вставляти нулі: "небінарний" атом Джеллі буде приймати числа, крім простого 0і 1. Коли ми дозволяємо собі використовувати 2, ця модель стає простішою:

2111   = 2*2^3 + 1*2^2 + 1*2^1 + 1*2^0
2211   = 2*2^3 + 2*2^2 + 1*2^1 + 1*2^0
2221   = 2*2^3 + 2*2^2 + 2*2^1 + 1*2^0

Коли ми підсумовуємо цифри в кожному стовпчику, отримуємо

6543   = 6*2^3 + 5*2^2 + 4*2^1 + 3*2^0 = 48 + 20 + 8 + 3 = 79.

Трюк, який використовує ця відповідь, полягає в генеруванні цього шаблону та помноженні кожної цифри на відповідну цифру в оригіналі, щоб скасувати необхідні стовпці. 12, наприклад, буде представлено як

 1100
×6543
=6500  = 6*2^3 + 5*2^2 + 0*2^1 + 0*2^0 = 48 + 20 + 0 + 0 = 68.


1

Лушпиння , 13 12 байт

-1 байт завдяки @Mr. Xcoder!

ṁḋ§z·+Θḣotṫḋ

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

Пояснення

ṁḋ§z·+Θḣ(tṫ)ḋ  -- example input: 6
            ḋ  -- convert to binary: [1,1,0]
  §            -- fork argument
        (tṫ)   -- | tail of tails: [[1,0],[0]]
       ḣ       -- | heads: [[1],[1,1],[1,1,0]]
   z           -- and zipWith the following (example with [1,0] [1])
    · Θ        -- | prepend 0 to second argument: [0,1]
     +         -- | concatenate: [1,0,0,1]
               -- : [[1,0,1,0],[1,1,0,0]]
ṁ              -- map the following (example with [1,0,1,0]) and sum
 ḋ             -- | convert from binary: 10
               -- : 22


1

Піп , 21 18 байт

2*a-a%2**_MS1,#TBa

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

Пояснення

Зателефонуйте на наш номер введення a. Для кожного бінарного індексу, iв який ми хочемо вставити нуль, ми можемо обчислити біти, що знаходяться ліворуч від точки вставки, як a // 2**i(де //це ціле ділення і **є експоненціацією), біти справа від точки вставки як a % 2**i, а отже, розведене ціле число як 2 * (a // 2**i) * 2**i + (a % 2**i). Але (a // 2**i) * 2**iце дорівнює a - (a % 2**i), і тому ми можемо переставити на більш коротку формулу: 2 * (a - a % 2**i) + a % 2**i= 2 * a - a % 2**i.

2*a-a%2**_MS1,#TBa
                       a is 1st command-line argument (implicit)
               TBa     Convert a to binary
              #        Length of the binary expansion
            1,         Range from 1 up to (but not including) that number
          MS           Map this function to the range and sum the results:
2*a-a%2**_              The above formula, where _ is the argument of the function
                       The final result is autoprinted

1

R , 141 48 байт

function(n,l=2^(1:log2(n)))sum(n%%l+(n%/%l*2*l))

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

Або я роблю щось по-справжньому неправильно, або R просто жахливо при маніпуляціях. Перенесення підходу Луїса Мендо - це легко, правильно та головно.

Але якщо ви дійсно хочете розібратися з бітовими операціями, MickyT запропонував наступні 105 байт:

function(i)sum(sapply(1:max(which(b<-intToBits(i)>0)),function(x)packBits(head(append(b,F,x),-1),"i")))-i

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


Ось 111 байт, на який я впевнений, що ви можете взяти ще кілька.
MickyT

@MickyT Привіт! дуже приємно, хоча перенос зовсім іншого підходу краще!
Джузеппе


1

Пакетна, 92 77 байт

@set/an=2,t=0
:l
@if %1 geq %n% set/at+=%1*2-(%1%%n),n*=2&goto l
@echo %t%

Редагувати: перемикається на ту саму формулу, що і всі інші.




0

Attache , 57 байт

Sum##UnBin=>{Join[Join=>_,"0"]}=>SplitAt#1&`:@{#_-1}##Bin

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

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

Пояснення

Ось розширена версія:

Define[$joinByZero, {Join[Join=>_,"0"]}]

Define[$insertionPoints,
    SplitAt#1&`:@{#_-1}
]

Define[$f,
Sum##UnBin=>joinByZero=>insertionPoints##Bin
]

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


0

J , 33 байти

1#.[:}:#.@(<\;@(,0;])"0<@}.\.)@#:

Швидше за все, є багато місця для подальшого гольфу.

Як?

@#: перетворити у двійкові та

<@}.\. - знайдіть усі достатки, скиньте першу цифру з кожного і поле

<\ - знайдіть усі префікси та встановіть їх у вікні

(,0;])"0 - до кожного префікса додайте 0, а потім додайте відповідний обезголовлений суфікс

;@ raze (скасувати)

1#.[:}:#.@ - перетворити в десятковий, скоротити і суму

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.