这个数字是什么基数?


31

这是一个很好的简单挑战:

给定一个代表未知基数的字符串,请确定该数字可能位于的最低基数。该字符串仅包含0-9, a-z。如果您愿意,可以选择使用大写字母而不是小写字母,但是请指定。您必须以十进制输出这个最低的底数。

这是一个更具体的例子。如果输入字符串为“ 01234”,则该数字不可能为二进制,因为2、3和4都未定义为二进制。同样,此数字不能以3或4为底。因此,此数字必须以5或更高的底数为基础,因此应输出“ 5”。

您的代码必须适用于以1为底(一元,全为0)和以36为底(“ 0-9”和“ a-z”)的任何底。

您可以接受输入并以任何合理的格式提供输出。允许进行基本转换内置函数。像往常一样,存在标准漏洞,而最短的答案是以字节为单位!

测试IO:

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

8
我可以以36为底输出吗?
Leaky Nun

9
@LeakyNun Geez,我希望不会。
丹尼斯

4
@LeakyNunYou must output this lowest possible base in decimal.
DJMcMayhem

3
@RohanJhunjhunwala如果这是您最接近字符串的语言,我不知道为什么不这样做。
DJMcMayhem

3
通常,一元都是全1,而对于任何基于位置的数字系统,前导零都不是标准的。
停止Harming Monica

Answers:


16

果冻,4 字节

ṀØBi

需要大写。在线尝试!验证所有测试用例

怎么运行的

ṀØ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.

1
实际上是7个字节,而不是4个。前2个字符为多字节。
Nicomak

14
@Nicomak此答案在Jelly代码页中编码,所有这些字符每个都编码为1个字节。
罗夫霍

26

Python,27 22字节

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

这要求输入是字节串(Python 3)或字节数组(Python 2和3)。

感谢@AleksiTorhamo打高尔夫球5个字节!

Ideone上进行测试

怎么运行的

我们从获取字符串的最大值开始。这是字母的代码点高于数字的代码点,此最大字符也是最大的基数36位。

的代码点“0” - “9”48 - 57,所以我们必须减去48从它们的代码点来计算对应的数字,或47来计算最低的可能基。同样,字母的代码点“A” - “Z”97 - 122。由于“ a”代表数值为10的数字,我们必须从其代码点中减去87来计算相应的数字,或者减去86来计算可能的最低基数。实现此目的的一种方法如下。

之间的差值9758“:”后的文字,“9”)是39,因此服用代码点模39所能达到的减法。由于48%39 = 9,并为字符所需的结果“0”1,我们首先减去8取模的结果之前39。首先必须减去,因为否则'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

如果将其制成Python 3,并将输入作为字节字符串,则可以将ord()和删除3个字节。:)
Aleksi Torhamo

好主意!让我问一下OP。
丹尼斯

3
@AleksiTorhamo NOOOOOOOOOOOO贾宝玉呢DIS
Rɪᴋᴇʀ

20

Python,25个字节

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

定义一个接受字符串的lambda x。查找字符串中最大的数字(按python的默认设置,在数字上方用字母排序),然后转换为以36为底。加1,因为8不在8底。


11

Haskell,34个字节

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

使用mod(ord(c)-8,39)丹尼斯的想法。

41个字节

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

45个字节:

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

输出如Just 3


6

切达(Cheddar)34 29 21字节

由于丹尼斯节省了8个字节!!!

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

使用小写字母

在线尝试

说明

s -> (      // Input is `s`
  s.bytes    // Returns array of char codes
   .max      // Get maximum item in array
) % 39      // Modulus 39

1
或者,您也可以在输入中加上引号
DJMcMayhem

12
@DJMcMayhem .___。我什至不知道我自己的语言可以做到这一点
Downgoat

怎么样(-)&8,而不是n->n-8
科纳·奥布莱恩

@ ConorO'Brien> _> _> _>我还没明白。我只是打算这样做,然后发布了这个挑战。Bassically f&n债券n的函数的第一个参数。
Downgoat

@Downgoat哦。> _>
科纳·奥布莱恩

6

05AB1E,6个字节

{¤36ö>

大写字母。

说明

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

在线尝试


原谅我05AB1E的天真,但您的意思是从36基(转换为10基)转换吗?
Keeta

@Keeta您当然是正确的。我的错。
Emigna '16


5

Julia, 22 bytes

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

There's a BS character (0x08) between the quotes. Try it online!


what does the -'' do?
Downgoat

It subtracts 8 from the code point and returns an integer.
Dennis

4

JavaScript (ES6), 41 37 bytes

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

Edit: Saved 4 bytes thanks to @edc65.


use pop() to save 4
edc65

@edc65 I can't believe that's not under JavaScript tips.
Neil

3

Haskell, 55 40 bytes

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

Thanks @Dennis for his approach. (take that, @xnor ;))


I think you can remove f= for 38 bytes since f doesn't take explicit arguments.
Cyoce

3

Perl 6: 18 bytes

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

Defines a lambda that takes a single string argument, and returns an integer. It splits the string into characters, finds the "highest" one, converts it to base 36, adds 1.

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

This one uses the modulo approach from Dennis. Same length.


2

Retina, 28 bytes

O`.
.\B

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

Try it online! (The first line enables a linefeed-separated test suite.)

Explanation

O`.

This sorts the characters of the input.

.\B

This removes all characters except the last, so the first two stages find the maximum character.

{2`
$`
}T01`dl`_o

These are two stages which form a loop. The first one duplicates the first character and the second one "decrements" it (replacing e.g. x with w, a with 9 and 1 with 0). The latter stage encounters a zero as the first character, it removes it instead. This is a standard technique for generating a range of characters, given the upper end. Hence, this generates all "digits" from 0 to the maximum digit.

.

Finally, we simply count the number of digits, which gives us the base.


2

R, 99 89 85 bytes

Look ! Less than 100 bytes !
Look ! 10 bytes off !
Look ! 4 bytes off !

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.

As often, this answer makes use of the ifelse function : ifelse(Condition, WhatToDoIfTrue, WhatToDoElse)


I love your version; however, treating letters and numbers separately creates those pesky extra bytes. Please have a look at my solution that uses a different method.
Andreï Kostyrka

Your answer is interesting indeed. I will use the your scan method to golf some bytes ;)
Frédéric

1

PHP, 51 38 bytes

(From Dennis) ^^

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

Other proposal without Dennis' trick

<?=($a=max(str_split($argv[1])))<a?$a+1:ord($a)-86;
  • Takes input as argument $argv[1];
  • Take max character (using ASCII) values
  • If it is a number (inferior to < 'a' ascii value) then output number+1
  • Else output ascii value -86 (97 for 'a' in ascii, -11 for 'a' is 11th base-digit)

It's too bad PHP has such verbose function names: <?=base_convert(max(str_split($argv[1])),36,10)+1 is an elegant solution, but at 49 bytes!

@YiminRong you can use intval() instead of base_convert() which shortens down to 38 bytes <?=intval(max(str_split($argn)),36)+1; tio: tio.run/##K8go@P/…
640KB



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 is thanks to @Dennis' amazing answer.

Ungolfed & test code:

Try it here.

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()));
  }
}

Output:

1
7
16
9
5
25
36

2
Instead of Math.max() you can use m = m>c?m:c
RobAu

@RobAu Ah of course, thanks. Completely forgot about it.. Sometimes I forget the easiest codegolfing things in Java that are even mentioned multiple times in the Tips for Codegolfing in Java post. Thanks for the reminder.
Kevin Cruijssen

If you switch to Java 8 you can replace this whole function with a lambda that does a single reduce
BlueRaja - Danny Pflughoeft

@BlueRaja-DannyPflughoeft I know, which is why I specifically mentioned it as Java 7. Feel free to post a Java 8 lambda as a separate answer.
Kevin Cruijssen

@BlueRaja-DannyPflughoeft I wonder if that would end up with less 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 shamelessly stolen from Dennis

Test

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");
}

Output

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

Saved 2 bytes thanks to Toby Speight

Saved 2 bytes thanks to Kevin Cruijssen


You can save 2 bytes with the non-prototype declaration: f(char*s,int b) becomes f(s,b)char*s;.
Toby Speight

You can save 3 bytes by removing the unnecessary parenthesis and space: 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

This answer assumes that the input is in ASCII (or identical in the numbers and letters, e.g. ISO-8859 or UTF-8):

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

We simply iterate along the string, remembering the largest value seen, then use the well-known modulo-39 conversion from base-{11..36}.

Test program

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

Test results

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

Couldn't you remove the m=0? If m appears at the top level of the file, its extern which implies static which implies it is initialized to zero.
Batman

@Batman - yes, but only if you won't call f() more than once. I know that almost anything's fair game in golf, but my professional instincts regard that as too fragile!
Toby Speight

On further thought, I could make it an external requirement to reset m between calls to f(). Then my test program could still work.
Toby Speight

@Batman: on Code Golf Meta, the majority opinion on the question "Do function submissions have to be reusable?" seems to be against allowing single-use functions. So I'll stick with what I have. Thanks for the suggestion, anyway.
Toby Speight

1

Mathematica, 34 32 bytes

2 bytes saved thanks to Martin Ender

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

I decided the different method deserved a new answer.

method stolen inspired by Dennis' solution


2
Use some prefix notation: Max@Mod[ToCharacterCode@#-8,39]& (same goes for your other answer)
Martin Ender

2
Also, you need to add & to the end to indicate an anonymous function.
LegionMammal978

You forgot one @ in both of your answers (ToCharacterCode@# and Characters@#).
Martin Ender

1

Mathematica, 34 32 bytes

saved 2 bytes thanks to Martin Ender

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

Defines a pure function that takes a string as input.

Splits the input into characters, converts them to base 36 numbers, and returns the maximum +1.


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

1

C# REPL, 17 bytes

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

Just ported @Dennis's answer to C#.


1

CJam, 10 bytes

Thanks to Martin Ender for saving me a few bytes!

Uses Dennis's formula

q:e>8-i39%

Try it online

CJam, 18 16 btyes

Alternative solution:

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

Try it 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

1

Scala, 25 bytes

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

Run it like:

$ scala whatbase.scala 0123456789abcdefghijklmnopqrstuvwxyz


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"
                                                )

Update: shaved off 8 bytes due to the redundancy of na.rm=T under the assumption of input validity.

A 39% improvement in size compared to Frédéric's answer. Besides that, it runs a wee bit faster: 0.86 seconds for 100000 replications versus 1.09 seconds for the competing answer. So the one of mine is both smaller and more efficient.


0

Dyalog APL, 10 bytes

Prompts for uppercase input.

⌈/⍞⍳⍨⎕D,⎕A

⌈/ maximum

characters of input

⍳⍨ 1-indexed into

⎕D, all digits followed by

⎕A all characters

TryAPL online!


0

BASH 70

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

Input letters are lowercase.


0

JavaScript, 57 50 48 bytes

7 bytes saved thnks to @kamaroso97 2 bytes saved thanks to @Neil

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

Original answer:

n=>n.split``.map(a=>parseInt(a,36)).sort((a,b)=>b-a)[0]+1

You can knock off 7 bytes with n=>Math.max(...n.split``.map(a=>parseInt(a,36)+1)).
kamoroso94

@kamoroso94 I didn't realize Math.max existed. Thanks for telling me about it!
DanTheMan

[...s] is shorter than s.split``.
Neil

0

Perl, 30 27 bytes

Includes +1 for -p

Run with the input on STDIN, e.g.

base.pl <<< codegolf

base.pl:

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

0

LiveScript, 32 bytes

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

A port of this answer in my favorite language that compile to JavaScript. If base~number operator worked with variables I could write ->1+36~(it/'')sort!pop! (23 bytes), but it conflicts with the function bind operator :/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.