Find the sum of all possible base representations

20

0

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.

Arcturus

Posted 2015-12-04T16:21:48.770

Reputation: 6 537

5Are builtins for base conversion allowed? – lirtosiast – 2015-12-04T16:29:14.260

2Important test case: 0 – Martin Ender – 2015-12-04T17:12:09.267

Dang it, I was going to post a very similar challenge. – DanTheMan – 2015-12-04T17:49:25.433

@ThomasKwa Yes. – Arcturus – 2015-12-04T18:29:43.230

3@MartinBüttner Why is 0 an important test case? 0 is 0 in every base, and there's no such thing as base 1. – Arcturus – 2015-12-04T18:33:01.800

3@Eridan because some languages might try converting that from base 1 and fail. – Martin Ender – 2015-12-04T18:44:30.907

Isn't base 1 unary ? Like, 0, 00, 000... ? – Quentin – 2015-12-04T21:16:09.740

@Quentin Not according to the usual formulation of bases. 000 would be 01^2 + 01^1 + 0*1^0 = 0. – user253751 – 2015-12-04T21:51:45.287

The HELLOworld implies that the program must be able to output greater than 32-bit integers. Is this correct or can we just 32 bit outputs? If not, do we do just up to 64 bit integers, or do we need to arbitrary precision? – Digital Trauma – 2015-12-04T22:18:37.843

@immibis Mh. I'm used to the "number of different symbols" approach, with which a unary zero would be "" (nothing). But I'm probably confused. – Quentin – 2015-12-04T22:26:39.373

@Quentin By that (looser) definition, this program should also consider the number in modified-unary where 1, 2, 3, 4, ..., Z mean the same as 0. (Where the "decimal" number 184172 and the "binary" number 011001 are both six) – user253751 – 2015-12-04T22:32:44.050

@immibis Makes no sense indeed :) – Quentin – 2015-12-04T22:48:46.143

Answers

12

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)

Adnan

Posted 2015-12-04T16:21:48.770

Reputation: 41 965

@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) – Kevin W. – 2015-12-04T16:57:20.870

@FryAmTheEggman Thanks! I have adjusted it – Adnan – 2015-12-04T17:41:29.150

Just checked for you. The try except will let you do range(37). Two bytes! – Sherlock9 – 2015-12-04T17:47:04.900

@Sherlock9 It won't work for purely numeric inputs, these will be interpreted as base 10 numbers. – Adnan – 2015-12-04T17:50:19.133

Oh right, darn. @Adnan – Sherlock9 – 2015-12-04T17:54:43.817

By my count, if you switch to x=N=0 and while N<36: N+=1, you save two bytes against the range. – DSM – 2015-12-05T03:31:03.263

@DSM That is quite clever! – Adnan – 2015-12-05T10:44:00.083

10

Pyth, 20 19 11 bytes

sm.xizd0S36

Blatantly stole Adnan's idea from his Python answer.

Try it here

orlp

Posted 2015-12-04T16:21:48.770

Reputation: 37 067

@orlp You can remove the S char – Blue – 2015-12-04T20:20:58.763

Nope. Test 1012. – orlp – 2015-12-04T23:39:19.017

4

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
$ 

Digital Trauma

Posted 2015-12-04T16:21:48.770

Reputation: 64 644

3

Mathematica, 57 bytes

#~Sum~{x,Max@CoefficientList[#,x]+1,36}&@FromDigits[#,x]&

alephalpha

Posted 2015-12-04T16:21:48.770

Reputation: 23 988

You can use infix form for the FromDigits. – LegionMammal978 – 2015-12-05T00:15:01.990

3

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

Mego

Posted 2015-12-04T16:21:48.770

Reputation: 32 998

Perhaps Seriously should have a command that produces the alphabet and/or the numbers 0-9? – Arcturus – 2015-12-05T02:16:45.243

@Eridan It seriously should - getting that index costs half the bytes. – Mego – 2015-12-05T07:48:22.257

2

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

Luis Mendo

Posted 2015-12-04T16:21:48.770

Reputation: 87 464

2

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.

beaker

Posted 2015-12-04T16:21:48.770

Reputation: 2 349

Very clever use of polyval to vectorize! – Luis Mendo – 2015-12-04T22:50:31.397

1

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

Adnan

Posted 2015-12-04T16:21:48.770

Reputation: 41 965

1

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

ETHproductions

Posted 2015-12-04T16:21:48.770

Reputation: 47 880

1

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.

Martin Ender

Posted 2015-12-04T16:21:48.770

Reputation: 184 808

q{'0-_9>7*-}% is just as short. – Peter Taylor – 2015-12-04T18:17:13.523

@PeterTaylor Oh, right... – Martin Ender – 2015-12-04T19:49:29.593

1

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
$ 

Digital Trauma

Posted 2015-12-04T16:21:48.770

Reputation: 64 644

In C can you remove the space in #include <stdlib.h> like you can in C++? – Alex A. – 2015-12-04T19:17:01.680

@AlexA. Yes - I didn't know that - thanks! – Digital Trauma – 2015-12-04T22:10:05.657

0

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.

Sherlock9

Posted 2015-12-04T16:21:48.770

Reputation: 11 664

0

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=>}

J Atkin

Posted 2015-12-04T16:21:48.770

Reputation: 4 846

0

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... ].

nimi

Posted 2015-12-04T16:21:48.770

Reputation: 34 639

0

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>

user81655

Posted 2015-12-04T16:21:48.770

Reputation: 10 181

&&b=v saves 1 byte over ?b=v:0. – Neil – 2015-12-06T19:15:53.040

@Neil Did you test it? I'm pretty sure that would be an invalid left-hand of assignment. – user81655 – 2015-12-06T21:58:10.180

Sorry I confused it with a similar case in another golf. – Neil – 2015-12-07T10:42:10.070

0

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

Paŭlo Ebermann

Posted 2015-12-04T16:21:48.770

Reputation: 1 010

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? – Neil – 2015-12-06T19:12:34.440

0

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

Brad Gilbert b2gills

Posted 2015-12-04T16:21:48.770

Reputation: 12 713