A expansão binária binária

9

Normalmente, decompomos um número em dígitos binários atribuindo-o com potências de 2, com um coeficiente de 0ou 1para cada termo:

25 = 1*16 + 1*8 + 0*4 + 0*2 + 1*1

A escolha de 0e 1é ... não muito binária. Realizaremos a verdadeira expansão binária expandindo com potências de 2, mas com um coeficiente de 1ou -1:

25 = 1*16 + 1*8 + 1*4 - 1*2 - 1*1

Agora isso parece binário.

Dado qualquer número positivo, deve ser trivial ver que:

  • Todo número ímpar tem infinitas expansões binárias verdadeiras
  • Todo número par não possui expansões binárias verdadeiras

Portanto, para que uma verdadeira expansão binária seja bem definida, exigimos que a expansão seja mínima , ou seja, com o menor comprimento.


Dado qualquer número inteiro positivo e ímpar n, retorne sua verdadeira expansão binária, do dígito mais significativo para o dígito menos significativo (ou em ordem inversa).

Regras:

  • Como esse é o , você deve fazer isso na menor contagem de bytes possível. Builtins são permitidos.
  • Qualquer saída que possa representar e listar os coeficientes é aceitável: uma matriz, uma sequência de coeficientes com separadores, etc ...
  • Aplicam-se lacunas de golfe padrão.
  • Seu programa deve funcionar para valores dentro do tamanho inteiro padrão do seu idioma.

Casos de teste

25 -> [1,1,1,-1,-1]
47 -> [1,1,-1,1,1,1]
1 -> [1]
3 -> [1,1]
1234567 -> [1,1,-1,-1,1,-1,1,1,-1,1,-1,1,1,-1,1,-1,-1,-1,-1,1,1]
Voile
fonte
Relacionado, mas bem diferente.
Giuseppe
4
Algoritmo simples: converta na base 2, substitua 0 por -1 e coloque o LSD na frente.
Josiah Winslow
Voile: Eu não estava explicando os votos negativos, estava apenas descrevendo um algoritmo para pessoas que possuem comandos de conversão de base em seu idioma.
Josiah Winslow
Como você está tão interessado em ser verdadeiramente binário, podemos retornar o valor em bits compactados com o valor de lugar usual, mas com a nova interpretação dos dois estados? eletricamente, é apenas alta ou baixa tensão (ou o que seja), e não é minha culpa se os depuradores padrão imprimem em 0vez do -1estado de baixa tensão. O chamador que recebe os bits sabe o que eles significam. (Ainda é um exercício de manipulação de bits não-trivial, uma vez que uma rotação direita só funciona se tiver 32 bits significativos por exemplo, um número 5 bits precisa de uma largura de rotação de 5..)
Peter Cordes
A saída precisa incluir separadores? É 111-1-1uma saída válida para 25?
Oliver

Respostas:

7

Japonês , 6 bytes

¤é r0J

Experimente online!

Explicação:

¤é r0J  // Test input:                  25
¤       // Binary the input:            11001
 é      // Rotate 1 chars to the right: 11100
   r0J  // Replace 0s with -1:          111-1-1
Oliver
fonte
11
Ah, a rotação; que é por isso que não estava funcionando para mim.
Shaggy
2
Rodar ??? dagnabbit.
Giuseppe
3

Pitão ,  12  11 bytes

|R_1.>jQ2 1

Experimente aqui!


Como?

| R_1.> JQ2 1 Programa completo.

      jQ2 Converte a entrada em uma lista binária.
     .> 1 Gire ciclicamente a lista acima em 1 lugar à direita.
| R_1 Substitua 0 por -1.
               Saída implícita.

Primeiro, notamos que a tarefa é apenas "substituir os 0s na escrita binária por -1s e deslocar para a direita por 1 lugar". - É exatamente o que devemos fazer! A conversão binária dá-nos uma lista de 0s e 1s. Tudo o que deve fazer aqui é encontrar uma maneira golfy para converter 0para -1. O operador bit a bit |(OR bit a bit) é nosso amigo. O mapa sobre a representação binária mudou com |e -1. Se o número atual for 0, ele será convertido em -1.

Mr. Xcoder
fonte
Eu não acho que há uma maneira melhor. ;)
Josiah Winslow
@JosiahWinslow eu faço ... tentando encontrá-lo
Mr. Xcoder
Hum? O algoritmo parece ótimo, talvez seja porque eu não conheça Pyth.
Josiah Winslow
@JosiahWinslow encontrou o melhor caminho. Melhor maneira sintática, melhor não algorítmica.
Mr. Xcoder
@ Mr.Xcoder E agora realmente não há pelo menos para mim.
Erik the Outgolfer
3

JavaScript (ES6), 35 34 bytes

f=n=>n?[...f(n>>=1),!n|n%2||-1]:[]

Snippet de teste

ETHproductions
fonte
2

Perl 6 , 72 bytes

Certamente há uma maneira melhor, mas é isso que eu tenho ...

->$a {grep {$a==[+] @^a.reverse Z+< ^∞},[X] (1,-1)xx $a.base(2).chars}

Experimente online!

Explicação : É uma função que recebe um argumento ( ->$a). Primeiro obtemos o número de coeficientes necessários ( $a.base(2).chars= número de caracteres na representação da base 2) e, em seguida, fazemos um produto cartesiano ( X) com muitos pares (1,-1). (O [X]meio: reduza a lista a seguir com X.) Portanto, obtemos uma lista de todas as combinações possíveis de 1s e -1s. Em seguida, filtramos ( grep) apenas as listas que codificam o número fornecido $a. Existe apenas um, então obtemos uma lista de uma lista com os coeficientes.

O bloco grep faz isso: pega seu argumento como uma lista ( @^a), o reverte e o fecha com uma lista infinita 0,1,2,...usando o operador "left bit shift" +<. O zíper pára assim que a lista mais curta se esgota (bom para nós!) Em seguida, somamos todos os resultados e comparamos com o número fornecido. Tivemos que usar .reverseporque o OP exige que os coeficientes estejam na ordem do mais significativo para o menos significativo.

Ramillies
fonte
1

05AB1E , 6 5 bytes

bÁ0®:

Experimente online!

Okx
fonte
D<pode ser ®( ®é o padrão -1).
Erik the Outgolfer
@EriktheOutgolfer Thanks! Não percebi isso.
Okx 31/08/19
1

J, 11 bytes

1-~2*_1|.#:

Experimente online!

Obrigado a @JosiahWinslow pelo algoritmo.

Alguma idéia de como reduzir a conversão? Meu pensamento é usar !.-fit (nvm, isso apenas altera a tolerância da conversão).

O uso de {-take é maior em 1 caractere.

_1 1{~_1|.#:
Cole
fonte
1

Java 8, 101 bytes

n->{String s=n.toString(n,2);return(s.charAt(s.length()-1)+s.replaceAll(".$","")).replace("0","-1");}

Porto de @Oliver resposta Japt 's , com um pouco mais bytes ..;)

Definitivamente, você pode jogar golfe usando uma abordagem matemática em vez dessa abordagem de String.

Explicação:

Experimente aqui.

n->{                             // Method with Integer parameter and String return-type
  String s=n.toString(n,2);      //  Convert the Integer to a binary String
  return(s.charAt(s.length()-1)  //  Get the last character of the binary String
    +s.replaceAll(".$","")       //   + everything except the last character
   ).replace("0","-1");          //  Then replace all zeroes with -1, and return the result
}                                // End of method
Kevin Cruijssen
fonte
1

R , 90 88 46 bytes

function(n)c((n%/%2^(0:log2(n))%%2)[-1],1)*2-1

Experimente online!

Implementa o algoritmo de Oliver , mas retorna os dígitos na ordem inversa. Como garantimos que isso nnunca é uniforme, o bit menos significativo (o primeiro) é sempre 1, por isso o removemos e anexamos um 1ao final para simular a rotação em R. Agradecemos a Shaggy por me ajudar a corrigir minha matemática .

Simplesmente colocar rev( )as chamadas de função no rodapé deve retornar os valores na mesma ordem.

resposta original, 88 bytes:

function(n,b=2^(0:log2(n)))(m=t(t(expand.grid(rep(list(c(-1,1)),sum(b|1))))))[m%*%b==n,]

Função anônima; retorna os valores na ordem inversa com os nomes das colunas anexados.

Experimente online!

Explicação:

function(n){
 b <- 2^(0:log2(n))         # powers of 2 less than n
 m <- expand.grid(rep(list(c(-1,1)),sum(b|1))) # all combinations of -1,1 at each position in b, as data frame
 m <- t(t(m))               # convert to matrix
 idx <- m%*%b==n            # rows where the matrix product is `n`
 m[idx,]                    # return those rows
}
Giuseppe
fonte
Eu não consideraria essa saída válida; sugira pedir confirmação ao autor do desafio.
34
A ordem inversa @Shaggy é explicitamente permitida: from the most significant digit to the least significant digit (or in reversed order).portanto, isso deve ser perfeitamente aceitável.
31717 Giuseppe
11
Ordem invertida , não sinais invertidos. Significando saída válida para 25, por exemplo, seria [1,1,1,-1,-1]ou [-1,-1,1,1,1].
Shaggy
11
@ Ah desagradável, você está certo, eu acabei de fazer a matemática errado! deve ser em 2*bits - 1vez de 1-2*bits. Obrigado.
Giuseppe
0

CJam, 12 bytes

Um porto da minha resposta Golfscript.

qi2b{_+(}%)\
Josiah Winslow
fonte
0

Golfscript, 14 13 14 bytes

-1 byte porque esqueci que %existia. 1 byte porque também esqueci que a entrada é uma string.

~2base{.+(}%)\
Josiah Winslow
fonte
11
Se você assumir que a entrada é um número inteiro, envolva o código {}para torná-lo um bloco. Programas completos podem receber apenas entradas como strings.
Peter Taylor
Hum ... o que? Eu quis dizer, o número está sendo enviado como um número inteiro, em vez de uma string contendo um número.
Josiah Winslow
Nesse caso, sua resposta não é um programa completo e, portanto, deve ser uma "função" ou, no caso do GolfScript, um bloco. Portanto, é {2base{.+(}%\}de 15 bytes. Da mesma forma, sua resposta CJam.
Peter Taylor
Este é um programa completo. A entrada no Golfscript é implicitamente enviada para a pilha no início do programa, e a entrada no CJam é especificada antes da execução e acessada com o comando q.
Josiah Winslow
Eu tenho alguma familiaridade com o GolfScript . ( E CJam ). Se você quiser afirmar que é um programa completo, precisará prefixá-lo ~.
Peter Taylor