The Base in the mix

23

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

Kevin Cruijssen

Posted 2016-09-23T07:12:12.273

Reputation: 67 575

1For 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 – 2016-09-23T08:13:43.893

@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 – 2016-09-23T08:17:42.020

Answers

4

05AB1E, 7 6 5 bytes

Uses the 05AB1E encoding.

Saved 1 byte using the new built-in š as suggested by Kevin Cruijssen

TšüöO

Explanation

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

Tš     # prepend a 10 to the list
  üö   # reduce by conversion to base-10
    O  # sum

Try it online!

Modified testsuite

Emigna

Posted 2016-09-23T07:12:12.273

Reputation: 50 798

2Can be 5 bytes now with the builtin š instead of ¸ì. Also, your explanation states "append" instead of "prepend". :) – Kevin Cruijssen – 2019-03-21T08:50:44.953

@KevinCruijssen: Thank you :) – Emigna – 2019-03-21T09:39:21.950

9

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

Jonathan Allan

Posted 2016-09-23T07:12:12.273

Reputation: 67 804

7

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

Jonathan Allan

Posted 2016-09-23T07:12:12.273

Reputation: 67 804

6

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

Ton Hospel

Posted 2016-09-23T07:12:12.273

Reputation: 14 114

I'd be really interested in an explanation for those of us with weaker perl-fu! – m-chrzan – 2016-09-23T15:16:55.047

2@m-chrzan Solution fixed and explanation added – Ton Hospel – 2016-09-23T17:18:29.450

4

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.

aross

Posted 2016-09-23T07:12:12.273

Reputation: 1 583

3

Java 7, 109 89 86 bytes

int c(int[]a){for(Byte 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(Byte 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

Kevin Cruijssen

Posted 2016-09-23T07:12:12.273

Reputation: 67 575

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 – 2016-09-23T08:32:56.000

1used 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 – 2016-09-23T08:35:25.977

@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 – 2016-09-23T08:38:32.410

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 – 2016-09-23T09:06:12.930

@OlivierGrégoire Feel free to post it as a separate answer. 86 bytes is still shorter than my previous 109 (-12 because of an obvious mistake, so 97) answer. – Kevin Cruijssen – 2016-09-23T09:11:42.083

@cliffroot Btw, don't you mind that I edit your answer every time? If you post it as a separate answer you definitely get my (and other) upvotes for more rep. It's unfortunate comment upvotes aren't worth any rep.. – Kevin Cruijssen – 2016-09-23T09:12:53.050

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 – 2016-09-23T09:14:53.063

3

Jelly, 7 bytes

ṙ1DḅṖḌS

Try it online!

Dennis

Posted 2016-09-23T07:12:12.273

Reputation: 196 637

3You could replace ṖḌ with F – Jonathan Allan – 2016-09-23T07:58:55.403

4Unfortunately, that won't work in the first number has two digits. – Dennis – 2016-09-23T15:31:05.767

3

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

Lmis

Posted 2016-09-23T07:12:12.273

Reputation: 421

Nice! I think you can save a byte by replacing &&s with |s. – ETHproductions – 2016-09-23T15:26:54.543

You can also replace const g with just g – Clyde Lobo – 2016-09-24T08:51:30.167

3

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

Olivier Grégoire

Posted 2016-09-23T07:12:12.273

Reputation: 10 647

3

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.

Digital Trauma

Posted 2016-09-23T07:12:12.273

Reputation: 64 644

2

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

Mego

Posted 2016-09-23T07:12:12.273

Reputation: 32 998

2

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.

Martin Ender

Posted 2016-09-23T07:12:12.273

Reputation: 184 808

2

JavaScript (ES6), 54 48 40 bytes

I used a recursive approach.

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

Saved 6 bytes, thanks to Lmis!
Saved 8 more bytes, thanks to Neil!

Huntro

Posted 2016-09-23T07:12:12.273

Reputation: 459

1I 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 – 2016-09-23T08:21:22.537

1I also think you can save some bytes by using a[0]?stuff():0 instead of a.length&&stuff() – Lmis – 2016-09-23T08:31:32.380

@Lmis Thanks, I've updated it :) – Huntro – 2016-09-23T08:44:50.283

1I think you can shorten this to 40 bytes: f=([b,...a],c)=>b?parseInt(b,c)+f(a,b):0 – Neil – 2016-09-24T18:07:21.340

@Neil nice way of not using the slice function – Huntro – 2016-09-25T09:59:11.527

2

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.

Damien

Posted 2016-09-23T07:12:12.273

Reputation: 2 407

2

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

ptev

Posted 2016-09-23T07:12:12.273

Reputation: 111

You can save one byte with function s=r(x);... – Luis Mendo – 2016-09-24T15:18:54.470

2

Perl 6,  52  50 bytes

{sum (10,|@_).rotor(2=>-1).map:{+":{.[0]}<{.[1]}>"}}
{sum (10,|@_).rotor(2=>-1).map:{":{.[0]}<$_[1]>"}}

Explanation:

# bare block lambda with implicit parameter 「@_」
{
  sum

    ( 10, |@_ )        # the input with a preceding 10
    .rotor( 2 => -1 )  # grab 2 values, back up one, repeat
    .map:
    {
      # create a string of the form ":10<4>"
      ":{
        .[0]            # first element from $_
      }<{
        .[1]            # second element from $_
      }>"
    }
}

Brad Gilbert b2gills

Posted 2016-09-23T07:12:12.273

Reputation: 12 713

1

Japt -x, 7 bytes

äÏsnX}A

Try it

äÏsnX}A     :Implicit input of array
ä           :Take each consecutive pair of elements
 Ï          :Pass them through the following function as X & Y
  s         :  Convert Y to a base-10 string
   nX       :  Convert to an integer from base-X
     }      :End function
      A     :Before doing any of that, though, prepend 10 to the array
            :Implicit output of the sum of the resulting array

Shaggy

Posted 2016-09-23T07:12:12.273

Reputation: 24 623

1

Python 2, 52 bytes

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

Test it on Ideone.

Dennis

Posted 2016-09-23T07:12:12.273

Reputation: 196 637

1

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

nyro_0

Posted 2016-09-23T07:12:12.273

Reputation: 281

1

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

cia_rana

Posted 2016-09-23T07:12:12.273

Reputation: 441

1

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

corvus_192

Posted 2016-09-23T07:12:12.273

Reputation: 1 889

1

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.

Greg Martin

Posted 2016-09-23T07:12:12.273

Reputation: 13 940

1

Common Lisp, 83

(lambda(s)(loop for b ="10"then x for x in s sum(#1=parse-integer x :radix(#1#b))))

Details

(defun base-mix (list)
  (loop
     for base = "10" then string
     for string in list
     sum (parse-integer string :radix (parse-integer base))))

The loop construct accepts "v then w" iteration constructs, where v is an expression to be evaluated the first time the iteration variable is computed, and w is the expression to be evaluated for the successive iterations. Declarations are evaluated one after the other, so base is first "10", then the previous element stringof the list list being iterated. The sum keyword computes a sum: the integer read from string with base b, where b is the integer parsed from the base string, in base 10. #1= and #1# are notations to define and use reader variables: the first affects an s-expression to a variable, the other one replaces the reference by the same object. This saves some characters for long names.

Example

(base-mix '("4" "12" "34" "20" "14" "6" "25" "13" "33"))
=> 235

coredump

Posted 2016-09-23T07:12:12.273

Reputation: 6 292