# Turn an Array into a Math Problem

Given a nonempty list of nonnegative integers, consider rewriting it as an arithmetic problem where:

• A plus sign (+) is inserted between pairs of numbers that increase from left to right (a.k.a. from the start of the list to the end).
• A minus sign (-) is inserted between pairs of numbers that decrease from left to right.
• A multiplication sign (*) is inserted between pairs of numbers that are equal.

Said another way: any sublist a,b becomes a+b if a<b, a-b if a>b, and a*b if a==b.

For example, the list

[12, 0, 7, 7, 29, 10, 2, 2, 1]


would become the expression

12 - 0 + 7*7 + 29 - 10 - 2*2 - 1


which evaluates to 75.

Write a program or function that takes in such a list and evaluates it, printing or returning the result.

• Order of operations matters. Multiplications should be done before any addition or subtraction.
• If the input list has one number, that should be what it evaluates to. e.g.  should give 64.
• Use of eval or exec or similar constructs is allowed.

[list]
expression
value


0
0


1
1


78557
78557

[0,0]
0*0
0

[1,1]
1*1
1

[2,2]
2*2
4

[0,1]
0+1
1

[1,0]
1-0
1

[1,2]
1+2
3

[2,1]
2-1
1

[15,4,4]
15-4*4
-1

[9,8,1]
9-8-1
0

[4,2,2,4]
4-2*2+4
4

[10,9,9,12]
10-9*9+12
-59

[1,1,2,2,3,3]
1*1+2*2+3*3
14

[5,5,4,4,3,3]
5*5-4*4-3*3
0

[3,1,4,1,5,9,2,6,5,3,5,9]
3-1+4-1+5+9-2+6-5-3+5+9
29

[7637,388,389,388,387,12,0,0,34,35,35,27,27,2]
7637-388+389-388-387-12-0*0+34+35*35-27*27-2
7379


The shortest code in bytes wins. Tiebreaker is earlier answer.

• Regarding "order of operations matters" it might be good to state explicitly that addition and subtraction are left-associative and have the same precedence. Jun 12, 2016 at 8:15

## Python 2, 63 bytes

p=s='print-'
for x in input():s+='*+-'[cmp(x,p)]+x;p=x
exec s


Constructs and evals the expression string. The arithmetic symbol is chosen by comparing the previous number p to the current one x. The symbol is appended followed by the current number.

The first number is handled with a clever trick from Sp3000. The initial value of p is set to a string, which is bigger than any number and therefore causes a - before the first number. But, s is initialized to print- at the same time that makes the result start with print-- (thanks to xsot for saving 2 bytes by initializing with print.)

• I think you can move print into the string and use exec instead of eval.
– xsot
Jun 12, 2016 at 13:20

# Pyth, 3126191716 15 bytes

Expressions with * won't evaluate online, but they would theoretically work.

2 bytes thanks to Maltysen.

vsm+@"*-+"._-~k


Test suite (with evaluation).

The other cases (without evaluation).

## History

• 31 bytes: M+G@"*-+"->GH<GHv+sgMC,JsMQtJ\x60e
• 26 bytes: M+G@"*-+"->GH<GHv+sgVQtQ\x60e
• 19 bytes: vtssVm@"*-+"->Zd<~Z
• 17 bytes: vtssVm@"*-+"._-~Z
• 16 bytes: vssVm@"*-+"._-~k
• 15 bytes: vsm+@"*-+"._-~k
• Why won't multiplication work online? If you're not sure it works it may be best to test a bit more before answering. Jun 12, 2016 at 4:26
• Because security stuff (evaluation only works for + and - online) Jun 12, 2016 at 4:26
• @HelkaHomba I didn't have a chance to try it offline yet, but it should work. The online interpreter uses the --safe switch, which replaces eval with ast.literal_eval. Jun 12, 2016 at 4:31
• Ok, fair enough. Jun 12, 2016 at 4:42
• Confirmed, this works with the offline interpreter. Jun 12, 2016 at 5:16

# Jelly, 181615 14 bytes

I0;ð1g×⁹⁸œṗP€S


Uses no built-in eval. Try it online! or verify all test cases.

### How it works

I0;ð1g×⁹⁸œṗP€S  Main link. Input: A (list)

I               Increments; compute the deltas of all adjacent items of A.
0;             Prepend a 0.
ð            Begin a new, dyadic chain.
Left argument: D (0 plus deltas). Right argument: A
1g          Compute the GCD of 1 and each item in D.
This yields 1 for non-negative items, -1 for negative ones.
×⁹        Multiply each 1 or -1 with the corresponding item of A.
This negates every item in A that follows a - sign.
⁸œṗ     Partition the result by D. This splits at occurrences of non-zero
values of D, grouping items with identical absolute value.
P€   Take the product of each group.

• I out-golfed you! Jun 12, 2016 at 6:04
• Nicely done. I should add Python's eval as an atom... Jun 12, 2016 at 6:07
• I out-out-golfed you. :P Jun 12, 2016 at 6:25
• Nicely done, your turn! Jun 12, 2016 at 6:29

# MATL, 12 bytes

Y'^l6MdZSh*s


This uses @aditsu's very nice idea of run-length encoding.

Try it online!

### Explanation

       % Take input vector implicitly
Y'     % RLE. Produces two vectors: values and lengths
^      % Rise each value to the number of consecutive times it appears. This
% realizes the product of consecutive equal values
l      % Push 1
6M     % Push vector of values again
d      % Consecutive differences
ZS     % Sign function. Gives 1 or -1 (no 0 in this case)
h      % Concatenate horizontally with previous 1
*      % Multiply. This gives plus or minus depending on increasing character
s      % Sum of vector. This realizes the additions or subtractions
% Display implicitly

• Haha had just written up something similar. RLE works out well for this Jun 12, 2016 at 13:42
• @Suever I see :-D Jun 12, 2016 at 14:59

# CJam, 20

q~e{~_W-g\:W@#*}%:+


Try it online

Explanation:

q~       read and evaluate the input (array of numbers)
e       RLE encode, obtaining [count number] pairs
{…}%     map each pair
~_     dump the count and number on the stack, and duplicate the number
W-     subtract the previous number (W is initially -1 by default)
g      get the sign of the result
\      swap with the other copy of the number
:W     store it in W (for next iteration)
@#     bring the count to the top, and raise the number to that power
*      multiply with the sign
:+       add all the results together


# JavaScript (ES6), 54

p=>eval(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))


eval receives a comma separated list of expressions and returns the value of the last one.

Test

f=p=>eval(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))

t=p=>(0+p.map(v=>x+='*-+'[(p>v)+2*(p<v)]+(p=v),x=1))

function Test() {
var a=I.value.match(/\d+/g).map(x=>+x) // convert input to a numeric array

var x=f(a),y=t(a)
O.textContent='Value '+x+'\n(no eval '+y+')'
}

Test()
#I { width:80%}
<input value='12, 0, 7, 7, 29, 10, 2, 2, 1' id=I>
<button onclick='Test()'>Test</button>
<pre id=O></pre>

• That's the worst abuse of the comma operator that I can remember seeing on this site...
– Neil
Jun 12, 2016 at 10:26

# Julia, 76 57 bytes

!x=[[" ""-*+"[2+sign(diff(x))]...] x]'|>join|>parse|>eval


My first time golfing Julia, so maybe there are obvious improvements. Try it online!

Dennis saved a ton of bytes.

• Nice job. I didn't realize you can define a custom function for !. Jun 12, 2016 at 19:43
• @Eᴀsᴛᴇʀʟʏ Iʀᴋ codegolf.stackexchange.com/a/81028/12012 Jun 12, 2016 at 19:51

# Pyth - 2322 20 bytes

As with Kenny's, multiplication doesn't work online.

vs.i+\+@L"*+-"._M-Vt

• Whoo is Kevin ? Jun 12, 2016 at 4:43
• @LeakyNun I forgot your name after a while >_> Jun 12, 2016 at 4:43
• @Maltysen Haha, you're thinking of kevin-not-kenny Lau Jun 12, 2016 at 4:57
• Sorry, I was eating, so I could not golf my solution. Your turn. Jun 12, 2016 at 5:14
• @LeakyNun almost there Jun 12, 2016 at 6:00

# R, 92 bytes

There's likely still some good golfing that can be done here.

eval(parse(t=paste(i<-scan(),c(ifelse(d<-diff(i),ifelse(d>0,"+","-"),"*"),""),collapse="")))


Ungolfed:

i = scan()                # Read list from stdin
d = diff(i)               # Calculate difference between each element of list
s = ifelse(d,             # If d!=0
ifelse(d>0,  # And if d>1
"+",  # Return plus
"-"), # Else return minus
"*")         # Else (i.e. d==0) return multiply.
s = c(s,"")               # Pad the list s with an empty string, so it's the same
# length as i
p = paste(i,s,collapse="")# Paste the elements of i and s into one long string.
eval(parse(t=p))          # Evaluate the string as a language object.

• I managed to save just one byte using an indexing approach Jul 19, 2018 at 19:04

# Brachylog, 34 32 bytes

~b≜ḅ⟨h⟨h≡^⟩l⟩ᵐs₂ᶠ{zh>₁&ttṅ|tt}ᵐ+


Try it online!

# TI-BASIC, 146 bytes

I'll format it nicely when not on mobile. Sleep escapes me, so you get this. Enjoy.

Prompt L₁
"(→Str1
For(A,1,dim(L₁
{0,1→L₂
{0,L₁(A→L₃
LinReg(ax+b) L₁,L₃,Y₁
Equ►String(Y₁,Str2
sub(Str2,1,-1+inString(Str2,"X→Str2
If A>1
Then
L₁(A-1
2+(Ans>L₁(A))-(Ans<L₁(A
Str1+sub("+*-",Ans,1→Str1
End
Str1+Str2→Str2
End
expr(Str1


# Javascript ES6, 64 62 chars

a=>eval(a.map((x,i)=>x+('*+-'[x<a[++i]|(x>a[i])*2])).join+1)

• Should not this be a function and a a parameter? Jun 12, 2016 at 13:26
• This is invalid as-is. Jun 12, 2016 at 15:19
• @edc65, yes, it should. But in fact it was counted (61 specified, but real code length was 59), I just badly copied a new code (the edit should be a[i+1]...a[i+1] => a[++i]...a[i] - 2 chars shorter, but I mistakenly replaced the whole code dropping a=>). Jun 12, 2016 at 19:39
• @EᴀsᴛᴇʀʟʏIʀᴋ, it's just a wrong paste. See comment above and edit history for more detailes. Jun 12, 2016 at 19:40
• @Qwertiy okay cool. Nice answer btw.. Jun 12, 2016 at 19:42

# Java, 384 bytes

int s(int[]l){int n=l,m;for(int i=0;i<l.length-1;i++)if(l[i]<l[i+1])if(i<l.length-2&&l[i+1]!=l[i+2])n+=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n+=m;}else if(l[i]>l[i+1])if(i<l.length-2&&l[i+1]!=l[i+2])n-=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n-=m;}else{m=l[i];while(i<l.length-1&&l[i]==l[i+1])m*=l[i++];n+=m;}return n;}


Ungolfed try online

int s(int[] l)
{
int n=l, m;

for(int i=0; i<l.length-1; i++)
{
if(l[i] < l[i+1])
{
if (i<l.length-2 && l[i+1]!=l[i+2])
{
n += l[i+1];
}
else
{
m = l[i+1];
while(i<l.length-2 && l[i+1]==l[i+2]) m *= l[(i++)+1];
n += m;
}
}
else if(l[i] > l[i+1])
{
if (i<l.length-2 && l[i+1]!=l[i+2])
{
n -= l[i+1];
}
else
{
m = l[i+1];
while(i<l.length-2 && l[i+1]==l[i+2]) m *= l[(i++)+1];
n -= m;
}
}
else
{
m = l[i];
while(i<l.length-1 && l[i]==l[i+1]) m *= l[i++];
n += m;
}
}

return n;
}

• Some quick golfs: int a=l.length, && => &, put the int i=0 on the same "line" as int n=l,m. Jun 12, 2016 at 10:10
• In if(i<l.length-2&&l[i+1]!=l[i+2])n+=l[i+1];else{m=l[i+1];while(i<l.length-2&&l[i+1]==l[i+2])m*=l[(i++)+1];n+=m;, you can just replace this with the content inside the else block. Jun 12, 2016 at 10:11

# Javascript ES6, 79 chars

a=>eval(${a}.replace(/(\d+),(?=(\d+))/g,(m,a,b)=>a+('*+-'[+a<+b|(+a>+b)*2])))  ## Perl, 49 bytes 48 bytes code + 1 for -p s/\d+ (?=(\d+))/$&.qw(* - +)[$&<=>$1]/ge;$_=eval  ### Usage perl -pe 's/\d+ (?=(\d+))/$&.qw(* - +)[$&<=>$1]/ge;$_=eval' <<< '12 0 7 7 29 10 2 2 1' 75  ### Notes I learnt here that you can capture a lookahead in PCRE, although it's a little unintuitive ((?=(\d+)) instead of ((?=\d+))). It does make sense after reading though as you would be capturing a zero-length match (the lookahead) with the latter, and instead capture the match with the former). Thanks to @ninjalj for saving 8 bytes! • @LeakyNun I never know exactly what to count for that, I can't find the relevant meta post, I'm happy to bump the count, but I thought that since you can run with -e for free, adding a p making it -pe was +1? Will update for now, but if you could find a source I could quote/link to going forward, that'd be awesome! Jun 12, 2016 at 12:37 • @DomHastings 1 is correct, per the reason you say + this meta post Jun 12, 2016 at 12:39 • Thanks @Sp3000! I couldn't find that post for the life of me! @LeakyNun meta post for +1 as per comment from Sp3000 Jun 12, 2016 at 12:47 • Instead of using chained conditional operators, you can use the spaceship operator to select from a list: $&.qw(* - +)[$&<=>$1] in the replacement part of the s/// operator. Jun 13, 2016 at 17:44
• @ninjalj Of course! amazing, thanks! -8 with that! Jun 13, 2016 at 18:12

## Actually, 30 bytes

;2@VpXdXi-su"+*-"EM' @o♀+εj≡


Unfortunately, because the eval (≡) command only evaluates literals on TIO, this program does not work on TIO.

Explanation:

;2@VpXdXi-su"+*-"EM' @o♀+εj≡
;                               duplicate input
2@V                            overlapping sublists of length <= 2
pXdX                        discard first and last element (length-1 sublists)
i-su"+*-"EM           map: for each pair of elements
i-su                     flatten, subtract, sign, increment (results in a 0 if b < a, 1 if b == a, and 2 if b > a)
"+*-"E               select the correct operation
' @o       put a space at the beginning of the list to pad it properly
♀+     pairwise addition (since addition is not defined for strings and integers, this just zips the lists and flattens the result into a single flat list)
εj   join with empty string
≡  eval


# R, 120 44 bytes

r=rle(scan());c(1,sign(diff(r$v)))%*%r$v^r$l  Try it online! The algorithm is similar to this answer's, but I only realized it after coding my answer. Much better than my original answer that was using eval(parse). Fully leverages R's vectorized operations - does the * operation first using rle(x)$values ^ rle(x)$lenghts and dot-products this vector with sign( diff( rle(x)$values ) ) (predended with 1).

# 05AB1E (legacy), 1716 15 bytes

ü.S…*-+sè‚ζJJ.E


-2 bytes thanks to @Emigna.

Explanation:

ü                  # Pair-wise loop over the (implicit) input-list
#  i.e. [12,0,7,7] → [[12,0],[0,7],[7,7]]
.S                # Calculate the signum of the pair (-1 for a<b; 0 for a==b; 1 for a>b)
#  i.e. [[12,0],[0,7],[7,7]] → [1,-1,0]
…*-+sè          # Index over "*-+" (with wrap-around)
#  i.e. [1,-1,0] → ['-','+','*']
‚ζ        # Zip the two lists together (appending the operands to the numbers)
#  i.e. [12,0,7,7] and ['-','+','*','+']
#   → [[12,'-'],[0,'+'],[7,'*'],[7,' ']]
JJ      # Join them together
#  [[12,'-'],[0,'+'],[7,'*'],[7,' ']] → '12-0+7*7 '
.E    # Evaluate as Python code
#  i.e. '12-0+7*7' → 61

• Due to modular indexing, you can remove > by moving + to the end of the string. Aug 23, 2018 at 7:10
• @Emigna Not sure how I missed that.. Thanks! Aug 23, 2018 at 7:13
• You can save another byte by removing Ć and ¨, if you use ‚ζ instead of ø Aug 23, 2018 at 7:18
• @Emigna Oh, now that is smart! Thanks. I knew the enclose was a bit of a weird work-around, but didn't knew how to fix it. ‚ζ is a perfect alternative work-around, since the space is ignore in the eval. Thanks again. :) Aug 23, 2018 at 7:37

# PHP, 103 bytes

Neat challenge. This got longer than expected. I think using array_map or similar won't improve the byte count, as anonymous functions are still expensive in PHP.

foreach(fgetcsv(STDIN)as$v)(0<=$p?$o.=$p.('*-+'[($p>$v)+2*($p<$v)]):_)&&$p=$v;echo eval("return$o$v;");


Runs from command line, will prompt for a comma separated list, like:

php array_to_math.php
12, 0, 7, 7, 29, 10, 2, 2, 1


## PowerShell v2+, 62 bytes

-join($args|%{"$o"+'*+-'[($o-lt$_)+2*($o-gt$_)];$o=$_})+$o|iex  Takes input as space-separated command-line arguments, which gets converted into automatic array $args. We iterate through each element, using helper variable $o each iteration to remember what our previous entry was. We use a indexed-string to pull out the appropriate operator, done by performing math on the implicitly-converted Boolean values (e.g., if the previous entry is smaller, the [] evaluates to 1+2*0 so '*+-' means the + is selected). The concatenated strings are left on the pipeline. We collect all of those snippets together (e.g., 3-, 1+, 4-, etc.) with a -join operation, concatenate on the final number (implicitly converted to string), and pipe it to iex (alias for Invoke-Expression and similar to eval). • A concern is that if the caller has already given$o a value (say $o = 999) then the expression in this entry will not compute the correct value. An initialization of$o needs to be added to this solution.
– Bevo
Aug 12, 2016 at 21:39
• @Bevo This is intended to be a full script, executed via the command line, and not a function or via the interactive shell. The vast majority of my submissions are as such, since in such a scenario, there is no predefined variables to worry about and thus the code can be a bit shorter. Aug 14, 2016 at 3:52

# Japt, 25 bytes

Would like to cut it shorter, but I couldn't make an eval-less version work.

S+Uä!- ®"*+-"gZÎÃ¬)íU
OxU


Try it online!

• Got it down to 22 bytes but still think it can be improved on. Aug 24, 2018 at 14:32

# Japt-x, 21 19 bytes

änJ f mÎí*Uò¦ ®ÎpZÊ


Try it

## Explanation

                        :Implicit input of array U
J                     :Prepend -1
än                      :Get deltas
f                   :Filter (remove 0s)
m                 :Map
Î                : Signs
í               :Interleave
U             :  Original input
ò            :  Partition on
¦           :   Inequality
®         :  Map each sub-array Z
Î        :    Get first element
p       :    Raise to the power of
ZÊ     :     Length of Z
*              :Reduce each pair of elements by multiplcation
:Implicitly reduce by addition and output