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]

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

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.


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


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.




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|.#:

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

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
}

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

Golfscript, 14 13 14 bytes

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

~2base{.+(}%)\

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.