Super Folding Numbers

10

Já definimos um número dobrável aqui .

Mas agora vamos definir um número super dobrável. Um número Super Folding é um número que, se dobrado o suficiente, chegará a um a menos que a potência de dois. O método de dobrar é um pouco diferente do que na questão do número de dobras.

O algoritmo de dobragem é o seguinte:

  • Pegue a representação binária

    por exemplo, 5882

    1011011111010
    
  • Derramado em três partições. Primeira metade, última metade e dígito do meio (se tiver um número ímpar de dígitos)

    101101 1 111010
    
  • Se o dígito do meio for zero, esse número não poderá ser dobrado

  • Inverta a segunda metade e sobreponha na primeira metade

    010111
    101101
    
  • Adicione os dígitos no lugar

    111212
    
  • Se houver 2s no resultado, o número não pode ser dobrado, caso contrário, o novo número é o resultado do algoritmo de dobragem.

Um número é um número super dobrável, se puder ser dobrado em uma sequência contínua de unidades. (Todos os números dobráveis ​​também são números super dobráveis)

Sua tarefa é escrever o código que recebe um número e gera um valor verdadeiro se o número for um número Super Folding e, caso contrário, falsificará. Você será pontuado no tamanho do seu programa.

Exemplos

5200

Converter em binário:

1010001010000

Dividido ao meio:

101000 1 010000

O meio é um, então continuamos Sobreponha as metades:

000010
101000

Adicionados:

101010

Não há dois, então continuamos Divididos ao meio:

101 010

Dobra:

010
101

111

O resultado é 111(7 em decimal), portanto, este é um número super dobrável.

Casos de teste

Os primeiros 100 números super dobráveis ​​são:

[1, 2, 3, 6, 7, 8, 10, 12, 15, 20, 22, 28, 31, 34, 38, 42, 48, 52, 56, 63, 74, 78, 90, 104, 108, 120, 127, 128, 130, 132, 142, 150, 160, 170, 178, 192, 204, 212, 232, 240, 255, 272, 274, 276, 286, 310, 336, 346, 370, 400, 412, 436, 472, 496, 511, 516, 518, 524, 542, 558, 580, 598, 614, 640, 642, 648, 666, 682, 704, 722, 738, 772, 796, 812, 852, 868, 896, 920, 936, 976, 992, 1023, 1060, 1062, 1068, 1086, 1134, 1188, 1206, 1254, 1312, 1314, 1320, 1338, 1386, 1440, 1458, 1506, 1572, 1596]
Caçador Ad Hoc Garf
fonte
2
A menos que eu esteja enganado, como se 3infiltrou nos casos de teste novamente? Não consigo ver como ela pode ser dobrada, pois se divide em 1 1, dando imediatamente um 2. Ou você está dizendo que dobrá-lo zero vezes também conta?
Geobits
O @geobits 3 deveria estar lá. Eu verifiquei desta vez;). Três é 11 assim que começa a únicos em arquivos de zero
Ad Hoc Garf Hunter
Acho que vale a pena colocar uma anotação bem no topo, logo após o link para a outra questão de número dobrável que aponta que as dobras individuais nessa pergunta usarão um método diferente.
Jonathan Allan

Respostas:

9

Aqui está minha primeira tentativa no código de golfe:

Python 3, 167 bytes

167 bytes se tabulações ou espaços únicos forem usados ​​para indentação

def f(n):
 B=bin(n)[2:];L=len(B);M=L//2
 if'1'*L==B:return 1
 S=str(int(B[:M])+int(B[:-M-1:-1]))
 return 0if(~L%2==0and'0'==B[M])or'2'in S else{S}=={'1'}or f(int(S,2))

Edit: Graças à ajuda de todos abaixo, o código acima foi reduzido de um tamanho original de 232 bytes!

Kapocsi
fonte
11
Bem-vindo ao PPCG! Você pode salvar um monte de bytes removendo os espaços após os :, retornando 0e em 1vez de Truee False.
Steven H.
Obrigado Steven. Além disso, não tenho 100% de certeza de ter contado o comprimento de bytes corretamente.
Kapocsi
11
Estou vendo 232 bytes. Dê-me um segundo e eu posso tentar jogar um pouco mais.
Steven H.
Eu usei isso para medir: bytesizematters.com
Kapocsi 7/10
11
@ Kapocsi, bytesizematters.com conta as novas linhas incorretas. Compare com mothereff.in , 5 dígitos e 5 novas linhas deve ser de 10 bytes, e não a 14 que eu tenho em bytesize ... a 232.
Linus
5

Java 7, 202 bytes

boolean g(Integer a){byte[]b=a.toString(a,2).getBytes();int i=0,l=b.length,o=0,c,z=(a+1&a)==0?-1:1;for(;i<l/2&z>0;o+=o+c*2,z*=c>1|(l%2>0&b[l/2]<49)?0:1)c=b[i]+b[l-++i]-96;return z<0?1>0:z<1?0>1:g(o/2);}

Foi preciso um pouco de esforço para tornar a função de dobrar antiga recursável, mas aqui está. É feio como o pecado, para ser honesto. Vou ter que dar uma olhada de manhã para ver se posso jogar mais, já que mal posso suportar olhar agora.

Com quebras de linha:

boolean g(Integer a){
    byte[]b=a.toString(a,2).getBytes();
    int i=0,l=b.length,o=0,c,z=(a+1&a)==0?-1:1;
    for(;i<l/2&z>0;o+=o+c*2,z*=c>1|(l%2>0&b[l/2]<49)?0:1)
        c=b[i]+b[l-++i]-96;
    return z<0?1>0:z<1?0>1:g(o/2);
}
Geobits
fonte
3

CJam , 47 44 bytes

ri2b{_W%.+__0e=)\_,1>\0-X+:*3<*&}{_,2/<}w2-!

Experimente online! ou gere uma lista de números super dobráveis ​​até um determinado número.
Tentativas de golfe podem ser vistas aqui .


O código divide-se nas seguintes fases:

ri2b                e# get input in binary
{                   e# While fold is legal
 _W%.+_             e#   "fold" the whole number onto itself
 _0e=)\             e#   count zeros and add 1 (I)
 _,1>\              e#   size check, leave 0 if singleton (II)*
 0-X+:*3<           e#   product of 2s, leave 0 if too many (III)
 *&                 e#   (II AND III) AND parity of I
}{                  e# Do
 _,2/<              e#   slice opposite to the actual fold**
}w                  e# End while
2-!                 e# return 1 if "fold" ended in all 2s

EDIT: Esta versão tem mais ou menos uma abordagem da Lei de De Morgan para a versão anterior.

* O problema com a execução de singletons é que ficamos presos com uma string vazia após a fatia.

** Se um número binário é super dobrável, sua imagem no espelho (com 0s à esquerda, se necessário) é. Isso economiza um byte ao pegar a metade direita.

Linus
fonte
2

JavaScript, 149 bytes

f=(i,n=i.toString(2),l=n.length,m=l/2|0)=>/^1*$/.test(n)?1:/[^01]/.test(n)|!+n[m]&l?0:f(0,+n.slice(0,m)+ +n.slice(m+l%2).split``.reverse().join``+"")

Define uma função recursiva.

Explicação:

f=(i                       //Defines the function: i is input
,n=i.toString(2)           //n is the current number
,l=n.length                //l is the length of the number,
,m=l/2|0)=>                //m is the index of the center character
/^1*$/.test(n)?1:          //returns 1 if the number is all ones
/[^01]/.test(n)            //returns 0 if the number has any chars other than 0 or 1
|!+n[m]&l?0:               //or if the middle char is 0
f(0,+n.slice(0,m)+ +n.slice(m+l%2).split``.reverse().join``+"")
                           //otherwise recurses using the first half of the number plus the second half
DanTheMan
fonte
m=l>>1, /2/.test(n), n.slice(l-m)(Ou cortar a corda invertida). Eu acho que se você alternar os casos de falha e sucesso, poderá usar /0/.test(n)?f(...):1.
Neil
2

JavaScript (ES6), 113 109 108 bytes

f=(n,[h,...r]=n.toString(2),b='')=>++n&-n-n?h?f(2,r,r[0]?b+(h- -r.pop()):+h?b:2):!isNaN(n=+('0b'+b))&&f(n):1

Formatado e comentado

f = (                               // given:
  n,                                // - n = integer to process
  [h, ...r] = n.toString(2),        // - h = highest bit, r = remaining low bits
  b = ''                            // - b = folded binary string
) =>                                //
  ++n & -n - n ?                    // if n is not of the form 2^N - 1:
    h ?                             //   if there's still at least one bit to process:
      f(                            //     do a recursive call with:
        2,                          //     - n = 2 to make the 2^N - 1 test fail
        r,                          //     - r = remaining bits
        r[0] ?                      //     - if there's at least one remaining low bit:
          b + (h - -r.pop())        //       append sum of highest bit + lowest bit to b
        : +h ? b : 2                //       else, h is the middle bit: let b unchanged
      )                             //       if it is set or force error if it's not
    : !isNaN(n = +('0b' + b)) &&    //   else, if b is a valid binary string:
      f(n)                          //     relaunch the entire process on it
  : 1                               // else: n is a super folding number -> success

Demo

f=(n,[h,...r]=n.toString(2),b='')=>++n&-n-n?h?f(2,r,r[0]?b+(h- -r.pop()):+h?b:2):!isNaN(n=+('0b'+b))&&f(n):1

// testing integers in [1 .. 99]
for(var i = 1; i < 100; i++) {
  f(i) && console.log(i);
}

// testing integers in [1500 .. 1599]
for(var i = 1500; i < 1600; i++) {
  f(i) && console.log(i);
}

Arnauld
fonte
2

Perl, 71 70 bytes

Inclui +1 para -p

Dê o número em STDIN

superfolding.pl:

#!/usr/bin/perl -p
$_=sprintf"%b",$_;s%.%/\G0$/?2:/.\B/g&&$&+chop%eg while/0/>/2/;$_=!$&
Ton Hospel
fonte
1

Python 2, 151 bytes

f=lambda n,r=0:f(bin(n)[2:],'')if r<''else(r==''and{'1'}==set(n)or(n in'1'and f(r,'')+2)or n!='0'and'11'!=n[0]+n[-1]and f(n[1:-1],r+max(n[0],n[-1])))%2

ideona

Uma função duplamente recursiva que pega um número inteiro,, ne retorna 0ou 1.

Uma variável ré mantida para permitir o resultado da dobra e para saber se atualmente: temos um número inteiro (apenas o primeiro); tenha uma nova string binária para tentar dobrar (externa); ou estão dobráveis ​​(interno).

Na primeira passagem, né um número inteiro, que está <''no Python 2, portanto a recursão começa convertendo para uma sequência binária.

A próxima execução tem r=''e, portanto, o teste {'1'}==set(n)é executado para verificar se há uma sequência contínua de 1s (o RHS não pode ser {n}o que talvez seja necessário para passar esse ponto posteriormente com r=''e vazio nquando isso seria um dicionário que não seja igual a {'1'}um conjunto).

Se isso não for atendido, o critério da cauda interna será testado (mesmo que desnecessário): if n in'1'será avaliado como True quando nfor uma string vazia ou uma única 1, após o que uma nova recursão externa é iniciada, colocando r, pela string binária então dobrada, em ne ''para dentro r. O literal 2é adicionado ao resultado dessa chamada de função para permitir que não ocorra a próxima parte (à direita de uma lógica or) que é corrigida posteriormente.

Se esse não for um valor verdadeiro (todos os números inteiros diferentes de zero são verdadeiros em Python), o critério de recursão da cauda externa é testado para: n!=0exclui o caso com um meio 0e os dois caracteres externos são testados aos quais não são somados 2pela concatenação da string '11'!=n[0]+n[-1]; se ambos são verdadeiros, os bits externos são descartados de ncom n[1:-1]e, em seguida, a 1é anexado a rse houver um fora, caso contrário a 0é, usando o fato de que '1'>'0'em Python com max(n[0],n[-1]).

Finalmente, a adição de 2cada recursão interna é corrigida com %2.

Jonathan Allan
fonte
0

PHP, 113 bytes

for($n=$argv[1];$n!=$c;$n=($a=$n>>.5+$e)|($b=$n&$c=(1<<$e/=2)-1))if($a&$b||($e=1+log($n,2))&!(1&$n>>$e/2))die(1);

sai com erro (código 1) se o argumento não for super dobrável, código0 mais. Corra com -r.
A entrada 0retornará true (código 0).

demolir

for($n=$argv[1];            
    $n!=$c;                 // loop while $n is != mask
                            // (first iteration: $c is null)
    $n=                     // add left half and right half to new number
        ($a=$n>>.5+$e)      // 7. $a=left half
        |
        ($b=$n&             // 6. $b=right half
            $c=(1<<$e/=2)-1 // 5. $c=mask for right half
        )
)
    if($a&$b                // 1. if any bit is set in both halves
                            // (first iteration: $a and $b are null -> no bits set)
        ||                  // or
        ($e=1+log($n,2))    // 2. get length of number
        &
        !(1&$n>>$e/2)       // 3. if the middle bit is not set -> 1
                            // 4. tests bit 0 in length --> and if length is odd
    )
    die(1);                 // -- exit with error
Titus
fonte
0

PHP, 197 bytes

function f($b){if(!$b)return;if(!strpos($b,"0"))return 1;for($n="",$i=0;$i<($l=strlen($b))>>1;)$n.=$b[$i]+$b[$l-++$i];if($l%2&&!$b[$i]||strstr($n,"2"))return;return f($n);}echo f(decbin($argv[1]));

Expandido

function f($b){
    if(!$b)return; # remove 0
    if(!strpos($b,"0"))return 1; # say okay alternative preg_match("#^1+$#",$b)
    for($n="",$i=0;$i<($l=strlen($b))>>1;)$n.=$b[$i]+$b[$l-++$i]; #add first half and second reverse
    if($l%2&&!$b[$i]||strstr($n,"2"))return; #if middle == zero or in new string is a 2 then it's not a number that we search
    return f($n); #recursive beginning
}
echo f(decbin($argv[1]));

Valores verdadeiros <10000

1, 2, 3, 6, 7, 8, 10, 12, 15, 20, 22, 28, 31, 34, 38, 42, 48, 52, 56, 63, 74, 78, 90, 104, 108, 120, 127, 128, 130, 132, 142, 150, 160, 170, 178, 192, 204, 212, 232, 240, 255, 272, 274, 276, 286, 310, 336, 346, 370, 400, 412, 436, 472, 496, 511, 516, 518, 524, 542, 558, 580, 598, 614, 640, 642, 648, 666, 682, 704, 722, 738, 772, 796, 812, 852, 868, 896, 920, 936, 976, 992, 1023, 1060, 1062, 1068, 1086, 1134, 1188, 1206, 1254, 1312, 1314, 1320, 1338, 1386, 1440, 1458, 1506, 1572, 1596, 1644, 1716, 1764, 1824, 1848, 1896, 1968, 2016, 2047, 2050, 2054, 2058, 2064, 2068, 2072, 2110, 2142, 2176, 2180, 2184, 2222, 2254, 2306, 2320, 2358, 2390, 2432, 2470, 2502, 2562, 2576, 2618, 2650, 2688, 2730, 2762, 2866, 2898, 2978, 3010, 3072, 3076, 3080, 3132, 3164, 3244, 3276, 3328, 3380, 3412, 3492, 3524, 3584, 3640, 3672, 3752, 3784, 3888, 3920, 4000, 4032,4095, 4162, 4166, 4170, 4176, 4180, 4184, 4222, 4318, 4416, 4420, 4424, 4462, 4558, 4674, 4688, 4726, 4822, 4928, 4966, 5062, 5186, 5200, 5242, 5338, 5440, 5482, 5578, 5746, 5842, 5986, 6082, 6208, 6212, 6216, 6268, 6364, 6508, 6604, 6720, 6772, 6868, 7012, 7108, 7232, 7288, 7384, 7528, 7624, 7792, 7888, 8032, 8128, 8191, 8202, 8206, 8218, 8232, 8236, 8248, 8318, 8382, 8456, 8460, 8472, 8542, 8606, 8714, 8744, 8814, 8878, 8968, 9038, 9102, 9218, 9222, 9234, 9248, 9252, 9264, 9334, 9398, 9472, 9476, 9488, 9558, 9622, 9730, 9760, 9830, 9894, 99848128, 8191, 8202, 8206, 8218, 8232, 8236, 8248, 8318, 8382, 8456, 8460, 8472, 8542, 8606, 8714, 8744, 8814, 8878, 8968, 9038, 9102, 9218, 9222, 9234, 9248, 9252, 9264, 9334, 9398, 9472, 9476, 9488, 9558, 9622, 9730, 9760, 9830, 9894, 99848128, 8191, 8202, 8206, 8218, 8232, 8236, 8248, 8318, 8382, 8456, 8460, 8472, 8542, 8606, 8714, 8744, 8814, 8878, 8968, 9038, 9102, 9218, 9222, 9234, 9248, 9252, 9264, 9334, 9398, 9472, 9476, 9488, 9558, 9622, 9730, 9760, 9830, 9894, 9984

Jörg Hülsermann
fonte