Para encontrar a dureza digital de um número inteiro, obtenha sua representação binária e conte o número de vezes que uma guia inicial e uma final
1
podem ser removidas até que iniciem ou terminem com a0
. O número total de bits removidos é a sua dureza digital.
Essa é uma explicação bastante prolixo - então vamos detalhar com um exemplo bem trabalhado.
Neste exemplo, usaremos o número 3167. Em binário, é o seguinte:
110001011111
(Observe que, durante a conversão para binário, retire os zeros iniciais)
Como não começa nem termina 0
, removemos 1 par de bits:
1 1000101111 1
E outro:
11 00010111 11
Mas agora há um 0 no começo, então não podemos remover mais 1
pares. No total, removemos 4 bits e, portanto, 4 é a dureza digital de 3167.
No entanto, para números que podem ser escritos como 2 n -1 para n positivo (ou seja, contêm apenas 1
na representação binária), 0 nunca será alcançado e, portanto, todos os bits poderão ser removidos. Isso significa que a dureza é simplesmente o tamanho do bit do número inteiro.
O desafio
n >= 0
Sua tarefa é escrever um programa ou função que, dado um número inteiro não negativo , determine sua dureza digital.
Você pode enviar um programa completo que execute E / S ou uma função que retorne o resultado. Seu envio deve funcionar com valores n
dentro do intervalo inteiro padrão do seu idioma.
Casos de teste
Notifique-me se algum deles estiver incorreto ou se você gostaria de sugerir algum caso extremo a ser adicionado.
0 -> 0
1 -> 1
8 -> 0
23 -> 2
31 -> 5
103 -> 4
127 -> 7
1877 -> 2
2015 -> 10
Aqui está a solução Python não utilizada que eu usei para gerar esses casos de teste (não é garantido que não haja erros):
def hardness(num) -> int:
binary = bin(num)[2:]
if binary.count('0') == 0:
return num.bit_length()
revbin = binary[::-1]
return min(revbin.find('0'), binary.find('0')) * 2
1
retorna 1 quando não há nenhum0
? Quero dizer, você não pode remover 1s suficientes da string para que ela comece ou termine0
.Respostas:
Geléia ,
1110 bytesExperimente online!
Como funciona
fonte
Python ,
76696863626057 bytesExperimente online!
Como funciona
Esta é uma solução recursiva que recebe uma entrada n e continua aumentando k - começando em 0 - enquanto LSB k (n) (bit no índice k da direita) e MSB k (n) (bit no índice k da esquerda) estão prontos. Uma vez finalizado, ele retorna k se todos os bits de n estiverem definidos e 2k, se não.
Vamos começar reescrevendo o lambda f como uma função nomeada F , com uma variável auxiliar t .
Em cada chamada de F , que primeiro bit de deslocamento n um total de K unidades para a direita e armazenar o resultado em t . Dessa forma, LSB 0 (t) = LSB k (n) , então t é ímpar se e somente se LSB k (n) estiver definido.
Determinar se MSB k (n) está definido é um pouco mais complicado; é isso que
n & t > t >> 1
alcança. Para ilustrar como funciona, vamos considerar um número inteiro n = 1αβγδεζη 2 de comprimento 8 e analisar a chamada de função F (n, 3) , ou seja, k = 3 .Estamos tentando determinar se o MSB 3 (n) = γ é definido examinando o valor de verdade da comparação (n & t> t >> 1) = (1αβγδεζη 2 & 1αβγδ 2 > 1αβγ 2 ) . Vamos examinar os números inteiros envolvidos.
Afirmamos que γ = 1 se e somente se n & t> t >> 1 .
Se γ = 1 , então n & t possui bit 5, enquanto t >> 1 possui bit 4 , então n & t> t >> 1 .
Isso prova que γ = 1 implica n & t> t >> 1 .
Se n & t> t >> 1 , há duas opções: γ = 1 ou γ = 0 . No primeiro caso, não há mais nada a provar.
No segundo caso, temos que αβγδ 2 ≥ n & t> t >> 1 = 1αβγ 2 .
Como αβγδ 2 > 1αβγ 2 , devemos ter MSB 0 (αβγδ 2 ) ≥ MSB 0 (1αβγ 2 ) , significando que α = 1 .
Dessa forma, 1βγδ 2 > 11βγ 2 , portanto, devemos ter o MSB 1 (1βγδ 2 ) ≥ MSB 1 (11βγ 2 ) , o que significa que β = 1 .
Por sua vez, isso implica que 11γδ 2 > 111γ 2 . Lembrando que γ = 0 no segundo caso, obtemos a desigualdade 110δ 2 > 1110 2 , o que é falso desde MSB 2 (110δ 2 ) = 0 <1 = MSB 2 (1110 2 ) .
Assim, apenas o primeiro caso é possível e n & t> t >> 1 implica γ = 1 .
Resumindo, se LSB k (n) e MSB k (n) estiverem definidos, t será ímpar e n & t> t >> 1 será True , portanto t & (n & t> t >> 1) será rendimento 1 . No entanto, se LSB k (n) ou MSB k (n) estiver desativado (ou se ambos estiverem), t será par ou n & t> t >> 1 será False , então t & (n & t> t> > 1) produzirá 0 .
Chamar F com um único argumento inicializa k = 0 . Embora a condição que discutimos anteriormente seja válida, o código após
and
é executado, que (entre outras coisas) chama recursivamente F com k incrementado .Uma vez que LSB k (n) ou MSB k (n) não está definido, a condição falha e F (n, k) retorna 0 . Cada uma das chamadas de função k anteriores adiciona (n & (n + 1)> 0) + 1 a F (n, k) = 0 , portanto F (n) retorna ((n & (n + 1)> 0) + 1) k .
Agora, se todos os bits de n forem iguais (ou seja, se n for 0 ou se todos os seus bits estiverem configurados), n + 1 não terá nenhum bit em comum com n , então n & (n + 1) = 0 e F (n) retorna k . No entanto, se n tiver bits definidos e não definidos, n & (n + 1)> 0 e F (n) retornarão 2k .
fonte
input()
,while
Eprint
já são 17 bytes ...MATL ,
1312 bytesExperimente online! Ou verifique todos os casos de teste .
Explicação
O código repete cada dígito binário e conta quantas vezes é possível remover dois dígitos externos.
fonte
Python, 82 bytes
Sinto que ainda pode jogar golfe, mas passei um tempo tentando métodos diferentes e esse foi o mais curto.
Experimente online
Embora isso funcione de maneira semelhante ao programa Python do OP, eu o criei antes que a pergunta fosse publicada, depois de visualizá-la na Sandbox, que não continha esse programa.
fonte
Python 2, 66 bytes
Divide a representação binária da entrada em partes de 1. Conta o número de 1's no menor e no primeiro e último pedaço e depois dobra-o, a menos que haja um único pedaço que isso contaria duas vezes.
fonte
PowerShell ,
109106 bytesExperimente online!
Recebe entrada
$args[0]
, usa a chamada .NET paraconvert
elatoString
com base2
(ou seja, torna-a binária), depois-split
s que string em0
s, armazena-o em$a
. Importante observar: a chamada do .NET não retorna zeros à esquerda, portanto, o primeiro dígito é sempre um1
.Existem, portanto, duas possibilidades - a string binária é todas, ou havia pelo menos um zero. Diferenciamos aqueles com pseudo-ternário indexado por
$a.count-eq1
. Se o binário tiver pelo menos um zero, o caso esquerdo, usaremos o mínimo do comprimento da primeira[0]
string de se1
da última[-1]
string (encontrada por|sort
e então[0]
). O menor desses é o maior número de pares que podemos remover, portanto multiplicamos por2
. Observe que, se a string binária original terminar em a0
, como na entrada8
,[-1].length
também será0
(já que é uma string vazia), que quando multiplicada por2
ainda é0
.Caso contrário, com todas as cadeias binárias, consideraremos justamente
$b
(que anteriormente era definido como o comprimento da primeira[0]
cadeia, nesse caso, a totalidade da cadeia binária).Em qualquer das situações, esse resultado é deixado no pipeline e a saída é implícita.
fonte
JavaScript (ES6), 57 bytes
Pega o binário e tenta corresponder a todos
1s
ou com falha nesse número igual de inicial e final1s
.fonte
Retina , 48 bytes
Experimente online
Explicação:
fonte
C #, 133 bytes
Função que retorna dureza. Pega inteiro do argumento.
Bem, hoje eu descobri
'1' + '1' = 98
em C #.fonte
'1'
é o caractere ASCII 49, e 49 + 49 = 98.1 + 1 = 2
não funcionou. @FlipTackC,
898885 bytesDois bytes salvos devido a @FlipTack apontar uma declaração inútil.
Ligue
f()
com o número para testar, a saída é retornada da função.Experimente em ideone .
fonte
JavaScript (ES6),
5958 bytesCasos de teste
Mostrar snippet de código
fonte
Gelatina , 14 bytes
Experimente online!
fonte
C,
1371321221191171149894928785 BytesHora de começar a jogar golfe B-)
Aqui está a prova
e a saída;
fonte
Java (OpenJDK) ,
181156150 bytesExperimente online!
fonte
Mathematica,
6356 bytesExplicação
Gere a representação base-2 da entrada, envolvida por um
List
. Armazene isso eml
Se o elemento min de
l
for 1, saída 1. Caso contrário, saída 2. Multiplique isso por ...Dividido
l
em execuções.Pegue o primeiro e o último elemento.
Pegue o total de ambos.
Encontre o menor entre os dois.
(Multiplique o primeiro resultado (1 ou 2) com este resultado).
fonte
Oitava,
5654 bytesExperimente Online!
Explicação:
representação binária de
n
Tome min acumulado de
d
e min acumulado de viradod
faça multiplicação de matrizes
multiplique por 2 se todos os dígitos forem 1;
fonte
Pitão, 18 bytes
Um programa que recebe a entrada de um número inteiro e imprime o resultado.
Suíte de teste (primeira linha para formatação)
Como funciona
fonte
APL, 26 bytes
Casos de teste:
Explicação:
fonte
J, 22 bytes
Isso se baseia no puro truque aprendido com esse desafio .
Experimente online!
Explicação
fonte
PHP,
8374 bytes3 + 6 bytes salvos por Jörg
recebe entrada do STDIN; corra com
-nR
.demolir
fonte
<?=~($s=decbin($argn))[$a=strspn($s,1)]?2*min($a,strspn(strrev($s),1)):$a;
JavaScript (ES6), 83 bytes
Ungolfed:
fonte
Mathematica, 62 bytes
Função pura onde
#
representa o primeiro argumento.(h=0;...;h)&
defineh=0
, faz um monte de coisas...
, depois retornah
(a dureza). Vejamos o monte de coisas:Agradeço a Greg Martin por me apresentar esse truque .
fonte
Haskell ,
9492 bytesExperimente online! Uso:
Explicação:
b
converte um número em binário e retorna uma lista de zero e aqueles com o bit menos significativo primeiro. Emh
, essa lista é revertida e multiplicada por elementos com a lista original, depois éspan(>0)
dividida após os1
s iniciais :A tupla resultante é correspondida com o padrão
(c,_:_)
onde_:_
corresponde a qualquer lista não vazia, portantoc = [1,1]
. Como os bytes são removidos na frente e atrás,c++c = [1,1,1,1]
são retornados e finalmente somados para produzir a dureza digital .Se a segunda lista da tupla estiver vazia, a representação binária conterá apenas uma, e o número de unidades é a dureza digital. Com a correspondência de padrões, o
h
retorno falha apenasn
, que é novamente resumido.fonte
Perl, 61 bytes
O coração disso é a expressão regular,
/^(1+).*\1$/
onde 2 vezes o comprimento de$1
é a resposta. O restante do código está sobrecarregado e trata do caso especial de todos os 1.fonte
sprintf
argumentos. Além disso, o uso do-p
sinalizador permitirá que você escreva um programa completo que seja mais curto do que sua função, como você poderá omitirsub f{...}
(em vez disso, você terá que terminar,$_=...
mas isso ainda é uma melhoria de 4 bytes). Finalmente, em vez delength(...)
você, você pode fazer/0/&&s/^(1+).*\1$/$1$1/;$_=y///c
. Isso deve levar a 51 bytes.PHP, 65 bytes
Versão Online
fonte
CJam, 14 bytes
Explicação:
fonte