20
\$\begingroup\$

The objective of this challenge is to write a program to convert an inputed string of what can be assumed as containing only letters and numbers from as many bases between 2 and 36 as possible, and find the base 10 sum of the results.

The input string will be converted to all the bases in which the number would be defined according to the standard alphabet for bases up to 36: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ. For example, the input 2T would be valid in only bases 30 and up. The program would convert 2T from bases 30 through 36 to decimal and sum the results.

You may assume that the input string contains only letters and numbers. Your program may use uppercase or lowercase; it can, but does not need to, support both.


Test cases

Sample input: 2T

Chart of possible bases

Base   Value
30     89
31     91
32     93
33     95
34     97
35     99
36     101

Output: 665

Sample input: 1012

Chart of possible bases:

Base   Value
3      32
4      70
5      132
6      224
7      352
8      522
9      740
10     1012
11     1344
12     1742
13     2212
14     2760
15     3392
16     4114
17     4932
18     5852
19     6880
20     8022
21     9284
22     10672
23     12192
24     13850
25     15652
26     17604
27     19712
28     21982
29     24420
30     27032
31     29824
32     32802
33     35972
34     39340
35     42912
36     46694

Output: 444278

Sample input: HELLOworld

Chart of possible bases

Base   Value
33     809608041709942
34     1058326557132355
35     1372783151310948
36     1767707668033969

Output: 5008425418187214

An input of 0 would be read as 0 in all bases between 2 and 36 inclusive. There is no such thing as base 1.


This is code golf. Standard rules apply. Shortest code in bytes wins.

\$\endgroup\$
  • 5
    \$\begingroup\$ Are builtins for base conversion allowed? \$\endgroup\$ – lirtosiast Dec 4 '15 at 16:29
  • 2
    \$\begingroup\$ Important test case: 0 \$\endgroup\$ – Martin Ender Dec 4 '15 at 17:12
  • \$\begingroup\$ Dang it, I was going to post a very similar challenge. \$\endgroup\$ – DanTheMan Dec 4 '15 at 17:49
  • 3
    \$\begingroup\$ @MartinBüttner Why is 0 an important test case? 0 is 0 in every base, and there's no such thing as base 1. \$\endgroup\$ – Arcturus Dec 4 '15 at 18:33
  • 3
    \$\begingroup\$ @Eridan because some languages might try converting that from base 1 and fail. \$\endgroup\$ – Martin Ender Dec 4 '15 at 18:44

17 Answers 17

12
\$\begingroup\$

Python 3, 72 71 69 bytes

Thanks to FryAmTheEggman for saving a byte!

Thanks to DSM for saving 2 bytes!

N=x=0
y=input()
while N<36:
 N+=1
 try:x+=int(y,N)
 except:0
print(x)
\$\endgroup\$
  • \$\begingroup\$ @ThomasKwa that will add a zero, which will not work for purely numeric inputs as that functions as checking if it's base 10 (which will make some results too large) \$\endgroup\$ – Kevin W. Dec 4 '15 at 16:57
  • \$\begingroup\$ @FryAmTheEggman Thanks! I have adjusted it \$\endgroup\$ – Adnan Dec 4 '15 at 17:41
  • \$\begingroup\$ Just checked for you. The try except will let you do range(37). Two bytes! \$\endgroup\$ – Sherlock9 Dec 4 '15 at 17:47
  • \$\begingroup\$ @Sherlock9 It won't work for purely numeric inputs, these will be interpreted as base 10 numbers. \$\endgroup\$ – Adnan Dec 4 '15 at 17:50
  • \$\begingroup\$ Oh right, darn. @Adnan \$\endgroup\$ – Sherlock9 Dec 4 '15 at 17:54
10
\$\begingroup\$

Pyth, 20 19 11 bytes

sm.xizd0S36

Blatantly stole Adnan's idea from his Python answer.

Try it here

\$\endgroup\$
  • \$\begingroup\$ @orlp You can remove the S char \$\endgroup\$ – Blue Dec 4 '15 at 20:20
  • \$\begingroup\$ Nope. Test 1012. \$\endgroup\$ – orlp Dec 4 '15 at 23:39
4
\$\begingroup\$

Pure Bash (no utilities), 38

Assuming built-in base conversions are allowed:

for((b=36;s+=$b#$1;b--));{ :;}
echo $s

This will output an error to STDERR. I'm assuming this is OK as per this meta answer.

Test output:

$ for t in 0 2T 1012 HELLOworld; do ./basesum.sh $t; done 2> /dev/null
0
665
444278
5008425418187214
$ 
\$\endgroup\$
3
\$\begingroup\$

Mathematica, 57 bytes

#~Sum~{x,Max@CoefficientList[#,x]+1,36}&@FromDigits[#,x]&
\$\endgroup\$
  • \$\begingroup\$ You can use infix form for the FromDigits. \$\endgroup\$ – LegionMammal978 Dec 5 '15 at 0:15
3
\$\begingroup\$

Seriously, 65 bytes

,û;╗rk`"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"íu`MSd:37:@x`╜¿`MΣ.

Contains unprintables, hexdump:

2c963bbb726b6022303132333435363738394142434445464748494a4b4c4d4e4f505152535455565758595a22a175604d53643a33373a407860bda8604de42e7f

Unfortunately I don't have a good way to filter from a list based on types. Note to self: add that.

Takes input like "2T"

Try it online (you will have to manually enter input)

Explanation:

,û    get input and convert to uppercase
;╗    make a copy and save to register 0
rk    explode string into list
`"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"íu`M  map the function over the list:
    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"íu    get the character's index in the string and add one to get a value in [1,36]
Sd    get maximum element (maximum base aka max_base) from list by sorting and popping the last element off and pushing it to the stack
:37:@x  push range(max_base,37)
`╜¿`M  map the function over the list:
    ╜¿    convert value in register 0 to an int, interpreting it as a base-n int (n is value from list)
Σ.    sum and print
0x7f  quit
\$\endgroup\$
  • \$\begingroup\$ Perhaps Seriously should have a command that produces the alphabet and/or the numbers 0-9? \$\endgroup\$ – Arcturus Dec 5 '15 at 2:16
  • \$\begingroup\$ @Eridan It seriously should - getting that index costs half the bytes. \$\endgroup\$ – Mego Dec 5 '15 at 7:48
2
\$\begingroup\$

Matlab, 98 bytes

function y=f(s)
[~,m]=max(bsxfun(@eq,s,[48:57 65:90]'));y=0;for n=max(m):36
y=y+base2dec(s,n);
end
\$\endgroup\$
2
\$\begingroup\$

Octave, 75 73 bytes

function v=u(a) m([48:57 65:90])=0:35;v=sum(polyval(t=m(a),max(t)+1:36));

Explanation:

function v=u(a) 
   m([48:57 65:90])=0:35; %// create a map: '0'-'9' = 0-9
                          %//               'A'-'Z' = 10-35
   t=m(a);                %// convert string to mapped values
   b=max(t)+1;            %// find minimum base
   p=polyval(t,b:36);     %// calculate polynomial for each base (vectorized)
   v=sum(p);              %// and return the sum of the resulting vector

polyval has an advantage over base2dec in that it's vectorized, so no for loop is required.

Only '0'..'9' and upper-case 'A'..'Z' are supported as input.

\$\endgroup\$
  • \$\begingroup\$ Very clever use of polyval to vectorize! \$\endgroup\$ – Luis Mendo Dec 4 '15 at 22:50
1
\$\begingroup\$

Japt, 26 bytes

1+U¬r@XwYn36}0)o37 £UnX} x

Try it online!

Ungolfed and explanation

1+U¬ r@   XwYn36}0)o37 £    UnX} x
1+Uq rXYZ{XwYn36}0)o37 mXYZ{UnX} x

           // Implicit: U = input string
Uq rXYZ{   // Split U into chars, and reduce each item Y and previous value X by:
XwYn36     //  Choosing the larger of X and parseInt(Y,36),
}0         // starting at 0.
1+   )o37  // Add 1 and create a range from this number to 36.
mXYZ{UnX}  // Map each item X in this range to parseInt(U,X)
x          // and sum.
           // Implicit: output last expression
\$\endgroup\$
1
\$\begingroup\$

Pyth, 16 bytes

V36 .x=+ZizhN ;Z

Try it online

Explaination:

                 # Implicit: Z = 0, z = input
V36              # For N in range 36
    .x           # Try except
      =+Z        # Z = Z + izhN
         izhN    # Convert z from base N+1 to decimal
              ;  # Infinite ), for closing the for loop
               Z # Print Z
\$\endgroup\$
1
\$\begingroup\$

CJam, 28 27 bytes

Thanks to Reto Koradi for saving 1 byte.

This is kinda horrible...

qA,s'[,65>+f#_:e>)37,>\fb:+

Requires upper case letters.

Test it here.

CJam doesn't have built-in base-36 conversion from strings, so we have to letters out the strings ourselves. I've been trying all sorts of divmod shenanigans, but it seems to be shortest to build a string of all 36 digits and just find the index of each character in that string.

\$\endgroup\$
  • \$\begingroup\$ q{'0-_9>7*-}% is just as short. \$\endgroup\$ – Peter Taylor Dec 4 '15 at 18:17
  • \$\begingroup\$ @PeterTaylor Oh, right... \$\endgroup\$ – Martin Ender Dec 4 '15 at 19:49
1
\$\begingroup\$

C function, 93 (32 bit integer output only)

Assuming its OK for the output to only go up to INT_MAX, then we can do this:

i,n,x;f(char *s){char *e;for(i=36,x=0;n=strtol(s,&e,i--),!*e&&i;)x+=*e?0:n;printf("%d\n",x);}

The last testcase implies that this is probably not sufficient. If so, then with 64-bit integers we have:

C function, 122

#include<stdlib.h>
f(char *s){long long i=36,n,x=0;char *e;for(;n=strtoll(s,&e,i--),!*e&&i;)x+=*e?0:n;printf("%lld\n",x);}

Unfortunately the #include <stdlib.h> is required so the return type of strtoll() is correct. We need to use long long to handle the HELLOworld testcase. Otherwise this could be a fair bit shorter.

Test driver:

#include<stdlib.h>
f(char *s){long long i=36,n,x=0;char *e;for(;n=strtoll(s,&e,i--),!*e&&i;)x+=*e?0:n;printf("%lld\n",x);}

int main (int argc, char **argv)
{
    f("0");
    f("2T");
    f("1012");
    f("HELLOworld");
}

Test output:

$ ./basesum
0
665
444278
5008425418187214
$ 
\$\endgroup\$
  • \$\begingroup\$ In C can you remove the space in #include <stdlib.h> like you can in C++? \$\endgroup\$ – Alex A. Dec 4 '15 at 19:17
  • \$\begingroup\$ @AlexA. Yes - I didn't know that - thanks! \$\endgroup\$ – Digital Trauma Dec 4 '15 at 22:10
0
\$\begingroup\$

Python 3, 142 bytes

Adnan has me soundly beat with their solution, but I did want to add my own attempt.

def f(s):
 t=0
 for x in range(37):
  n=0
  for i in s:
   try:m=int(i)
   except:m=ord(i)-55
   if x<=m:n=0;break
   n=n*x+m
  t+=n
 return t

This function only handles uppercase inputs. Add .upper() to for i in s, and it will handle both uppercase and lowercase.

\$\endgroup\$
0
\$\begingroup\$

Scala 2.11, 93 bytes

This is run on the scala console.

val i=readLine
var s=0
for(j<-2 to 36)try{s=s+Integer.parseInt(i,j)}catch{case _:Exception=>}
\$\endgroup\$
0
\$\begingroup\$

Haskell, 97 bytes

i c|'_'<c=fromEnum c-87|1<2=read[c]
f s=sum$map((`foldl1`map i s).((+).).(*))[1+i(maximum s)..36]

Supports only lowercase characters. Usage example:

f "2t"           -> 665
f "helloworld"   -> 5008425418187214

It's so massive, because I have to implement both char-to-ASCII and base conversion myself. The corresponding pre-defined functions are in modules which require even more expensive imports.

How it works: i converts a character c to it's digit value (e.g. i 't' -> 29). f calculates the value of the input string for every possible base and sums it. A non-pointfree version of the inner loop is map (\base -> foldl1 (\value digit -> value*base + digit) (map i s)) [ ...bases... ].

\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 86 bytes

s=>eval(`p=parseInt;b=2;[...s].map(d=>(v=p(d,36))>b?b=v:0);for(r=0;++b<37;)r+=p(s,b)`)

Explanation

s=>
  eval(`                     // use eval to enable for loop without return keyword or {}
    p=parseInt;
    b=2;                     // b = minimum base of s
    [...s].map(d=>           // iterate through each digit d
      (v=p(d,36))            // get it's base-36 value
        >b?b=v:0             // set b to the max value
    );
    for(r=0;++b<37;)         // r = sum of all base values
      r+=p(s,b)              // add each base value from b to 36 to r
  `)                         // implicit: return r

Test

<input type="text" id="input" value="HELLOworld" />
<button onclick="result.textContent=(

s=>eval(`p=parseInt;b=2;[...s].map(d=>(v=p(d,36))>b?b=v:0);for(r=0;++b<37;)r+=p(s,b)`)

)(input.value)">Go</button>
<pre id="result"></pre>

\$\endgroup\$
  • \$\begingroup\$ &&b=v saves 1 byte over ?b=v:0. \$\endgroup\$ – Neil Dec 6 '15 at 19:15
  • \$\begingroup\$ @Neil Did you test it? I'm pretty sure that would be an invalid left-hand of assignment. \$\endgroup\$ – user81655 Dec 6 '15 at 21:58
  • \$\begingroup\$ Sorry I confused it with a similar case in another golf. \$\endgroup\$ – Neil Dec 7 '15 at 10:42
0
\$\begingroup\$

Perl 6, 35 bytes

{[+] map {+(":$^a"~"<$_>")||0},^37}

usage:

# store it somewhere
my &code = {[+] map {+(":$^a"~"<$_>")||0},^37}

say code 'HELLOworld' # 5008425418187214

say map &code, <2T 1012>
# (665 444278)

say code 'qwertyuiopasdfghjklzxcvbnm1234567890'
# 79495849566202185148466281109757186006261081372450955140
\$\endgroup\$
0
\$\begingroup\$

Ceylon, 100 96 bytes

Integer b(String s)=>sum(((any(s*.letter)then 11else 2)..36).map((r)=>parseInteger(s,r)else 0));

I first had this simpler version taking just 69 bytes:

Integer b(String s)=>sum((2..36).map((r)=>parseInteger(s,r)else 0));

But this fails with the first test case, returning 2000000000665 instead of 665. (The reason is that the T in 2T is parsed as Tera, i.e. multiplies the 2 with 10^12, when the radix is 10.) Therefore we need to catch this case separately. Thanks to Neil for suggesting a different way of doing this which saved 4 bytes.

Formatted:

// Find sum of all possible base representations.
//
// Question:  https://codegolf.stackexchange.com/q/65748/2338
// My Answer: https://codegolf.stackexchange.com/a/65836/2338

Integer b(String s) =>
// take the sum of ...
        sum(
    // span from 2 to 36. (Though
    // if there are letters in there, we start at 11,
    // because the other ones can't be valid.
    // Also, parseInteger(s, 10) behaves a bit strange in Ceylon.)
    ((any(s*.letter) then 11 else 2) .. 36)
    // map each r of them to ...
        .map((r) =>
            // try parsing s as a number using base r
            parseInteger(s, r)
            // if that didn't succeed, use 0.
                    else 0
    )
);
\$\endgroup\$
  • \$\begingroup\$ Can you perhaps shorten the code by starting from base 11 if the string contains a letter, thus avoiding having to special-case base 10? \$\endgroup\$ – Neil Dec 6 '15 at 19:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.