Base grande, dígitos pequenos


19

A linguagem J possui uma sintaxe muito boba para especificar constantes . Quero focar em um recurso interessante em particular: a capacidade de escrever em bases arbitrárias.

Se você escrever XbYpara Xqualquer número e Yqualquer sequência de alfanuméricos, J interpretará Ycomo um Xnúmero base , onde 0por meio 9terá seu significado usual e apor meio zrepresentará 10 a 35.

E quando digo Xqualquer número, quero dizer qualquer número. Para os propósitos desta pergunta, tentarei Xser um número inteiro positivo, mas em J você pode usar qualquer coisa: números negativos, frações, números complexos, qualquer que seja.

O que é estranho é que você só pode usar os números de 0 a 35 como sua base, qualquer que seja o dígito, porque sua coleção de símbolos utilizáveis ​​consiste apenas de 0 a 9 e az.

O problema

Quero um programa para me ajudar a jogar números mágicos como 2.933.774.030.998 usando esse método. Bem, ok, talvez não tão grande, eu vou ser fácil com você. Então...

A sua tarefa é escrever um programa ou função que leva um (normalmente grande) número decimal Nentre 1 e 4294967295 (= 2 32 -1) como entrada, e as saídas / retorna a representação mais curto da forma XbY, em que Xé um número inteiro positivo, Yestá uma sequência composta por alfanuméricos (0-9 e az, sem distinção entre maiúsculas e minúsculas) e Yinterpretada em bases Xiguais N.

Se o comprimento de cada representação de XbYrepresentação for maior ou igual ao número de dígitos de N, em seguida, imprima N. Em todos os outros vínculos, você pode gerar qualquer subconjunto não vazio das representações mais curtas.

Isso é código de golfe, então quanto menor, melhor.

Casos de teste

      Input | Acceptable outputs (case-insensitive)
------------+-------------------------------------------------------
          5 | 5
            |
   10000000 | 79bkmom  82bibhi  85bgo75  99bauua  577buld
            | 620bq9k  999baka
            |
   10000030 | 85bgo7z
            |
   10000031 | 10000031
            |
   12345678 | 76bs9va  79bp3cw  82bmw54  86bjzky  641buui
            |
   34307000 | 99bzzzz
            |
   34307001 | 34307001
            |
 1557626714 | 84bvo07e  87brgzpt  99bglush  420blaze
            |
 1892332260 | 35bzzzzzz  36bvan8x0  37brapre5  38bnxkbfe  40bij7rqk
            | 41bgdrm7f  42bek5su0  45bablf30  49b6ycriz  56b3onmfs
            | 57b38f9gx  62b244244  69b1expkf  71b13xbj3
            |
 2147483647 | 36bzik0zj  38br3y91l  39bnvabca  42bgi5of1  48b8kq3qv
 (= 2^31-1) | 53b578t6k  63b2akka1  1022b2cof  1023b2661  10922bio7
            | 16382b8wv  16383b8g7  32764b2gv  32765b2ch  32766b287
            | 32767b241
            |
 2147483648 | 512bg000  8192bw00
            |
 4294967295 | 45bnchvmu  60b5vo6sf  71b2r1708  84b12mxf3  112brx8iv
 (= 2^32-1) | 126bh5aa3  254b18owf  255b14640  1023b4cc3  13107bpa0
            | 16383bgwf  21844b9of  21845b960  32765b4oz  32766b4gf
            | 32767b483  65530b1cz  65531b1ao  65532b18f  65533b168
            | 65534b143  65535b120

Se você não souber se uma representação é igual a algum número, use qualquer intérprete J, como o do Try It Online . Basta digitar stdout 0":87brgzpte J voltará a sair 1557626714. Observe que J aceita apenas letras minúsculas, mesmo que esse problema não diferencie maiúsculas de minúsculas.

Alguma teoria possivelmente útil

  • Para todos os Nmenos de 10.000.000, a representação decimal é tão curta quanto qualquer outra e, portanto, é a única saída aceitável. Para salvar qualquer coisa, você precisará ter pelo menos quatro dígitos a menos na nova base e ainda mais se a base for maior que 99.
  • Basta verificar as bases até o teto da raiz quadrada de N. Para qualquer base maior B , Nhaverá no máximo dois dígitos na base B , portanto, na primeira vez em que você obtiver algo com um primeiro dígito válido, será em torno de B 35/35 N. Mas, nesse tamanho, você sempre será pelo menos tão grande quanto a representação decimal; portanto, não há sentido em tentar. Isso em mente, ceil (sqrt (número maior, pedirei que você resolva esse problema)) = 65536.
  • Se você tiver alguma representação em uma base menor que 36, a representação da base 36 será pelo menos tão curta. Portanto, você não precisa se preocupar com soluções acidentalmente curtas em bases inferiores a 36. Por exemplo, a representação 35bzzzzzzpara 1.892.332.260 usa um dígito incomum para essa base, mas 36bvan8x0tem o mesmo comprimento.

Lol, 1557626714 = 420blaze ^ _ ^
DrQuarius

Respostas:


9

JavaScript (ES6), 103 101 bytes

Recebe a entrada como uma sequência.

n=>[...Array(7e4)].reduce(p=>p[(r=++b+(g=x=>x?g(x/b|0)+(x%b).toString(36):'b')(n)).length]?r:p,n,b=2)

Casos de teste

NOTA: O número de iterações na função de trecho é limitado a 600, para que os casos de teste sejam concluídos mais rapidamente. (Isso levaria alguns segundos.)


Se meu número for muito grande para trabalhar com isso, como eu o corrigirei? Aumentar as iterações não parece ajudar.
FrownyFrog

N<232.

Pesquisa "Números perniciosos", 2136894800297704.
FrownyFrog 25/08

@FrownyFrog Você pode processá-lo aumentando o número de iterações e usando em Math.floor(x/b)vez de x/b|0. (Mas eu não testá-lo.)
Arnauld

11
funcionou! Obrigado.
FrownyFrog

3

Ruby , 118 bytes

Isso foi vinculado em outra pergunta e eu notei que não há muitas respostas aqui, então decidi tentar.

Percorra todas as bases até e incluindo a entrada para construir todas as construções válidas do número J. No entanto, ele pula de 1 a 8, porque não há nenhuma maneira de serem menores do que a representação da base 10. É uma solução bastante ingênua, considerando todas as coisas, uma vez que chama o digitsbuilt-in para obter os dígitos, mas como isso começa com o dígito menos significativo primeiro, temos reverseque obter o número real, para que possa ser melhorado.

É lento. Então, muuuuito incrivelmente lento. O tempo limite do TIO é 34307000, por exemplo. Nós poderia ir com a raiz quadrada ou até mesmo a escolha de Arnauld de7e4 economizar tempo, mas bytes que os custos extras, então porque se preocupar?

->n{([n.to_s]+(9..n).map{|b|d=n.digits b;"#{b}b"+d.reverse.map{|i|i.to_s 36}*''if d.all?{|i|i<36}}-[p]).min_by &:size}

Experimente online!

Experimente on-line com sqrt para que tudo termine no prazo


1

05AB1E , 37 bytes

[¼35ݾãvtîEyNβQižhA«yèJ'bìNìDgIg@i\}q

Deve funcionar em teoria, mas atinge o tempo limite para todos os casos de teste não triviais 10000000. O produto cartesiano embutido ãé extremamente lento para4..

Sem a declaração if final, DgIg@i\}ela ainda pode ser testada para valores mais baixos, para verificar se realmente funciona: Experimente online.

Vou ver se consigo encontrar uma solução (provavelmente muito mais longa, mas) mais eficiente posteriormente.

Explicação:

[              # Start an infinite loop:
 ¼             #  Increase the counter variable by 1 (0 by default)
 35Ý           #  Push a list in the range [0, 35]
 ¾ã            #  Take the cartesian product of this list with itself,
               #  with chunks-sizes equal to the counter variable
 v             #  Loop `y` over each of these lists:
  t            #   Take the square-root of the (implicit) input-integer
   î           #   Ceil it
  E            #   Loop `N` in the range [1, ceil(square(input))]:
   yNβ         #    Convert list `y` to base-`N`
   Qi          #    If it's equal to the (implicit) input-integer:
     žh        #     Push string "0123456789"
       A«      #     Append the lowercase alphabet
     yè        #     Index each value in list `y` into this string
     J         #     Join the characters to a single string
     'bì      '#     Prepend a "b"
        Nì     #     Prepend the number `N`
     D         #     Duplicate it
      g        #     And pop and push the length of this string
       Ig      #     Also push the length of the input
         @i }  #     If the length of the string is >= the input-length:
           \   #      Discard the duplicated string
     q         #     Stop the program
               #     (after which the result is output implicitly;
               #      or if the string was discarded and the stack is empty, it will
               #      implicitly output the implicit input as result instead)

11
Resposta impressionante! Acho que você está perdendo uma regra: "Se o comprimento de toda representação XbYrepresentada for maior ou igual ao número de dígitos de N, então emita a saída N". Enquanto você tem os primeiros 10 milhões de números cobertos, suspeito que uma entrada de 10000031devolverá algo como 26blmoof. O número é válido, mas o comprimento é o mesmo da entrada, portanto, ele deve retornar a entrada.
Value Ink

@ValueInk Ah oops. Obrigado por perceber! Deve ser corrigido agora ao custo de alguns bytes.
Kevin Cruijssen 21/06
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.