Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Input:
A list/array of integers for which each item is in the range of 2-36.

Output:
The sum of the integers (as base 10), where each next integer is in the base of the previous value (starting with a regular base 10).

Example:
Let's say we have an input like this: [4, 12, 34, 20, 14, 6, 25, 13, 33]
Then we have a sum like this:

4    (4  in base-10) +
6    (12 in base-4 ) +
40   (34 in base-12) +
68   (20 in base-34) +
24   (14 in base-20) +
6    (6  in base-14) +
17   (25 in base-6 ) +
28   (13 in base-26) +
42   (33 in base-13)
= 235

Mathematical base explained:
I considered assuming everyone knows how base works, but I'll give a brief example of how it works anyway, just in case. Let's take the 34 in base-12 for example, how did we get 40?

1-34 in regular base-10:
 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34
 So, from 1 to 34 is 34 steps in base-10

1-34 in base-12:
 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 2A, 2B, 30, 31, 32, 33, 34
 So, from 1 to 34 is 40 steps in base-12

Here is perhaps a useful calculator.

Challenge rules:

  • Array size will be in reasonable range (like 1-100 / see test cases).
  • The test cases will never contain integers of which the current value is invalid for it's previous base (i.e. You will never have something like 19 in base-6 or 6 in base-6, because base-6 only contains the digits 0-5).
  • You can take the input any way you'd like. Can be as an int-array, as a comma/space-separated string, etc. Your call. (You are also allowed to take the int-array reversed, which could be useful for stack-based programming languages.)

General Rules:

  • This is , so shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-golfing languages. Try to come up with as short an answer as possible for any programming language.
  • Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code.
  • Also, please add an explanation if necessary.

Test cases:

[4, 12, 34, 20, 14, 6, 25, 13, 33]                            ->   235
 4+ 6+  40+ 68+ 24+ 6+ 17+ 28+ 42

[5, 14, 2, 11, 30, 18]                                        ->   90
 5+ 9+  2+ 3+  33+ 38

[12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 12, 2, 11, 3, 10, 2, 10]    ->   98
 12+ 13+ 11+ 9+ 8+ 7+ 6+ 5+ 4+ 3+ 5+  2+ 3+  3+ 3+  2+ 2

[36, 36]                                                      ->   150
 36+ 114
share|improve this question
    
Yes, this has been in de Sandbox for plusminus 80 hours. – Kevin Cruijssen yesterday
1  
For stack based languages which have a LIFO container, can the input be given in reversed order? In dc I would require ~30 bytes just to flip the stack to have the first number in the input be the first one to be processed, which non-stack based languages have by default. – seshoumara yesterday
    
@seshoumara Why not. I'll clarify this in the challenge. It's mainly about the challenge and output, and not really about the input-format. – Kevin Cruijssen yesterday

20 Answers 20

Python 3, 40 bytes

lambda a:sum(map(int,map(str,a),[10]+a))

Tests are at ideone

map(str, a) creates a generator, G, that calls str on each value in a, converting to strings
map(int, G, [10]+a) creates a generator that calls int(g, v) for pairs across G and [10]+a
int(g, v) converts the string g from the integer base v (if v is in [2,36] and g is valid)
sum does what it says on the tin

share|improve this answer

Python 2, 48 bytes

lambda a:sum(int(`x`,y)for x,y in zip(a,[10]+a))

Tests are at ideone

zip(a,[10]+a) traverses pairs of the values in a, and the previous value or 10 for the first
the backticks in the int call convert x to a string, s
int(s, y) converts the string s from the integer base y (if y is in [2,36] and s is valid)
sum does what it says on the tin

share|improve this answer

PHP, 53 51 bytes

for(;$x=$argv[++$i];$b=$x)$s+=intval($x,$b);echo$s;

Iterates over the input, converting each input to string variant. Then takes the integer value using the previous number as base. For the first number, the base will not be set, PHP will then start off with 10 (inferred from the number format).

Run like this (-d added for aesthetics only):

php -d error_reporting=30709 -r 'for(;$x=$argv[++$i];$b=$x)$s+=intval($x,$b);echo$s;' -- 12 11 10 9 8 7 6 5 4 3 12 2 11 3 10 2 10;echo

Tweaks

  • Actually, no need to convert to string, as CLI arguments are already string. Saved 2 bytes.
share|improve this answer

Perl, 35 34 33 bytes

Includes +2 for -ap

Run with the list of numbers on STDIN:

basemix.pl <<< "4 12 34 20 14 6 25 13 33";echo

basemix.pl:

#!/usr/bin/perl -ap
$\+=$&+"$`$& 10"*/.$/*$`for@F}{

I've been waiting for ages for a chance to use this abuse...

Explanation

The input numbers can have at most 2 digits. A number xy in base b is simply b*x+y. I'm going to use the regex /.$/ so the first digit ends up in $` and the last digit in $&, so the contribution to the sum is $&+$b*$`.

I abuse the fact that for does not properly localize the regex variables (like for example map and while do) so the results of a match in the previous loop is still available in the current loop. So if I'm careful about the order in which I do the operations the base is available as "$`$&", except for the very first loop where I need the base to be 10. So I use "$`$& 10" instead

The way the first $& works is an abuse too since it is actually changed by the /.$/ while it is already on the stack waiting to be added.

The final abuse is the }{ at the end which changes the loop implied by -p from

LINE: while (defined($_ = <ARGV>)) {
    ...code..
}
continue {
    die "-p destination: $!\n" unless print $_;
}

to

LINE: while (defined($_ = <ARGV>)) {
    ...code..
}
{
}
continue {
    die "-p destination: $!\n" unless print $_;
}

Which means $_ will be undefined in the print, but it still adds $\ in which I accumulated the sum. It is also a standard golf trick to get post-loop processing

share|improve this answer
    
I'd be really interested in an explanation for those of us with weaker perl-fu! – m-chrzan yesterday
1  
@m-chrzan Solution fixed and explanation added – Ton Hospel yesterday

Jelly, 7 bytes

ṙ1DḅṖḌS

Try it online!

share|improve this answer
3  
You could replace ṖḌ with F – Jonathan Allan yesterday
2  
Unfortunately, that won't work in the first number has two digits. – Dennis yesterday

05AB1E, 7 6 bytes

Uses CP-1252 encoding.

T¸ìüöO

Explanation

Input list is taken reversed, as allowed by challenge specification.

T¸ì     # append a 10 to the list
   üö   # reduce by conversion to base-10
     O  # sum

Try it online!

Modified testsuite

share|improve this answer

Java 7, 109 89 bytes

int c(int[]a){for(Integer i=1;i<a.length;a[0]+=i.valueOf(a[i]+"",a[++i-2]));return a[0];}

Golfed 20 bytes thanks to @cliffroot (of which 12 because of a stupid mistake I made myself).

Ungolfed & test code:

Try it here.

class M{
  static int c(int[] a){
     for(Integer i = 1; i < a.length; a[0] += i.valueOf(a[i]+"", a[++i-2]));
     return a[0];
  }

  public static void main(String[] a){
    System.out.println(c(new int[]{ 4, 12, 34, 20, 14, 6, 25, 13, 33 }));
    System.out.println(c(new int[]{ 5, 14, 2, 11, 30, 18 }));
    System.out.println(c(new int[]{ 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 12, 2, 11, 3, 10, 2, 10 }));
    System.out.println(c(new int[]{ 36, 36 }));
  }
}

Output:

235
90
98
150
share|improve this answer
    
Do you really need p? The sum can be computed like this, can't it: r+=r.valueOf(""+a[i],a[i-1])? – Olivier Grégoire yesterday
1  
used conversion +"" instead of valueOf and removed unnecessary variables – int c(int[]a){for(Integer i=1;i<a.length;a[0]+=i.valueOf(a[i]+"",a[++i-2]));return a[0];} – cliffroot yesterday
    
@cliffroot Ah, I'm an idiot.. When I was testing I made a mistake and had the 10 and p reversed. I realized the mistake and fixed it, but since the String part is now regular base-10 I can indeed remove the toString and just use +"".. Thanks, and also thanks for golfing the other things, -20 bytes. I really gotta make an answer you can't golf more (not that I don't appreciate it! the shorter the better of course - in code-golfing that is ;P) – Kevin Cruijssen yesterday
    
Just to compare with my answer, yours in current Java's syntax is 79 bytes long (mine is presently 86 bytes long). But that's not fun taking others' code ;) – Olivier Grégoire yesterday
1  
@KevinCruijssen , I'm more than fine with it :) I just feel that realistically Java does not compete with all that 5-6 bytes solution, so I don't add my own answers often, but I still find it fun to golf down others' solution. – cliffroot yesterday

Java, 86 bytes

s->{int[]b={10};return s.reduce(0,(r,n)->{r+=n.valueOf(""+n,b[0]);b[0]=n;return r;});}

Testing and ungolfed

import java.util.function.ToIntFunction;
import java.util.stream.Stream;

public class Main {

  public static void main(String[] args) {
    ToIntFunction<Stream<Integer>> f = s -> {
      int[] b = {10};                 // Base, initialized with 10
      return s.reduce(0, (r, n) -> {  // Typical use of reduction, sum starts with 0.
        r += n.valueOf("" + n, b[0]); // Add the value in the previous base.
        b[0] = n;                     // Assign the new base;
        return r;
      });
    };

    System.out.println(f.applyAsInt(Stream.of(new Integer[]{4, 12, 34, 20, 14, 6, 25, 13, 33})));
  }
}
share|improve this answer

JavaScript ES6, 45 42 41 Bytes

const g =
     a=>a.map(v=>s+=parseInt(v,p,p=v),s=p=0)|s
;

console.log(g.toString().length);                                            // 42
console.log(g([4, 12, 34, 20, 14, 6, 25, 13, 33]));                          // 235
console.log(g([5, 14, 2, 11, 30, 18]  ));                                    // 90
console.log(g([12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 12, 2, 11, 3, 10, 2, 10] )); // 98

Conventiently parseInt(x,0) === parseInt(x,10).

edit: Saved 1 byte thanks to @ETHproductions

share|improve this answer
    
Nice! I think you can save a byte by replacing &&s with |s. – ETHproductions yesterday
    
Thanks, @ETHproductions. Thats a neat trick. – Lmis yesterday
    
You can also replace const g with just g – Clyde Lobo 21 hours ago

Pure bash, 38

b=10
for i;{((t+=$b#$i,b=i));}
echo $t

The input list is given at the command-line. for i; automatically iterates over the input parameters (equivalent to for i in $@;).

Ideone.

share|improve this answer

Actually, 12 bytes

;p(dX(♂$♀¿Σ+

Try it online!

Explanation:

;p(dX(♂$♀¿Σ+
;             dupe input
 p            pop first element from list
  (dX         pop and discard last element from other copy
     (♂$      stringify all elements in first copy
        ♀¿    for each pair of elements in the two lists, interpret the first element as a base-(second element) integer
          Σ   sum
           +  add first element of original list
share|improve this answer

CJam, 15 bytes

l~{A\:A10bb}%:+

Try it online!

Explanation

l~     e# Read and evaluate input.
{      e# Map this block over the input...
  A    e#   Push A. Initially this is 10, afterwards it will be the value of the
       e#   last iteration.
  \:A  e#   Swap with current value and store that in A for the next iteration.
  10b  e#   Convert to base 10 to get its decimal digits.
  b    e#   Interpret those in the base of the previous A.
}%
:+     e# Sum all of those values.
share|improve this answer

JavaScript (ES6), 54 48 bytes

I used a recursive approach.

f=(a,b)=>a[0]?parseInt(a,b)+f(a.slice(1),a[0]):0

Saved 6 bytes, thanks to Lmis!

share|improve this answer
1  
I think you can save 3 bytes by using parseInt(a,b) instead of parseInt(a[0],b) since parseInt converts the first argument to string and ignores everything starting at the first invalid character (i.e. ','). – Lmis yesterday
1  
I also think you can save some bytes by using a[0]?stuff():0 instead of a.length&&stuff() – Lmis yesterday
    
@Lmis Thanks, I've updated it :) – Huntro yesterday
    
I think you can shorten this to 40 bytes: f=([b,...a],c)=>b?parseInt(b,c)+f(a,b):0 – Neil 11 hours ago

Haskell, 65 59 bytes

b%x|x<1=x|y<-div x 10=b*b%y+x-10*y
sum.((10:)>>=zipWith(%))

Test it on Ideone.

share|improve this answer

Matlab, 68 bytes

Not a very creative solution, but here it is:

function[s]=r(x);j=10;s=0;for(i=x)s=s+base2dec(num2str(i),j);j=i;end

Tests:

>> r([4,12,34,20,14,6,25,13,33])
ans =
   235
>> r([12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 12, 2, 11, 3, 10, 2, 10])
ans =
   98
>> r([5, 14, 2, 11, 30, 18])
ans =
   90
>> r([36,36])
ans =
   150
share|improve this answer
    
You can save one byte with function s=r(x);... – Luis Mendo 14 hours ago

Python 2, 52 bytes

f=lambda x:x[1:]and int(`x.pop()`,x[-1])+f(x)or x[0]

Test it on Ideone.

share|improve this answer

Julia, 63 Bytes

f(l)=sum([parse(Int,string(l[i]),l[i-1])for i=2:length(l)])+l[]

Parses each number (except the first) taking the previous element as base and sums. Adds the first element at the end

share|improve this answer

Ruby, 52 bytes

->a{eval a.zip([10]+a).map{|e|'"%s".to_i(%s)'%e}*?+}

ungolfed

->a{
  eval(
    a.zip([10]+a).map { |e|
      '"%s".to_i(%s)' % e
    }.join("+")
  )
}

usage

f=->a{eval a.zip([10]+a).map{|e|'"%s".to_i(%s)'%e}*?+}
p f[[4, 12, 34, 20, 14, 6, 25, 13, 33]] # => 235
share|improve this answer

Scala, 67 bytes

def f(a:Int*)=a zip(10+:a)map{t=>Integer.parseInt(""+t._1,t._2)}sum

Explanation:

def f(a: Int*) =     //declare a method f with varargs of type Int as parameter
a zip (10 +: a)      //zip a with 10 prepended to a, resulting in...
                     //...Array((4,10), (12,4), (34,12), (20,34), (14,20), (6,14), (25,6), (13,25), (33,13))
map { t =>           //map each tuple t to...
  Integer.parseInt(  //...an integer by parsing...
    ""+t._1, t._2    //...a string of the first item in base-second-item.
  )
}
sum                  //and sum
share|improve this answer

Mathematica, 59 bytes

I wish Mathematica's function names were shorter. But otherwise I'm happy.

Tr[FromDigits@@@Transpose@{IntegerDigits/@{##,0},{10,##}}]&

For example,

Tr[FromDigits@@@Transpose@{IntegerDigits/@{##,0},{10,##}}]&[4,12,34,20,14,6,25,13,33]

yields 235.

{##,0} is a list of the input arguments with 0 appended (representing the numerals); {10,##} is a list of the input arguments with 10 prepended (representing the bases). That pair of lists is Transposed to associate each with numeral with its base, and FromDigits (yay!) converts each numeral-base pair to a base-10 integer, the results of which are summed by Tr.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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