Em que base está esse número?

31

Aqui está um desafio fácil e agradável:

Dada uma sequência que representa um número em uma base desconhecida, determine a base mais baixa possível em que esse número possa estar. A sequência conterá apenas 0-9, a-z . Se desejar, você pode escolher letras maiúsculas em vez de minúsculas, mas especifique isso. Você deve gerar esta base mais baixa possível em decimal.

Aqui está um exemplo mais concreto. Se a sequência de entrada for "01234", é impossível que esse número esteja em binário, pois 2, 3 e 4 estão todos indefinidos em binário. Da mesma forma, esse número não pode estar na base 3 ou na base 4. Portanto, esse número deve estar na base 5 ou em uma base superior, portanto, você deve gerar '5'.

Seu código deve funcionar para qualquer base entre a base 1 (unária, todos os '0') e a base 36 ('0-9' e 'a-z').

Você pode receber e fornecer saída em qualquer formato razoável. Builtins de conversão de base são permitidos. Como sempre, as brechas padrão se aplicam e a resposta mais curta em bytes é a vencedora!

Teste de E / S:

#Input          #Output
00000       --> 1
123456      --> 7
ff          --> 16
4815162342  --> 9
42          --> 5
codegolf    --> 25
0123456789abcdefghijklmnopqrstuvwxyz    --> 36
DJMcMayhem
fonte
8
Posso imprimir na base 36?
Freira vazada
9
@LeakyNun Geez, espero que não.
Dennis
4
@LeakyNunYou must output this lowest possible base in decimal.
DJMcMayhem
3
@RohanJhunjhunwala Se esse é o seu idioma mais próximo do equivalente a uma string, não vejo por que não.
DJMcMayhem
3
Geralmente unário é 1s e zeros à esquerda não são padrão para qualquer sistema numérico baseado em posição.
parar de prejudicar Monica

Respostas:

16

Gelatina , 4 bytes

ṀØBi

Requer maiúsculas. Experimente online! ou verifique todos os casos de teste .

Como funciona

ṀØBi  Main link. Arguments: s (string)

Ṁ     Yield the maximum of s.
 ØB   Yield "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
   i  Find the 1-based index of the maximum in that string.
Dennis
fonte
1
Na verdade, são 7 bytes, não 4. Os dois primeiros caracteres são de vários bytes.
Nicomak
14
@ Nicomak Esta resposta está codificada na página de código Jelly , onde todos esses caracteres são codificados como 1 byte cada.
Loovjo 23/08/19
26

Python, 27 22 bytes

lambda s:(max(s)-8)%39

Isso requer que a entrada seja uma bytestring (Python 3) ou uma bytearray (Python 2 e 3).

Graças a @AleksiTorhamo por jogar fora 5 bytes!

Teste em Ideone .

Como funciona

Começamos tomando o máximo da string. Como os pontos de código das letras são maiores que os pontos de código dos dígitos, esse caractere máximo também é o máximo de 36 dígitos da base.

O ponto de código de '0' - '9' é 48 - 57 , portanto, devemos subtrair 48 de seus pontos de código para calcular os dígitos correspondentes, ou 47 para calcular a base mais baixa possível. Da mesma forma, os pontos de código das letras 'a' - 'z' são 97 - 122 . Como 'a' representa o dígito com o valor 10 , devemos subtrair 87 dos pontos de código para calcular os dígitos correspondentes ou 86 para calcular a base mais baixa possível. Uma maneira de conseguir isso é a seguinte.

A diferença entre 97 e 58 ( ':' , o caractere após '9' ) é 39 , portanto, pegar os pontos de código no módulo 39 pode obter a subtração. Como 48% 39 = 9 e o resultado desejado para o caractere '0' é 1 , subtraímos 8 antes de pegar o módulo de resultado 39 . Subtrair primeiro é necessário, pois caso contrário 'u'% 39 = 117% 39 = 0 .

c    n    n-8    (n-8)%39
0    48    40     1
1    49    41     2
2    50    42     3
3    51    43     4
4    52    44     5
5    53    45     6
6    54    46     7
7    55    47     8
8    56    48     9
9    57    49    10
a    97    89    11
b    98    90    12
c    99    91    13
d   100    92    14
e   101    93    15
f   102    94    16
g   103    95    17
h   104    96    18
i   105    97    19
j   106    98    20
k   107    99    21
l   108   100    22
m   109   101    23
n   110   102    24
o   111   103    25
p   112   104    26
q   113   105    27
r   114   106    28
s   115   107    29
t   116   108    30
u   117   109    31
v   118   110    32
w   119   111    33
x   120   112    34
y   121   113    35
z   122   114    36
Dennis
fonte
Se você criar o Python 3 e usar a entrada como uma sequência de bytes, poderá soltar o ord()e ganhar por 3 bytes. :)
Aleksi Torhamo 23/08/16
Boa ideia! Deixe-me perguntar ao OP.
Dennis
3
@AleksiTorhamo NOOOOOOOOOOOO yu fazer dis
Rɪᴋᴇʀ
20

Python, 25 bytes

lambda x:int(max(x),36)+1

Define uma lambda que aceita a sequência x. Localiza o maior dígito da string (classificado com letras acima dos dígitos, por padrão do python) e converte na base 36. Adiciona 1, porque 8não está na base 8.

Rɪᴋᴇʀ
fonte
11

Haskell, 34 bytes

f s=length['\t'..maximum s]`mod`39

Usa a mod(ord(c)-8,39)ideia de Dennis.

41 bytes

g '0'=1
g 'W'=1
g x=1+g(pred x)
g.maximum

45 bytes:

(`elemIndex`(['/'..'9']++['a'..'z'])).maximum

Saídas como Just 3.

xnor
fonte
6

Queijo Cheddar , 34 29 21 bytes

Economizou 8 bytes graças a Dennis !!!

s->(s.bytes.max-8)%39

Usa letras minúsculas

Experimente online

Explicação

s -> (      // Input is `s`
  s.bytes    // Returns array of char codes
   .max      // Get maximum item in array
) % 39      // Modulus 39
Downgoat
fonte
1
Ou você poderia apenas colocar aspas em torno da entrada
DJMcMayhem
12
@DJMcMayhem .___. Eu nem sequer sei que minha própria língua poderia fazer isso
Downgoat
Que tal em (-)&8vez de n->n-8?
Conor O'Brien
@ ConorO'Brien> _> _> _> Ainda não cheguei a isso. Eu estava apenas planejando fazê-lo e, em seguida, este desafio foi publicado. Bassly se f&nliga nao primeiro argumento da função.
Downgoat 23/08/16
@Downgoat Oh. > _>
Conor O'Brien
6

05AB1E , 6 bytes

{¤36ö>

Leva letras maiúsculas.

Explicação

{       # sort
 ¤      # take last
  36ö   # convert from base 36 to base 10
     >  # increment

Experimente online

Emigna
fonte
Perdoe minha ingenuidade com 05AB1E, mas você quer dizer converter DA base 36 (para a base 10)?
Keeta 23/08/16
@ Keeta É claro que você está correto. Minha culpa.
Emigna
5

Julia, 22 bytes

!s=(maximum(s)-'')%39

Há um caractere BS (0x08) entre as aspas. Experimente online!

Dennis
fonte
o que -''faz?
Downgoat 23/08/16
Subtrai 8 do ponto de código e retorna um número inteiro.
Dennis
4

JavaScript (ES6), 41 37 bytes

s=>parseInt([...s].sort().pop(),36)+1

Editar: salvou 4 bytes graças a @ edc65.

Neil
fonte
use pop()para salvar 4
edc65 23/08
@ edc65 Não acredito que isso não esteja nas dicas de JavaScript.
Neil
3

Haskell, 55 40 bytes

f=(\y->mod(y-8)39).Data.Char.ord.maximum

Obrigado @Dennis por sua abordagem. (pegue isso, @xnor;))

ThreeFx
fonte
Eu acho que você pode remover f=por 38 bytes, uma vez fque não leva argumentos explícitos.
Cyoce 23/08/16
3

Perl 6: 18 bytes

{:36(.comb.max)+1}

Define um lambda que recebe um argumento de cadeia única e retorna um número inteiro. Divide a cadeia em caracteres, encontra a "mais alta", converte-a na base 36 e acrescenta 1.

{(.ords.max-8)%39}

Este usa a abordagem de módulo de Dennis. Mesmo comprimento.

smls
fonte
2

Retina , 28 bytes

O`.
.\B

{2`
$`
}T01`dl`_o
.

Experimente online! (A primeira linha ativa um conjunto de testes separado por avanço de linha.)

Explicação

O`.

Isso classifica os caracteres da entrada.

.\B

Isso remove todos os caracteres, exceto o último, para que os dois primeiros estágios encontrem o caractere máximo.

{2`
$`
}T01`dl`_o

Estes são dois estágios que formam um loop. O primeiro um duplica o primeiro carácter e os decréscimos segundo "" lo (por exemplo, substituindo xcom w, acom 9e 1com 0). O último estágio encontra um zero como o primeiro caractere; ele o remove. Essa é uma técnica padrão para gerar um intervalo de caracteres, considerando o limite superior. Portanto, isso gera todos os "dígitos" do 0número máximo.

.

Finalmente, contamos simplesmente o número de dígitos, o que nos dá a base.

Martin Ender
fonte
2

R, 99 89 85 bytes

Veja ! Menos de 100 bytes!
Veja ! 10 bytes de desconto!
Veja ! 4 bytes de desconto!

ifelse((m=max(strsplit(scan(,''),"")[[1]]))%in%(l=letters),match(m,l)+10,strtoi(m)+1)

Ungolfed:

l=letters                  #R's built-in vector of lowercase letters

n=scan(what=characters())  #Takes an input from STDIN and convert it to characters

m=max(strsplit(n,"")[[1]]) #Splits the input and takes to max. 
                           #`letters` are considered > to numbers (i.e. a>1)


ifelse(m%in%l,match(m,l)+10,strtoi(m)+1) #If the max is in `letters`,
                                             #outputs the matching position of `m`in `letters` + 10 (because of [0-9]). 
                                             #Else, outputs `m` (as a number) + 1.

Com frequência, esta resposta faz uso da ifelsefunção:ifelse(Condition, WhatToDoIfTrue, WhatToDoElse)

Frédéric
fonte
Eu amo sua versão; no entanto, tratar letras e números separadamente cria esses bytes extras irritantes. Por favor, dê uma olhada na minha solução que usa um método diferente.
Andreï Kostyrka
Sua resposta é realmente interessante. Vou usar o seu scanmétodo para golf alguns bytes;)
Frédéric
1

PHP, 51 38 bytes

(De Dennis) ^^

<?=(ord(max(str_split($argv[1])))-8)%39;

Outra proposta sem o truque de Dennis

<?=($a=max(str_split($argv[1])))<a?$a+1:ord($a)-86;
  • Recebe entrada como argumento $ argv [1];
  • Obter valores máximos de caracteres (usando ASCII)
  • Se for um número (inferior ao valor ascii <'a'), digite o número + 1
  • Outro valor ASCII de saída -86 (97 para 'a' em ASCII, -11 para 'a' é o 11º dígito base)
Crypto
fonte
É uma pena que o PHP tenha nomes de função detalhados: <?=base_convert(max(str_split($argv[1])),36,10)+1é uma solução elegante, mas com 49 bytes!
@YiminRong você pode usar em intval()vez de base_convert()diminuir para 38 bytes <?=intval(max(str_split($argn)),36)+1;tio: tio.run/##K8go@P/…
640KB
1

Oitava, 20 bytes

@(a)mod(max(a)-8,39)
alefalpha
fonte
1

Pyke, 6 bytes

Seb36h

Experimente aqui!

Se     -   sorted(input)[-1]
  b36  -  base(^, 36)
     h - ^ + 1
Azul
fonte
1

Java 7, 67 61 bytes

int c(char[]i){int m=0;for(int c:i)m=m>c?m:c;return(m-8)%39;}

(m-8)%39é graças à incrível resposta de @Dennis .

Ungolfed & código de teste:

Experimente aqui.

class Main{
  static int c(char[] i){
    int m = 0;
    for(int c : i){
      m = m > c
           ? m
           : c;
    }
    return (m-8) % 39;
  }

  public static void main(String[] a){
    System.out.println(c("00000".toCharArray()));
    System.out.println(c("123456".toCharArray()));
    System.out.println(c("ff".toCharArray()));
    System.out.println(c("4815162342".toCharArray()));
    System.out.println(c("42".toCharArray()));
    System.out.println(c("codegolf".toCharArray()));
    System.out.println(c("0123456789abcdefghijklmnopqrstuvwxyz".toCharArray()));
  }
}

Saída:

1
7
16
9
5
25
36
Kevin Cruijssen
fonte
2
Em vez de Math.max()você pode usarm = m>c?m:c
Robau
@ RobAu Ah, claro, obrigado. Esqueci completamente. Às vezes, esqueço as coisas mais fáceis de codegolfing em Java que são mencionadas várias vezes na publicação Dicas para codegolfing em Java . Obrigado pela lembrança.
Kevin Cruijssen 23/08/16
Se você alternar para o Java 8, poderá substituir toda essa função por um lambda que faça um únicoreduce
BlueRaja - Danny Pflughoeft
@ BlueRaja-DannyPflughoeft Eu sei, e é por isso que eu o mencionei especificamente como Java 7. Sinta-se à vontade para postar um lambda do Java 8 como uma resposta separada.
Kevin Cruijssen
@ BlueRaja-DannyPflughoeft I maravilha se isso iria acabar com menos bytes ..
Robau
1

C89, 55 53 52 50 bytes

f(s,b)char*s;{return*s?f(s+1,*s>b?*s:b):(b-8)%39;}

-8%39 roubado descaradamente de Dennis

Teste

test(const char* input)
{
    printf("%36s -> %u\n", input, f((char*)input,0));
}

main()
{
    test("00000");
    test("123456");
    test("ff");
    test("4815162342");
    test("42");
    test("codegolf");
    test("0123456789abcdefghijklmnopqrstuvwxyz");
}

Saída

                               00000 -> 1
                              123456 -> 7
                                  ff -> 16
                          4815162342 -> 9
                                  42 -> 5
                            codegolf -> 25
0123456789abcdefghijklmnopqrstuvwxyz -> 36

Economizou 2 bytes graças a Toby Speight

Guardado 2 bytes graças a Kevin Cruijssen

YSC
fonte
Você pode salvar 2 bytes com a declaração sem protótipo: f(char*s,int b)torna - se f(s,b)char*s;.
Toby Speight
Você pode salvar 3 bytes, removendo o parêntese desnecessários e espaço:f(s,b)char*s;{return*s?f(s+1,*s>b?*s:b):(b-8)%39;}
Kevin Cruijssen
@KevinCruijssen thx
YSC
1

C, 55 bytes

Esta resposta assume que a entrada está em ASCII (ou idêntica nos números e letras, por exemplo, ISO-8859 ou UTF-8):

m;f(char*s){for(m=0;*s;++s)m=m>*s?m:*s;return(m-8)%39;}

Nós simplesmente iteramos ao longo da string, lembrando o maior valor visto, depois usamos a conhecida conversão módulo 39 da base- {11..36}.

Programa de teste

int printf(char*,...);
int main(int c,char **v){while(*++v)printf("%s -> ",*v),printf("%d\n",f(*v));}

Resultado dos testes

00000 -> 1
123456 -> 7
ff -> 16
4815162342 -> 9
42 -> 5
codegolf -> 25
0123456789abcdefghijklmnopqrstuvwxyz -> 36
Toby Speight
fonte
Não foi possível remover m = 0? Se m aparecer no nível superior do arquivo, seu externo, o que implica estático, o que implica que ele será inicializado com zero.
Batman
@ Batman - sim, mas apenas se você não ligar f()mais de uma vez. Sei que quase tudo é justo no golfe, mas meus instintos profissionais consideram isso muito frágil!
Toby Speight
Pensando melhor, eu poderia torná-lo um requisito externo para redefinir m entre chamadas para f(). Então, meu programa de teste ainda pode funcionar.
Toby Speight
@Batman: on Code Golf Meta , a opinião da maioria sobre a questão " Os envios de funções precisam ser reutilizáveis? " Parece ser contra a permissão de funções de uso único. Então, eu vou ficar com o que tenho. Obrigado pela sugestão de qualquer maneira.
Toby Speight
1

Mathematica, 34 32 bytes

2 bytes economizados graças a Martin Ender

Max@Mod[ToCharacterCode@#-8,39]&

Decidi que o método diferente merecia uma nova resposta.

método roubado inspirado na solução de Dennis

DanTheMan
fonte
2
Use um pouco de notação de prefixo: Max@Mod[ToCharacterCode@#-8,39]&(o mesmo vale para a sua outra resposta)
Martin Ender
2
Além disso, você precisa adicionar &no final para indicar uma função anônima.
LegionMammal978
Você esqueceu uma @das duas respostas ( ToCharacterCode@#e Characters@#).
Martin Ender
1

Mathematica, 34 32 bytes

economizou 2 bytes graças a Martin Ender

Max@BaseForm[Characters@#,36]+1&

Define uma função pura que aceita uma string como entrada.

Divide a entrada em caracteres, converte-os em 36 números base e retorna o +1 máximo.

DanTheMan
fonte
Max@BaseForm[Characters@#,36]+1&
alephalpha
1

C # REPL, 17 bytes

x=>(x.Max()-8)%39

Acabei de portar a resposta de @ Dennis para C #.

stannius
fonte
1

CJam, 10 bytes

Obrigado a Martin Ender por me salvar alguns bytes!

Usa a fórmula de Dennis

q:e>8-i39%

Experimente online

CJam, 18 16 anos

Solução alternativa:

A,s'{,97>+q:e>#)

Experimente online

A,s'{,97>+       e# Push the string "0123456789abcdefghijklmnopqrstuvwxyz"
          q      e# Get the input
           :e>   e# Find the highest character in the input
              #  e# Find the index of that character in the string
               ) e# Increment
Gato de negócios
fonte
1

Scala, 25 bytes

print((args(0).max-8)%39)

Execute-o como:

$ scala whatbase.scala 0123456789abcdefghijklmnopqrstuvwxyz

AmazingDreams
fonte
1

R, 62 54 bytes

max(match(strsplit(scan(,''),"")[[1]],c(0:9,letters)))

Ungolfed:

max(
  match( # 2: Finds the respective positions of these characters
    strsplit(scan(,''),"")[[1]], # 1: Breaks the input into characters
                                c(0:9,letters)) # 3: In the vector "0123...yz"
                                                )

Atualização: eliminou 8 bytes devido à redundância de na.rm=Tsob a suposição de validade de entrada.

Uma melhoria de 39% no tamanho em comparação com a resposta de Frédéric . Além disso, ele roda um pouquinho mais rápido: 0,86 segundos para 100000 repetições versus 1,09 segundos para a resposta da concorrência. Então a minha é menor e mais eficiente.

Andreï Kostyrka
fonte
0

Dyalog APL , 10 bytes

Solicita entrada em maiúsculas.

⌈/⍞⍳⍨⎕D,⎕A

⌈/ máximo

caracteres de entrada

⍳⍨ Indexado em

⎕D, todos os dígitos seguidos por

⎕A todos os caracteres

TryAPL online!

Adão
fonte
0

BASH 70

grep -o .|sort -r|head -c1|od -An -tuC|sed s/$/-86/|bc|sed s/-/39-/|bc

As letras de entrada estão em minúsculas.

Riley
fonte
0

JavaScript, 57 50 48 bytes

7 bytes salvos thnks em @ kamaroso97 2 bytes salvos graças a @Neil

n=>Math.max(...[...n].map(a=>parseInt(a,36))+1)

Resposta original:

n=>n.split``.map(a=>parseInt(a,36)).sort((a,b)=>b-a)[0]+1
DanTheMan
fonte
Você pode bater 7 bytes com n=>Math.max(...n.split``.map(a=>parseInt(a,36)+1)).
Kamoroso94
@ kamoroso94 Eu não sabia que Math.maxexistia. Obrigado por me dizer sobre isso!
21416 DanTheMan
[...s]é mais curto que s.split``.
Neil
0

Perl, 30 27 bytes

Inclui +1 para -p

Corra com a entrada no STDIN, por exemplo

base.pl <<< codegolf

base.pl:

#!/usr/bin/perl -p
\@F[unpack"W*"];$_=@F%39-9
Ton Hospel
fonte
0

LiveScript, 32 bytes

->1+parseInt (it/'')sort!pop!,36

Uma porta desta resposta no meu idioma favorito que compila para JavaScript. Se o base~numberoperador trabalhava com variáveis, eu poderia escrever ->1+36~(it/'')sort!pop!(23 bytes), mas entra em conflito com o operador de ligação da função: /

Gustavo Rodrigues
fonte