Calcular a soma binária de uma palavra

22

Pegue uma string scontendo caracteres ASCII imprimíveis como entrada e produza sua "soma binária dividida". Precisa de uma explicação?

Como você obtém a soma binária dividida?

Usaremos a string A4como exemplo na explicação a seguir.

  • Converta os caracteres em binários, tratando cada letra como um caractere ASCII de 7 bits

    A -> ASCII 65 -> 1000001
    4 -> ASCII 52 -> 0110100
    
  • Concatenar os números binários em um novo número binário

    A4 -> 1000001 & 0110100 -> 10000010110100
    
  • Divida o novo número binário em blocos, onde nenhum 1pode ter um 0à esquerda. Você não deve dividir 1s consecutivos .

    10000010110100 -> 100000, 10, 110, 100
    
  • Converta esses números binários em decimal

    100000, 10, 110, 100 -> 32, 2, 6, 4
    
  • Tome a soma destes números:

    32 + 2 + 6 + 4 = 44
    

Portanto, a saída para a string A4deve ser 44.


Casos de teste:

a
49

A4
44

codegolf
570

Hello, World!
795
Stewie Griffin
fonte
2
Eu acho que esse teria sido um desafio melhor sem a etapa de conversão ASCII, apenas usando o número (decimal) após a etapa 2 como entrada.
Xnor
Bem, 8372na verdade.
Xnor
1
@ xnor, você pode estar certo, e seria mais limpo. Eu me diverti resolver isso em Octave, porém, e espero que outros irão desfrutar de resolvê-lo também :)
Stewie Griffin

Respostas:

12

Python 2 , 86 81 76 bytes

-5 bytes graças Adnan
-5 bytes graças xnor

s=0
for c in input():s=s*128+ord(c)
print eval(bin(s).replace('01','0+0b1'))

Experimente online!

for c in input():s=s*128+ord(c)para fazer a conversão ASCII numericamente, onde *128é usado o turno esquerdo s7 vezes (etapas 1 e 2)
eval(('0'+new_bin).replace('01','0+0b1'))para dividir e somar (etapas 3, 4 e 5)

Cajado
fonte
Bom truque com o eval! Fazer a conversão ASCII numericamente salva alguns bytes.
xnor 14/05
7

Gelatina , 13 bytes

Oḅ128BŒg;2/ḄS

Experimente online!

Como funciona

Oḅ128BŒg;2/ḄS  Main link. Argument: s (string)

O              Ordinal; map characters to their code points.
 ḅ128          Unbase 128; convert the resulting list from base 128 to integer.
     B         Binary; Convert the resulting integer to base 2.
      Œg       Group consecutive, equal bits.
        ;2/    Concatenate all non-overlapping pairs.
           Ḅ   Unbinary; convert from base 2 to integer.
            S  Take the sum.
Dennis
fonte
Eu já perdi esse truque de conversão de base antes.
Jonathan Allan
Ah, bom truque mesmo!
Adnan
6

MATL , 14 bytes

YB!'1+0*'XXZBs

Experimente online!

Explicação

Considere a entrada 'A4'como um exemplo.

YB        % Implicit input. Convert to binary using characters '0' and '1'. 
          % Gives a char matrix, where each row corresponds to a number
          % STACK: ['1000001'; '0110100']
!         % Transpose. This is necessary because MATL uses column-major 
          % order when linearizing a matrix into a vector
          % STACK: ['10'; '01'; '01'; '00'; '01'; '00'; '10']
'1+0*'    % Push this string: regexp pattern
          % STACK: ['10'; '01'; '01'; '00'; '01'; '00'; '10'], '1+0*'
XX        % Regexp. Linearizes the first input into a row (in column-major
          % order), and pushes a cell array of substrings that match the
          % pattern given by the second input
          % STACK: {'100000'; '10'; 110'; '100'}
ZB        % Convert each string into a decimal number. Gives numeric vector
          % STACK: [32; 2; 6; 4]
s         % Sum. Implicitly display
          % STACK: 44
Luis Mendo
fonte
5

05AB1E , 18 bytes

Código:

Çžy+b€¦JTR021:2¡CO

Explicação:

Ç                   # Take the ASCII value of each character
 žy+                # Add 128 to each value (to pad each with enough zeros)
    b               # Convert to binary
     €¦             # Remove the first character
       J            # Join the array
        TR021:      # Replace 01 by 021
              2¡    # Split on the number 2
                C   # Convert from binary to decimal
                 O  # Sum them all up

Usa a codificação 05AB1E . Experimente online!

Adnan
fonte
5

05AB1E , 14 bytes

Çžy+b€¦Jγ2ôJCO

Uma porta da minha resposta Jelly , usando o deslocamento 128 da resposta 05ab1e de Adnan (em vez dos 256 na resposta Jelly que escrevi).

Experimente online!

Quão?

Çžy+b€¦Jγ2ôJCO
Ç              - to ordinals
   +           - add
 žy            - literal 128
    b          - to binary
     €         - for each
      ¦        -   dequeue
       J       - join
        γ      - group into chunks of equal elements
          ô    - split into chunks of
         2     - literal 2
           J   - join
            C  - from binary
             O - sum
Jonathan Allan
fonte
3

JavaScript (ES6), 97 92 bytes

s=>eval(s.replace(/./g,c=>(128+c.charCodeAt()).toString(2).slice(1)).replace(/1+/g,'+0b$&'))

Editar: salvou 5 bytes com alguma ajuda do @ ConorO'Brien.

Neil
fonte
Minha própria solução foi de 97 bytes, também: s=>eval([...s].map(e=>(e.charCodeAt()+128).toString(2).slice(1)).join``.replace(/1+0*/g,'+0b$&'))Você pode usar o meu método replace para salvar um byte, eu acho
Conor O'Brien
1
@ ConorO'Brien Mais do que um byte, eu acho!
Neil
Oo, n i c e: D
Conor O'Brien
3

Japonês , 18 12 bytes

c_¤ùT7Ãò< xÍ
c_           // Firstly, take the input and map over it as charcodes.
  ¤          // Take the binary representation of each item
   ùT7       // and left-pad it with zeroes to standardize the items.
      Ã      // After all of the above,
       ò<    // partition the result where ever a 0 precedes a 1.
          xÍ // Then sum the numbers from base 2.

Recebe a entrada como uma única sequência.
Eu também experimentei a adição 128 ou 256 usada por outras respostas, mas o preenchimento de 0 foi mais curto de usar.

Raspou um total de 6 bytes, graças à ETHproductions e Oliver .

Experimente aqui.

Nit
fonte
Você pode usar mais funções automáticas aqui: òÈ<YÃpode ser ò<(com espaço à direita) e Ën2Ãxpode ser xn2. Você também pode usar Tno lugar de 0para economizar na vírgula. (Além disso, sinta-se livre para se juntar a nós na sala de chat Japt se você tiver dúvidas ou quiser ajuda com golfe :-))
ETHproductions
@ETHproductions Obrigado novamente, especialmente pelo Ttruque, não sabia que você poderia (ab) usar variáveis ​​para isso, isso é muito útil. A função automática xn2parece um pouco estranha quando compilada, x("n", 2)por isso acho que ainda vai demorar um pouco até eu entender completamente a lógica por trás delas. Com sua ajuda, a solução Japt agora está empatada em primeiro lugar com a resposta Jelly .
Nit
ETHproductions recentemente fez um atalho para n2: Í. Não atingiu TIO ainda, mas você pode usá-lo aqui: ethproductions.github.io/japt/?v=1.4.5&code=Y1+k+VQ3w/...
Oliver
@ Oliver Wow, essa é uma vantagem muito grande, que ainda nem é abordada na referência de atalhos do intérprete. Muito obrigado!
Nit
2

Geléia , 16 15 bytes

-1 byte graças a Dennis (não é necessário achatar por 1 quando um achatamento completo é bom - substitua ;/por F)

O+⁹Bṫ€3FŒg;2/ḄS

Experimente online!

Quão?

O+⁹Bṫ€3FŒg;2/ḄS - Main link: list of characters, s    e.g. "A4"
O               - cast to ordinal (vectorises)        [65,52]
  ⁹             - literal 256
 +              - add (vectorises)                    [321, 308]
   B            - convert to binary (vectorises)      [[1,0,1,0,0,0,0,0,1],[1,0,0,1,1,0,1,0,0]]
    ṫ€3         - tail €ach from index 3              [[1,0,0,0,0,0,1],[0,1,1,0,1,0,0]]
       F        - reduce with concatenation           [1,0,0,0,0,0,1,0,1,1,0,1,0,0]
        Œg      - group runs of equal elements        [[1],[0,0,0,0,0],[1],[0],[1,1],[0],[1],[0,0]]
          ;2/   - pairwise reduce with concatenation  [[1,0,0,0,0,0],[1,0],[1,1,0],[1,0,0]]
             Ḅ  - convert from binary (vectorises)    [32,2,6,4]
              S - sum                                 44
Jonathan Allan
fonte
1
;/pode ser substituído por F.
Dennis
2

PHP, 116 bytes

for(;$c=ord($argn[$i++]);)$r.=sprintf("%07b",$c);$t=mb_split("(?<=0)(?=1)",$r);echo array_sum(array_map(bindec,$t));

Versão Online

PHP, 117 bytes

for(;$c=ord($argn[$i++]);)$r.=sprintf("%07b",$c);$t=preg_split("#0\K(?=1)#",$r);echo array_sum(array_map(bindec,$t));

Experimente online!

PHP, 120 bytes

for(;$c=ord($argn[$i++]);)$r.=sprintf("%07b",$c);preg_match_all("#1+0+#",$r,$t);foreach($t[0]as$b)$s+=bindec($b);echo$s;

Experimente online!

ou

for(;$c=ord($argn[$i++]);)$r.=sprintf("%07b",$c);preg_match_all("#1+0+#",$r,$t);echo array_sum(array_map(bindec,$t[0]));
Jörg Hülsermann
fonte
1

Pitão , 21 bytes

Está muito comprido...

siR2:.BiCMQ128"1+0+"1

Suíte de teste.

Freira Furada
fonte
1

[F #], 249 245 bytes

open System
let rec c a=function|[]->[a]|'0'::'1'::y->(a+"0")::(c""('1'::y))|x::y->c(a+string x)y
let x i=c""(String.Join("",(Seq.map(fun c->Convert.ToString(int c,2).PadLeft(7,'0'))i))|>Seq.toList)|>Seq.map(fun c->Convert.ToInt32(c,2))|>Seq.sum

Experimente online!

Nota: a versão em tio.run tem "Sistema aberto" no cabeçalho, adicionei sua contagem ao código acima. Não sei ao certo quais são as regras nas importações.

Ungolfed

let rec convert acc = function
    | [] -> [acc]
    | '0'::'1'::xs -> (acc + "0") :: (convert "" ('1'::xs))
    | x::xs -> convert (acc + string x) xs

let calculateSum input =
    let binary = Seq.map (fun x -> Convert.ToString(int x, 2).PadLeft(7, '0')) input

    String.Join("", binary)
    |> Seq.toList
    |> convert ""
    |>Seq.map (fun x -> Convert.ToInt32(x, 2))
    |>Seq.sum
Brunner
fonte
se open Systemfor o mesmo que C # s using System;, sim, você precisará incluí-lo na contagem. Se você puder fazer isso em F #, poderá se qualificar totalmente para qualquer coisa System. Por exemplo, em C # em System.Console...vez deusing System;Console...
TheLethalCoder 15/17
@TheLethalCoder É o mesmo, sim. Além disso, obrigado por esclarecer isso :) Optei pela versão "open .." porque não é apenas a String, mas também a Convert que vive nesse espaço de nome.
Brunner
0

Perl 6 , 62 bytes

{sum map {:2(~$_)},.comb».ord».fmt('%07b').join~~m:g/11*0*/}
Sean
fonte
use em .ordsvez de .comb».ord. prefixo [~]geralmente pode ser usado em vez de .join. combexiste o que faz a m:g/…coisa. /11*0*/pode ser reduzido para /1+0*/. Eu vim com{sum map {:2($_)},comb /1+0*/,[~] .ords».fmt('%07b')}
Brad Gilbert b2gills
0

J , 34 bytes

[:+/@(,#.;.1~1,1=2#.\,)(7#2)#:3&u:

Experimente online!

Explicação

[:+/@(,#.;.1~1,1=2#.\,)(7#2)#:3&u:  Input: array of characters S
                              3&u:  Get ASCII values of each character
                       (7#2)        Array with 7 copies of the value 2
                            #:      Convert each value to a base 2 array with length 7
[:  (                 )             Operate on those binary values
                     ,                Flatten it
                 2  \                 For each infix of size 2
                  #.                    Convert it to decimal from binary
               1=                     Test each value for equality to 1
             1,                       Prepend a 1
      ,                               The flattened binary values
         ;.1~                         Chop that at each occurrence of a 1
       #.                               Convert each chop from binary to decimal
 +/@                                Reduce by addition
milhas
fonte
0

mathematica 193 bytes

f=FromDigits;l=Flatten;(S=Split@l@Table[PadLeft[IntegerDigits[ToCharacterCode@#,2][[k]],7],{k,StringLength@#}];Plus@@Table[f[RealDigits@f@Join[S[[i]],S[[i+1]]],2],{i,1,Length@S-1,2}]+Last@l@S)&
J42161217
fonte
Você pode salvar 7 bytes executando f=FromDigits;l=Flatten;no início e, em seguida, substituindo todas as instâncias dessas duas funções por fe l.
Numbermaniac #
0

J , 40 bytes

+/>#.&.>(1,}.|.1 0 E.|.b)<;.1 b=.,#:a.i.

uso:

+/>#.&.>(1,}.|.1 0 E.|.b)<;.1 b=.,#:a.i.'A4'

retorna 44

protista
fonte
0

Clojure, 150 bytes

#(loop[[c & C](for[i % j[64 32 16 8 4 2 1]](mod(quot(int i)j)2))p 0 r 0 R 0](if c(if(=(dec c)p 0)(recur C c 1(+ R r))(recur C c(+(* 2 r)c)R))(+ R r)))

Bem, eu esperava que a conversão de ASCII para bytes fosse mais curta que isso. O corpo do loop real é bastante curto, usando rpara acumular o resultado atual e Racumular o resultado total. Se o bit anterior pé 0e o bit atual cé 1, dividimos um novo pedaço e acumulamos para R, caso contrário, atualizamos o re mantemos Rcomo estava.

NikoNyrh
fonte
0

Python 123 bytes

lambda w:sum(map(lambda x:int(x,2),"".join(map(lambda x:bin(ord(x))[2:].zfill(7),list(w))).replace("01","0:1").split(":")))

Atualizado, graças a Martin Ender.

ShadowCat
fonte
1
Bem-vindo ao PPCG! Todas as respostas precisam ser programas completos ou funções que podem ser chamadas (ao contrário de trechos em que a entrada é armazenada em uma variável codificada). A função pode ser sem nome, no entanto, incluir um lambda w:seria suficiente para validar sua resposta.
Martin Ender
Desculpe, eu provavelmente não frase tão bem. Sua edição ainda é inválida porque a) a entrada é codificada, b) Se este é um programa completo, na verdade não imprime o resultado. Para um programa completo, você teria que ler a entrada da entrada padrão ou um argumento da linha de comando e imprimir o resultado na saída padrão. É por isso que eu disse que provavelmente seria mais fácil se você enviá-lo como uma função adicionando lambda w:.
Martin Ender
Ohhh, Ok, entendi, seria suficiente assim: f = lambda w: sum (mapa (lambda x: int (x, 2), "".) Join (map (lambda x: bin (ord (x)) ) [2:]. Zfill (7), list (w))). Replace ("01", "0: 1"). Split (":")))
ShadowCat
Sim, isso é válido. Você nem precisa do f=, porque permitimos funções sem nome (a menos que você faça referência ao nome da função para chamadas recursivas).
Martin Ender
0

K (oK) , 31 bytes

Solução:

+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$

Experimente online!

Exemplos:

+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$,"a"
49
+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$"A4"
44
+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$"codegolf"
570
+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$"Hello, World!"
795

Explicação:

Converta em valores ASCII, converte em binário de 7 bits, achatar, encontre onde difere e contra a lista original para descobrir onde 1s diferem. Corte nesses índices, converta de volta para decimal e resuma:

+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$ / the solution
                            `i$ / convert to integer
                     (7#2)      / draw from 2, 7 times => 2 2 2 2 2 2 2
                          \'    / decode each (convert to binary)
                   ,/           / flatten
                 x:             / save as x
             ~~':               / not-not-each previous (differ)
            &                   / and with
           x                    / x
          &                     / indices where true
     _[;x]                      / projection, cut x at ...
  2/'                           / encode each (convert from binary)
+/                              / sum up

Bônus

Também gerenciei uma versão de 31 bytes no K4 , mas como não há TIO, estou postando minha solução oK.

+/2/:'_[;x]@&x&~~':x:,/1_'0b\:'
rua
fonte
0

APL (Dyalog) , 30 bytes

{+/2⊥¨(1∘+⊆⊢)∊¯7↑¨2⊥⍣¯1¨⎕UCS⍵}

Experimente online!

Quão?

⎕UCS⍵ - Unicodify

2⊥⍣¯1¨ - codifique cada um em binário

¯7↑¨ - e almofada para a esquerda com zeros para 7 lugares

- achatar

1∘+⊆⊢ - partição auto aumentada em um

2⊥¨ - decodificar cada um dos binários

+/ - soma

Uriel
fonte