Simplifique o binário

20

Desafio

Dado um número binário como entrada por qualquer meio, "simplifique" o número usando um programa ou uma função completa.

Entrada

[binary]
  • binary é um número no binário acima de 0.

Saída

Pegue a entrada, converta-a na base 10 sem usar um built-in; em seguida, se esse número contiver apenas 1s e 0s, converta-o em um número base 10 como se fosse outro número binário. Repita o processo até que o número não possa ser lido em binário e emita esse número.

Outra informação

  • Se a entrada for 1, basta emitir 1. Seu programa não deve continuar infinitamente simplificando 1.

  • Isso é código de golfe, então a resposta mais curta em bytes até terça-feira (17 de novembro) vence.

  • Se algo estiver confuso, deixe um comentário especificando o que eu preciso esclarecer e eu o editarei de acordo.

  • Builtins para conversão de base não são permitidos.

Exemplos

     Input | Output

         1 | 1
      1010 | 2
      1011 | 3
   1100100 | 4
   1100101 | 5
1111110011 | 3
The_Basset_Hound
fonte
4
Pode usar alguns casos de teste.
Isaacg
A entrada é uma sequência ASCII ou, na verdade, 1 e 0?
Tom Carpenter #
@TomCarpenter 1s e 0s.
The_Basset_Hound 11/11/2015
@isaacg Adicionadas maneiras de obter 1-5 como saída.
The_Basset_Hound 11/11
São permitidas funções que convertem uma string em uma determinada base?
Isaacg

Respostas:

14

Pitão, 20 16 bytes

u?-GTG`u+yNsTG0z

4 bytes graças a Jakube

Metade do código ( u+yNsTG0) é simplesmente o código de conversão base.

Suíte de teste

u?-GTG`u+yNsTG0z
                    z = input() (The string of 1s and 0s)
                    T = 10
u              z    Apply until the value stops changing, starting with z
                    G is the current value, a string of 0s and 1s.
 ?-GT               If G - T, e.g., G with the digits 1 and 0 removed is not empty,
     G              Return G, to end the iteration.
       u     G0     Else, reduce over G with initial value 0.
         yN         Double the running total
        +  sT       and add the next digit, cast to an int.
      `             Convert to string.

A entrada 1é manipulada pelo fato de unotar que o valor parou de mudar.

isaacg
fonte
4
Parabéns, você superou o Dennis! Por enquanto ...
Conor O'Brien
9
@ CᴏɴᴏʀO'Bʀɪᴇɴ O segredo é Pyth.
Isaacg
8

CJam, 24 23 bytes

q{:~{1$++}*s__,(As*-!}g

Experimente online no intérprete CJam .

Como funciona

q                        Read all input.
 {                   }g  Do:
  :~                       Evaluate each character. Maps '0' -> 0 and '1' -> 1.
    {    }*                Fold; for each integer but the first:
     1$                      Copy the second-topmost integer.
       ++                    Add all three integers on the stack.
           s__             Cast to string and push two copies.
              ,(           Calculate string length and subtract 1.
                As         Push the string "10".
                  *        Repeat the string length-1 times.
                   -       Remove its elements from the string representation
                           of the integer.
                    !      Apply logical NOT.
                         If `!' pushed 1, repeat the loop.
Dennis
fonte
Você precisa repetir os tempos das "10"cordas length-1ou pode pular o decremento?
DLosc
Subtrair 1 do comprimento se transforma "10"em ""se o número inteiro tiver um único dígito. Isso garante que o código não entre em um loop infinito.
Dennis
2
Fascinante, capitão. }: ^ |
DLosc
7

Pip, 28 27 bytes

Ta=1|aRMta:$+(^a)*2**RV,#aa

Recebe entrada como um argumento de linha de comando. Queremos fazer um loop até a=1ou aconter alguns caracteres além dos zeros e zeros. Essa última condição é testada RMinserindo todos os caracteres em t= 10from a. Se sobrar alguma coisa, a condição é verdadeira.

Dentro do loop, a conversão funciona da seguinte maneira:

a:$+(^a)*2**RV,#a

              ,#a  range(len(a))
            RV     reversed
         2**       2 to the power of each element
    (^a)*          multiplied item-wise with each digit in split(a)
  $+               Sum
a:                 and assign back to a

Colocar ano final imprime automaticamente.

Uma solução recursiva em 28 bytes:

a<2|aRMt?a(f$+(^a)*2**RV,#a)
DLosc
fonte
6

Python 2, 52

f=lambda n:n>1<'2'>max(`n`)and f(n%10+2*f(n/10))or n

É mais fácil pensar nisso como duas funções recursivas:

g=lambda n:n and n%10+2*g(n/10)
f=lambda n:n>1<'2'>max(`n`)and f(g(n))or n

A função gconverte um valor decimal em binário e a função fse aplica grepetidamente, desde que seu argumento seja composto pelos dígitos 0 e 1 ( '2'>max(`n`)) e não o seja 1. O código golfed os recolhe em uma única função, inserindo a definição de g(n)for f(n), substituindo a chamada recursiva por gwith f. O caso base n=0de gé tratado automaticamente pela verificação n>1.

xnor
fonte
Nice :) A única coisa é que o problema habitual aplica - o traquinas Lde repr...
SP3000
4

Prolog, 220 212 bytes

:-use_module(library(clpfd)).
x(B,N):-reverse(B,C),foldl(y,C,0-0,_-N).
y(B,J-M,I-N):-B in 0..1,N#=M+B*2^J,I#=J+1.
b(N,I):-N>47,N<50,I is(N-48).
p(N):-N>1,number_codes(N,L),maplist(b,L,Y),x(Y,B),p(B);write(N).

A explicação
p é a função principal e executa as seguintes etapas (com a ajuda de b, x, y):

  • verifica se o número atual é maior que 1
  • converte inteiro para lista de representações ascii de dígitos
  • verifica se todos os números são 0 ou 1
  • converte lista ascii em lista inteira binária
  • converte lista inteira binária em número decimal
  • recorrências
  • imprime quando um predicado falha.

Editar: salvou 8 bytes unificando as cláusulas p com OR.

Emigna
fonte
3

Mathematica 107 106

Com um byte salvo pelo DLosc.

j@d_:=(p=0;v=IntegerDigits@d;
Which[d<2,1,Complement[v,{0,1}]=={},j@Fold[#+#2 2^p++&,0,Reverse@v],1<2,d])

Divida a entrada em seus dígitos. Se a entrada for 1, a saída 1.

Se a entrada for um número composto por 0 e 1, converta-o em decimal e execute-o novamente.

Caso contrário, retorne a entrada.


j[1]

1


j[11010001]

209


j[1111110001]

1009


j[1111110011]

3

O primeiro passo produz 1011, que por sua vez produz 3.


Aqui testamos começando com 1011.

j[1011]

3

DavidC
fonte
3

Javascript, 132 , 123 bytes

Bem, não é a melhor resposta, mas ..

Para sua informação, se uma entrada inválida for fornecida, ela será exibida para o usuário.

function c(x){while(x!=0&&!/[2-9]/.test(x)){for(i=r=0;x;i++)r+=x%10*Math.pow(2,i),x=parseInt(x/10);x=r}alert(x)}c(prompt())

LearningDeveloper
fonte
1
Você pode salvar 19 bytes usando em forvez de whilee definindo valores diretamente na instrução (isso também reduz alguns {}), descartando alguns ;, usando a descrição da função ES6, incrementando em ilinha. Vai ficar assim: c=x=>{for(r=0;x&&!/[2-9]/.test(x);x=r)for(i=0;x>0;r+=x%10*Math.pow(2,i++),x=parseInt(x/10));alert(x)};c(prompt()).
insertusernamehere 11/11/15
1
114:function c(x){while(x^0&&!/[2-9]/.test(x)){for(i=r=0;x;i++)r+=x%10*Math.pow(2,i),x=0|x/10;x=r}alert(x)}c(prompt())
Mama Fun Roll
@insertusernamehere, obrigado pela sugestão, mas não entendi c=x=>no início, não funcionava no console do Chrome ou Firefox. :( @ ן nɟuɐɯɹɐ ן oɯ, não poderia envolver minha cabeça em torno da condição XOR ea x=0|x/10‌vez de parseInt, eu incorporei o resto das mudanças Thanks ...
LearningDeveloper
@ GauthamPJ Sinto muito, de alguma forma o código foi quebrado durante a cópia e continha caracteres não imprimíveis. Aqui está a versão correta: c=x=>{for(r=0;x!=0&&!/[2-9]/.test(x);x=r)for(i=r=0;x;)r+=x%10*Math.pow(2,i++),x=parseInt(x/10);alert(x)};c(prompt()). Ele definitivamente roda no Firefox 42, tente este violino . Observe que esta versão mais elaborada e também o seu código original não funcionam 1e serão executados em um loop infinito. c=x=>é como function c(x){}ver " Funções das setas ".
insertusernamehere
2

JavaScript ES6, 52

Como uma função. O argumento da função deve ser uma sequência de dígitos binários ou um número cuja representação decimal contenha apenas 1 e 0.

Teste a execução do snippet abaixo em um navegador compatível com EcmaScript 6 - implementando funções de seta, seqüências de caracteres de modelo e operador de propagação (eu uso o Firefox)

f=s=>s<2|[...s+''].some(c=>(n+=+c+n,c>1),n=0)?s:f(n)

// To test
console.log=(...x)=>O.innerHTML+=x+'\n';

// Basic test cases
;[[1,1],[1010,2],[1011,3],[1100100,4],[1100101,5],[1111110011,3]]
.forEach(t=>console.log(t[0]+' -> '+f(t[0])+' expected '+t[1]))

function longtest() {
  var o=[],i;
  for (i=1;i<1e6;i++)
    b=i.toString(2),v=f(b),v!=i?o.push(b+' '+v):0;
  O.innerHTML=o.join`\n`
}
Click to run the long test <button onclick="longtest()">go</button>
<pre id=O></pre>

edc65
fonte
1
Gosto muito n+=+c+nda conversão binária. Tão elegante ...
nderscore 11/11
2

Mathematica, 62 59 55 48 bytes

Economizou 7 bytes graças a Martin Büttner.

#//.a_/;Max[b=IntegerDigits@a]<2:>Fold[#+##&,b]&
alefalpha
fonte
1

Javascript (ES7) 87 80 78 77 74 bytes

Demonstração de trechos para oferecer suporte a navegadores (atualmente apenas o Firefox noturno suporta o operador exponencial)

f=x=>[...x].reverse(i=y=j=0).map(z=>(j|=z,y+=z*2**i++))&&j<2&y>1?f(y+[]):x
<input type="text" id="x" value="1111110011"><button onclick="o.innerHTML=f(x.value)">Run</button><div id="o"></div>

f=x=>
[...x].reverse(i=y=j=0) // reverse string as array, initialize vars
.map(z=>( // iterate over the all chatacters
    j|=z, // keep track of whether a digit higher than 1 is encountered
    y+=z*2**i++ // build decimal result from binary
))&&
j<2&y>1? // if we encountered only 1's and 0's and result > 1
    f(y+[]) // then call recursively and cast to a string
    :x // else return x

Javascript (ES6) 81 bytes

Demonstração de trechos para suportar navegadores

f=x=>[...x].reverse(i=y=j=0).map(z=>y+=z*Math.pow(2,i++,j|=z))&&j<2&y>1?f(y+[]):x
<input type="text" id="x" value="1111110011"><button onclick="o.innerHTML=f(x.value)">Run</button><div id="o"></div>

nderscore
fonte
1

, 37 caracteres / 54 bytes

↺;ï>1⅋(⬯+ï)ĉ/^[01]+$⌿);)ï=+('ᶀ'+ï);ôï

Try it here (Firefox only).

Não tenho certeza se o +operador conta como um built-in para conversão binária ...

Mama Fun Roll
fonte
1

Perl 6 , 67 bytes

get,{$_=0;for $^a.comb {$_+<=1;$_+=$^b};$_}...1|/<-[01]>/;say $_//1
Brad Gilbert b2gills
fonte
1

PHP, 210 204 bytes

É a minha primeira vez postando aqui, então espero que vocês gostem! Mesmo que obviamente não seja a melhor maneira de escrevê-lo, ainda fico feliz em mostrá-lo aqui!

O código

<?function j($a){$c=0;if($a==1){return 1;}else{if(preg_match("#^[01]+$#",$a)){$b=strlen($a);$a=str_split($a);foreach($a as$d){$c+=($d==0?0:2**($b-1));$b--;}return j($c);}else{return$a;}}}echo j($_GET[0]);

Eu criei uma função recursiva "j" que primeiro verifica se a entrada é igual a 1. Nesse caso, a função retorna 1 conforme o esperado, caso contrário, dividirá o número em uma matriz para calcular o valor decimal, mas apenas se o número for binário. Caso contrário, retornará o número como está.

Código ungolfed

<?
function j($a) {
  $c = 0;
  if ($a == 1) {
    return 1;
  }
  else {
    if (preg_match("#^[01]+$#", $a) {
      $b = strlen($a);
      $a = str_split($a);
      foreach ($a as $d) {
        $c += ($d == 0 ? 0 : 2 ** ($b - 1));
        $b--;
      }
      return j($c);
    }
    else {
      return $a;
    }
  }
}
echo j($_GET[0]);

Eu usei uma instrução "foreach" em vez da minha inicial "for", permitindo um ganho de 6 bytes, mas tenho certeza de que há muito mais a fazer.

Vincent Douay
fonte
1

PHP, 114 112 bytes

também trabalha para 0. Corra com -r.

for($n=$argv[1];count_chars($s="$n",3)<2&$s>1;)for($i=$n=0;""<$c=$s[$i++];)$n+=$n+$c;echo$s;

count_chars($s,3)retorna uma string contendo todos os caracteres da string (como array_uniquefaz para matrizes). Para números binários, este será 0, 1ou 01. Para outros números, ele conterá um dígito maior que 1, portanto <2, retornará verdadeiro apenas para números binários.

&$s>1é necessário para o caso especial 1.

O resto é direto: faça um loop pelos bits alterando o valor e adicionando o bit atual e, finalmente, copie o número (convertido em string) para $ s para o teste de loop externo.

Titus
fonte
0

CoffeeScript, 92 89 bytes

f=(x)->x>1&/^[01]+$/.test(x)&&f(''+x.split('').reverse().reduce ((p,v,i)->p+v*2**i),0)||x

JavaScript (ES6), 105 101 90 bytes

f=y=>y>1&/^[01]+$/.test(y)?f(''+[...y].reverse().reduce(((p,v,i)=>p+v*Math.pow(2,i)),0)):y

Demo

Funciona apenas em navegadores compatíveis com ES6, como Firefox e Microsoft Edge

f=y=>y>1&/^[01]+$/.test(y)?f(''+[...y].reverse().reduce(((p,v,i)=>p+v*Math.pow(2,i)),0)):y

// Snippet stuff
$(`form`).submit((e) => {
  document.getElementById(`y`).textContent = f(document.getElementById(`x`).value);
  e.preventDefault()
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
  <label>Input:
    <input pattern=^[01]+$ required id=x>
  </label>
  <button type=submit>Go</button>
  <p>Output:
    <output id=y></output>
  </p>
</form>

rink.attendant.6
fonte
Se você usar eval, poderá conseguir um retorno implícito.
Mama Fun Roll
5 bytes mais curto com funções eval e anônimos
Downgoat
Por algum motivo, a função avaliada não funciona 1. porque ele não entra no loop, eu assumo
rink.attendant
1
@nderscore Obrigado, mas a recursão foi 4 bytes mais curta :-)
rink.attendant.6
0

Scala, 128 bytes

def b(s:String):String=if(s.matches("[10]{2,}"))b(""+s.reverse.zipWithIndex.collect{case('1',i)=>Math.pow(2,i)}.sum.toInt)else s
Jacob
fonte
0

Matlab (115)

@(a)num2str(sum((fliplr(a)-48).*arrayfun(@(x)2^x,0:nnz(a)-1)));a=ans(input('','s'));while(find(a<50))a=ans(a);end,a

  • A função anônima é a conversão de tipo de número ( bin2dec)
Abr001am
fonte