A melhor base é 10 ... Vamos alcançá-lo!


40

Entrada:

Um número inteiro positivo n que consiste em dígitos no intervalo de 0 a 9 .

Desafio:

Se d é o dígito mais alto do número inteiro, assuma que a base do número é d + 1 . Por exemplo, se o número inteiro é 1256 , você deve assumir que está na base-7 , se for 10110 , deve assumir que é a base-2 (binária) e, se for 159 , é decimal.

Agora, faça o seguinte até você: 1: atingir um número inteiro de base 10 ou 2: alcançar um número inteiro de um dígito.

  1. Converta o número inteiro de base- (d + 1) em base-10
  2. Encontre a base desse novo número inteiro (novamente, base- (d + 1) onde d é o dígito mais alto do novo número)
  3. Vá para o passo 1 .

Exemplos:

Suponha que a entrada seja n = 413574 . O dígito mais alto d = 7 , então isso é base-8 (octal). Converta isso em decimal e obtenha 137084 . O dígito mais alto d = 8 , então isso é base-9 . Converta isso em decimal e obtenha 83911 . O dígito mais alto é 9 , então esse é um número decimal e paramos. A saída deve ser 83911 .

Suponha que a entrada seja n = 13552 . O dígito mais alto é d = 5 , então isso é base-6 . Converta isso em decimal e obtenha 2156 . O dígito mais alto d = 6 , então isso é base-7 . Converta isso em decimal e obtenha 776 . O dígito mais alto é d = 7 , então isso é base-8 . Converta isso em decimal e obtenha 510 . O dígito mais alto é d = 5 portanto é a base-6 . Converta isso em decimal e obtenha 186 . O dígito mais alto é 8 , então é a base-9 . Converta isso para decimal e obtenha 159 . O dígito mais alto é 9, então esse é um número decimal e paramos. A saída deve ser 159 .

Suponha que a entrada seja n = 17 . Isso nos dará 15 , depois 11 e 3 , que produziremos uma vez que é um dígito único.


Casos de teste:

5
5

17
3

999
999

87654321  (base-9 -> 42374116 in decimal -> base-7 -> 90419978 in decimal) 
9041998

41253  (5505 -> 1265 -> 488 -> 404 -> 104 -> 29)
29

Notas:

  • Regras padrão sobre E / S, brechas, etc. Você pode considerar a entrada como uma string
  • As explicações são incentivadas
  • Você pode usar comandos internos de conversão de base
    • As soluções que não usam as funções internas de conversão de base da linguagem (se existirem) são bem-vindas, mesmo que elas acabem sendo muito mais longas do que a abordagem óbvia usando funções internas.

Aparentemente, esse é o OEIS A091047 .


2
Aparentemente, eu amo matrizes , então pensei em fazer um desafio de conversão de base .
— Stewie Griffin

34
"A melhor base é 10" ... "10" está escrito em qual base?
— Olivier Grégoire

5
@ OlivierGrégoire Essa é a coisa mais inteligente ... Qualquer que seja a base que tenhamos, ainda será uma declaração válida!
— Stewie Griffin

@ StewieGriffin Mas como você o lê? "10" tem um nome diferente em cada base.
— user11153

10
Bem, isso depende da base ... ou como Meghan diria que "é tudo sobre essa base, 'Bout essa base, sem problemas" ;-)
— Stewie Griffin

Respostas:


20

Mathematica, 56 bytes

#//.x_/;(b=Max[d=IntegerDigits@x]+1)<11:>d~FromDigits~b&

Experimente online!(Usando matemática.)

Eu pensei em verificar como é a sequência:

insira a descrição da imagem aqui

E aqui está um gráfico do número de etapas necessárias para encontrar o resultado:

insira a descrição da imagem aqui

(Clique para versões maiores. Veja o histórico de revisões para gráficos apenas até n = 1000. )

Parece uma mistura muito interessante de estrutura em grande escala e caos em pequena escala. Eu me pergunto o que há com as lacunas mais amplas em torno de 30.000 e 60.000.


4
@StewieGriffin deve estar no lado esquerdo. As pequenas lacunas estão lá, porque os números que levam a um múltiplo de uma potência de 10 contêm a 9, então eles já estão na base 10. Mas, para 30k e 60k, parece que números com 8 ou até 7 (teriam que check) no lugar desses 9 sempre se tornam a base 10 após, no máximo, uma etapa.
— Martin Ender

@StewieGriffin Para ser mais preciso, todos os números no intervalo [28051, 28888] são da base 9 e se traduzem em números do formato 19xxx, duplicando assim essa lacuna.
— cmaster

Ah, entendi ... :) Para constar: eu sabia por que havia lacunas no lado esquerdo das potências dos anos 10 ... Somente as lacunas de tamanho duplo eram estranhas (por que 30/60 e não 20 / 40/50). Agora vejo que esses números estão no intervalo 28xxx -> 19xxx, mas 38xxx -> 26xxx, não 29xxx.
— Stewie Griffin

10

Java 8, 172 166 163 152 151 140 138 116 114 99 bytes

s->{for(Integer b=0;b<10&s.length()>1;s=""+b.valueOf(s,b=s.chars().max().getAsInt()-47));return s;}

Toma a entrada como a String.

-64 bytes graças a @ OlivierGrégoire . E aqui eu pensei que meu 172 inicial não era tão ruim ..;)

Experimente aqui.

Explicação:

s->{                    // Method with String as parameter and return-type
  for(Integer b=0;b<10  //  Loop as long as the largest digit + 1 is not 10
      &s.length()>1;    //  and as long as `s` contains more than 1 digit
    s=""+               //   Replace `s` with the String representation of:
         b.valueOf(s,   //    `s` as a Base-`b` integer
          b=s.chars().max().ge‌tAsInt()-47)
                        //     where `b` is the largest digit in the String + 1
  );                    //  End of loop
  return s;             //  Return result-String
}                       // End of method

11
Promete ficar calmo? : p Ok ... vamos lá: s->{for(Integer b=0;b<10&s.length()>1;)s=""+b.valueOf(s,b=s.chars().max().getAsInt()-47);return s;}. Também apaguei a maioria dos meus comentários, pois agora são totalmente irrelevantes ( bé a base, o seu a; e sé o número em que estamos trabalhando).
— Olivier Grégoire

11
Tentei recursificar isso para remover alguns bytes com: Integer b;return(b=s.chars().max().getAsInt()-47)>9|s.length()<2?s:c(""+b.valueOf(s,b));(88), mas sou novo em codificar golf. Este é um trecho, certo? Existe uma maneira de declarar isso como um método sem a necessidade de adicionar public String c(String s)?
— Lord Farquaad

11
@LordFarquaad Você não precisa do public, mas receio que você realmente precise usar String c(String s){}chamadas recursivas, mesmo no Java 8. Quando você cria um lambda usando java.util.function.Function<String, String> c=s->{Integer b;return(b=s.chars().max().getAsInt()-47)>9|s.length()<2?s:c‌.apply​(""+b.valueOf(s,b));}ou interface usando, interface N{String c(String s);}N n = s->{Integer b;return(b=s.chars().max().getAsInt()-47)>9|s.length()<2?s:n.c‌​(""+b.valueOf(s,b));};ele dará uma " auto-referência no inicializador erro "nos dois casos. Mas uma abordagem muito agradável, no entanto!
— Kevin Cruijssen 28/06

Ah, acho que eu destruí alguns bytes então. Mas obrigado pela ajuda! Vou manter isso em mente no futuro.
— Lord Farquaad

8

Pitão, 9 bytes

ui`GhseS`

Suíte de teste

Explicação:

ui`GhseS`
ui`GhseS`GQ    Implicit variable introduction
u         Q    Repeatedly apply the following function until the value repeats,
               starting with Q, the input.
        `G     Convert the working value to a string.
      eS       Take its maximum.
     s         Convert to an integer.
    h          Add one.
 i`G           Convert the working value to that base

É um pouco estranho como você usou um lambda de duas variáveis ​​e acabou usando uma variável ... e isso não gerou erros. Ah, as duas variáveis ​​são Qe Q, entendi.
— Erik the Outgolfer

@EriktheOutgolfer Não exatamente. usem sua terceira entrada é aplicada até a repetição, enquanto que com uma terceira entrada é aplicada um número fixo de vezes. ulambda tem Ge H, mas você não precisa usar H.
— Isaacg

Na verdade, substituir Gpor Hteria o mesmo resultado ... btw variável implícita é G?
— Erik the Outgolfer

@EriktheOutgolfer A variável implícita é Gsim. Hconta de 0 a cada iteração, por isso é completamente diferente. Não tenho muita certeza do que você está falando. Aqui está um exemplo de programa para mostrar o que está acontecendo: pyth.herokuapp.com/…
— isaacg

6

JavaScript (ES6), 63 57 54 53 bytes

f=a=>a>9&(b=Math.max(...a+""))<9?f(parseInt(a,b+1)):a

Economizou 8 bytes graças a Shaggy e Dom Hastings

f=a=>a>9&(b=Math.max(...a+""))<9?f(parseInt(a,b+1)):a;

console.log(f("413574"))


Bata-me para isso. Eu acho que você poderia economizar alguns bytes +a>9||b<9e reverter o ternário.
— Shaggy

11
@Shaggy edit: Eu sou burro
— Tom

11
Não seja tão duro consigo mesmo, Tom! Você não é burro, mas definitivamente não é tão esperto quanto o @Shaggy!
— Stewie Griffin

11
Alternativa para 55 bytesf=n=>n>9&&(k=Math.max(...n+"")+1)<10?f(parseInt(n,k)):n
— Dom Hastings

@DomHastings Obrigado pelas melhorias! :)
— Tom

5

Python 3 , 91 78 76 75 73 bytes

@Emigna raspou 5 bytes. @FelipeNardiBatista salvou 1 byte. @ RomanGräf salvou 2 bytes

i=input()
while'9'>max(i)and~-len(i):i=str(int(i,int(max(i))+1))
print(i)

Experimente online!


Explicação

i=input()                                  - takes input and assigns it to a variable i
while '9'>max(i)and~-len(i):               - repeatedly checks if the number is still base-9 or lower and has a length greater than 1
    i=str(...)                             - assigns i to the string representation of ...
          int(i,int(max(i))+1)             - converts the current number to the real base 10 and loops back again
print(i)                                   - prints the mutated i

5

05AB1E , 10 5 bytes

5 bytes economizados graças ao Magic Octopus Urn

F§Z>ö

Como isso diminui muito rapidamente para grandes entradas, estou deixando a versão antiga muito mais rápida aqui para teste. O algoritmo é o mesmo, apenas o número de iterações é diferente.

[©Z>öD®Q#§

Experimente online!

Explicação

[             # start a loop
 ©            # store a copy of the current value in the register
  Z>          # get the maximum (digit) and increment
    ö         # convert the current value to base-10 from this base
     D        # duplicate
      ®Q#     # break loop if the new value is the same as the stored value
         §    # convert to string (to prevent Z from taking the maximum int on the stack)

Além disso, você não pode simplesmente usar тFZ>ö§? Vendo como o número de iterações ( como visto aqui ) parece platô? Se você quer ser técnico, a taxa na qual as iterações aumentam é provavelmente logarítmica ... Portanto, você pode usar algo como: DFZ>ö§e declarar que não será executado em grande escala n. OU talvez até: T.n>FZ>ö§calcular diretamente o número de iterações como log_10(n).
— Magic Octopus Urn

@MagicOctopusUrn: Sim, agora que você mencionou, como a sequência definitivamente parece mais lenta que linear, F§Z>ödeve fazer o truque.
— Emigna

Eu acho que você pode remover o §.
— Erik the Outgolfer

@EriktheOutgolfer: Infelizmente não. Se removermos o §, Zassumirá o número mais alto da pilha em vez do dígito mais alto do número na parte superior da pilha.
— Emigna


3

APL (Dyalog) , 20 16 bytes

Pega e retorna uma string

((⍕⊢⊥⍨1+⌈/)⍎¨)⍣≡

(… )⍣≡ Aplique a seguinte função até que dois termos consecutivos sejam idênticos:

 ⍎¨ executar cada caractere (transforma a string em uma lista de números)

 (… ) Aplique a seguinte função tácita a isso:

  ⌈/ encontre o máximo do argumento

  1+ Adicione um

  ⊢⊥⍨ avaliar o argumento nessa base

  ⍕ formato (stringify, em preparação para outra aplicação da função externa)

Experimente online!



3

Mathematica, 52 bytes

FromDigits[s=IntegerDigits@#,Max@s+1]&~FixedPoint~#&

Função pura, recebendo um número inteiro não negativo como entrada e retornando um número inteiro não negativo. Usa a mesma mecânica central FromDigits[s=IntegerDigits@#,Max@s+1]como resposta de Jenny_mathy , mas explora FixedPointa fazer a iteração.


3

Perl 6 , 49 bytes

{($_,{.Str.parse-base(1+.comb.max)}...*==*).tail}

Teste-o

Expandido:

{
  (

    $_,                 # seed the sequence with the input

    {
      .Str
      .parse-base(      # parse in base:
        1 + .comb.max   # largest digit + 1
      )
    }

    ...                 # keep generating values until

    * == *              # two of them match (should only be in base 10)

  ).tail                # get the last value from the sequence
}


2

Pip , 17 bytes

Wa>9>YMXaaFB:1+ya

Recebe entrada como um argumento de linha de comando. Experimente online!

Explicação

Isso foi divertido - eu tive que retirar os operadores de comparação de encadeamento.

Queremos fazer um loop até o número ter um único dígito OU conter um 9. Equivalentemente, queremos fazer um loop enquanto o número é de vários dígitos E não contém um 9. Equivalentemente, fazer um loop enquanto o número é maior que 9 E o dígito máximo é menos de 9: a>9>MXa.

Wa>9>YMXaaFB:1+ya
                   a is 1st cmdline arg (implicit)
     YMXa          Yank a's maximum digit into the y variable
Wa>9>              While a is greater than 9 and 9 is greater than a's max digit:
         aFB:1+y    Convert a from base 1+y to decimal and assign back to a
                a  At the end of the program, print a

2

Python 2 , 60 59 56 53 bytes

Guardado 4 bytes graças a Felipe Nardi Batista
Guardado 3 bytes graças a ovs

f=lambda x,y=0:x*(x==y)or f(`int(x,int(max(x))+1)`,x)

Experimente online!

Usando uma lambda recursiva, comparando o resultado da conversão de base com a iteração anterior.


por que não usar x==y and x or ...como xnunca será 0(base 1). ou mesmo(x==y)*x or ...
— Felipe Nardi Batista

@FelipeNardiBatista: Obrigado! Eu tentei x and x==y or ...que não funcionou, mas eu não estou muito acostumado com esses truques assim que eu não sabia que eu poderia reverter isso :)
— Emigna

@ovs: Você está certo. Obrigado!
— Emigna

@FelipeNardiBatista "Input: Um número inteiro positivo n composto por dígitos no intervalo de 0 a 9." 0 ainda é uma entrada válida e agora o código a rejeita.
— Mast

@ Master: Felizmente para nós, 0 não é um número inteiro positivo, portanto não será fornecido como entrada.
— Emigna

2

C #, 257 244 243 244 233 222 bytes

using System.Linq;z=m=>{int b=int.Parse(m.OrderBy(s=>int.Parse(s+"")).Last()+""),n=0,p=0;if(b<9&m.Length>1){for(int i=m.Length-1;i>=0;i--)n+=int.Parse(m[i]+"")*(int)System.Math.Pow(b+1,p++);return z(n+"");}else return m;};

Bem, o C # sempre usa muitos bytes, mas isso é ridículo. Nenhum dos built-ins pode lidar com uma base arbitrária, então eu tive que calcular a conversão sozinho. Ungolfed:

using System.Linq;
z = m => {
int b = int.Parse(m.OrderBy(s => int.Parse(s + "")).Last()+""), n = 0, p = 0; //Get the max digit in the string
if (b < 9 & m.Length > 1) //if conditions not satisfied, process and recurse
{
    for (int i = m.Length - 1; i >= 0; i--)
        n += int.Parse(m[i] + "") * (int)System.Math.Pow(b+1, p++); //convert each base-b+1 representation to base-10
    return z(n + ""); //recurse
}
else return m; };

1

Mathematica, 92 bytes

f[x_]:=FromDigits[s=IntegerDigits@x,d=Max@s+1];(z=f@#;While[d!=10&&Length@s>1,h=f@z;z=h];z)&

1

Javascript (ES6) com função de seta 0, 74 bytes

function f(a){a>9&&b=Math.max(...a)<9&&f(parseInt(a,b+1));alert(a)}f('11')

3
Bem-vindo ao PPCG! :) Esta é provavelmente uma resposta muito boa, mas não posso dizer sem uma explicação. Eu (e provavelmente outros) nunca votou acima em respostas que não contêm explicações.
— Stewie Griffin

11
Por que você está ligando f('11')após a função? A menos que eu esteja perdendo algo que apenas parece ser de uso, na verdade não faz parte do envio. Nesse caso, você deve retirá-lo da seção de código e colocá-lo em sua explicação (quando adicionar um) e atualizar sua contagem de bytes para 67.
— PunPun1000

1

K4 , 19 bytes

Solução:

{(1+|/x)/:x:10\:x}/

Exemplos:

q)\
  {(1+|/x)/:x:10\:x}/413574
83911
  {(1+|/x)/:x:10\:x}/13552
159
  {(1+|/x)/:x:10\:x}/17
3
  {(1+|/x)/:x:10\:x}/41253
29    

Explicação:

Use /:interno para converter a base.

{(1+|/x)/:x:10\:x}/ / the solution
{                }/ / converge lambda, repeat until same result returned
            10\:x   / convert input x to base 10 (.:'$x would do the same)
          x:        / store in variable x
 (     )/:          / convert to base given by the result of the brackets
    |/x             / max (|) over (/) input, ie return largest
  1+                / add 1 to this

1

Kotlin , 97 bytes

fun String.f():String=if(length==1||contains("9"))this else "${toInt(map{it-'0'}.max()!!+1)}".f()

Embelezado

fun String.f(): String = if (length == 1 || contains("9")) this else "${toInt(map { it - '0' }.max()!! + 1)}".f()

Teste

fun String.f():String=if(length==1||contains("9"))this else "${toInt(map{it-'0'}.max()!!+1)}".f()
val tests = listOf(
        5 to 5,
        17 to 3,
        999 to 999,
        87654321 to 9041998,
        41253 to 29
)

fun main(args: Array<String>) {
    tests.forEach { (input, output) ->
        val answer = input.toString().f()
        if (answer != output.toString()) {
            throw AssertionError()
        }
    }
}

TIO

TryItOnline




0

C, 159 157 bytes

#include <stdlib.h>
char b[99];i=0;m=-1;c(n){do{m=-1;sprintf(b,"%d",n);i=0;while(b[i]){m=max(b[i]-48,m);i++;}n=strtol(b,0,++m);}while(b[1]&&m<10);return n;}

0

Scala , 119 bytes

if(x.max==57|x.length==1)x else{val l=x.length-1
f((0 to l).map(k=>(((x(k)-48)*math.pow(x.max-47,l-k))) toInt).sum+"")}

Experimente online!

Scala , 119 bytes

if(x.max==57|x.length==1)x else f((0 to x.length-1).map(k=>(((x(k)-48)*math.pow(x.max-47,x.length-1-k))) toInt).sum+"")

Experimente online!

Ambos os métodos funcionam da mesma maneira, mas no primeiro eu insiro x.length-1uma variável e no segundo não.

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.