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 .

Stewie Griffin
fonte
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.

Martin Ender
fonte
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().getAsInt()-47)
                        //     where `b` is the largest digit in the String + 1
  );                    //  End of loop
  return s;             //  Return result-String
}                       // End of method
Kevin Cruijssen
fonte
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
isaacg
fonte
É 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"))

Tom
fonte
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
Mr. Xcoder
fonte
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)
Emigna
fonte
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
@Emigna Huh?
Erik the Outgolfer
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!

Adão
fonte
3

Ruby , 60 56 bytes

->n{n=(s=n.to_s).to_i(s.bytes.max-47)while/9/!~s&&n>9;n}

Experimente online!

Value Ink
fonte
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.

Greg Martin
fonte
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
}
Brad Gilbert b2gills
fonte
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
DLosc
fonte
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.

Emigna
fonte
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; };
Ceshion
fonte
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)&
J42161217
fonte
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')
user71507
fonte
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
rua
fonte
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

jrtapsell
fonte
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;}
Govind Parmar
fonte
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.

V. Courtois
fonte