# Weapons of Math Instruction

Last time when I tried to come up with something easy that wasn't a duplicate, it ended up being way too hard.. So hopefully this time it's indeed something newcomers can try as well.

Input:

An array/list with integers/decimals. (Or a string representing an array with integers/decimals.)

Output:

Loop through the numbers and apply the following five mathematical operands in this order:

• Addition (+);
• Subtraction (−);
• Multiplication (* or × or ·);
• Real / Calculator Division (/ or ÷);
• Exponentiation (^ or **).

(NOTE: The symbols between parenthesis are just added as clarification. If your programming language uses a completely different symbol for the mathematical operation than the examples, then that is of course completely acceptable.)

Keep continuing until you've reached the end of the list, and then give the result of the sum.

Challenge rules:

• Exponentiation by 0 (n ^ 0) should result in 1 (this also applies to 0 ^ 0 = 1).
• There are no test cases for division by 0 (n / 0), so you don't have to worry about that edge-case.
• If the array contains just a single number, we return that as the result.

General rules:

• This is , so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer 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.

Test cases:

[1,2,3,4,5] -> 0
-> 1 + 2 = 3
-> 3 - 3 = 0
-> 0 * 4 = 0
-> 0 / 5 = 0

[5,12,23,2,4,4,2,6,7] -> 539
-> 5 + 12 = 17
-> 17 - 23 = -6
-> -6 * 2 = -12
-> -12 / 4 = -3
-> -3 ^ 4 = 81
-> 81 + 2 = 83
-> 83 - 6 = 77
-> 77 * 7 -> 539

[-8,50,3,3,-123,4,17,99,13] -> -1055.356...
-> -8 + 50 = 42
-> 42 - 3 = 39
-> 39 * 3 = 117
-> 117 / -123 = -0.9512...
-> -0.9512... ^ 4 = 0.818...
-> 0.818... + 17 = 17.818...
-> 17.818... - 99 -> -81.181...
-> -81.181... * 13 = -1055.356...

[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2] -> 256
-> 2 + 2 = 4
-> 4 - 2 = 2
-> 2 * 2 = 4
-> 4 / 2 = 2
-> 2 ^ 2 = 4
-> 4 + 2 = 6
-> 6 - 2 = 4
-> 4 * 2 = 8
-> 8 / 2 = 4
-> 4 ^ 2 = 16
-> 16 + 2 = 18
-> 18 - 2 = 16
-> 16 * 2 = 32
-> 32 / 2 = 16
-> 16 ^ 2 = 256

[1,0,1,0,1,0] -> 1
-> 1 + 0 = 1
-> 1 - 1 = 0
-> 0 * 0 = 0
-> 0 / 1 = 0
-> 0 ^ 0 = 1

[-9,-8,-1] -> -16
-> -9 + -8 = -17
-> -17 - -1 = -16

[0,-3] -> -3
-> 0 + -3 = -3

[-99] -> -99

• Not integer division? Jun 13, 2016 at 7:01
• @LeakyNun No. Perhaps I should change the input to a list with decimals instead of integers due to division (and test case 3)? Jun 13, 2016 at 7:02
• In math, there are two conflicting "rules": n ^ 0 = 1, but 0 ^ n = 0. The conflict is resolved by setting n != 0 for both of the rules, but then it leaves 0 ^ 0 undefined. However, there are a lot of things that fall into place nicely in mathematics if 0 ^ 0 is defined to be 1. See Wikipedia for some details.
– user45941
Jun 13, 2016 at 8:14
• @Bálint The rules state that there will never be a valid input with a division by zero. You don't have to worry about that edge case.
– user45941
Jun 13, 2016 at 9:12

# Emacs Lisp, 127 bytes

(lambda(x)(let((f'(+ - * / expt))(a(float(car x)))(x(cdr x)))(dotimes(i(length x)a)(set'a(funcall(nth(mod i 5)f)a(nth i x))))))


Ungolfed:

(lambda(x)
(let ((f'(+ - * / expt))  ; list of functions in order they are called
(a (float (car x))) ; initial value
(x (cdr x)))        ;
(dotimes (i (length x) a)
(set 'a (funcall (nth (mod i 5) f) ; call the i % 5th function
a                 ; with accumulator
(nth i x))))))    ; and the ith value


Testcases:

(-map
(lambda(x)(let((f'(+ - * / expt))(a(float(car x)))(x(cdr x)))(dotimes(i(length x)a)(set'a(funcall(nth(mod i 5)f)a(nth i x))))))
'((1 2 3 4 5)
(5 12 23 2 4 4 2 6 7)
(-8 50 3 3 -123 4 17 99 13)
(2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2)
(1 0 1 0 1 0)
(-9 -8 -1)
(0 -3)
(-99)))


Output:

(0.0 539.0 -1055.356943846277 256.0 1.0 -16.0 -3.0 -99.0)


# Ruby, 57 bytes

->a{i=0;a.reduce{|x,y|x.send %w[** + - * /][(i+=1)%5],y}}


Try it online!

Takes an array of floats, but also works with integers, as long as all division results are integer.

At first, I tried fiddling with eval which looks like the obvious approach, but it gets rather verbose. Instead, I opted for send, which is basically Ruby's way to call methods by names, so that x.send("+",y) is equivalent to x+y.

# shell script, 15713513313012499958885 81 bytes

golfed (bash/non-posix) - 81 bytes

f()(A=$1;S=+-*/^;shift;for B;{ C=${S:((I++%5)):1};A=bc -l<<<$A$C$B;};echo$A)


golfed (portable/posix, using 'cut'-operator) - 118 bytes

f()(S=+-x/^;A=$1;shift;for B;do C=echo$S|cut -b1;S=echo $S|cut -b2-5;S="$S$C";A=echo$A$C$B|bc -l;done;echo $A)  golfed (portable/posix, with builtins) - 124 bytes f()(A=$1;shift;for B;do case $I in 1)C=-;;2)C=*;;3)C=/;;4)C=^;;*)C=+;I=;;esac;I=$((I+1));A=echo $A$C$B|bc -l;done;echo$A)


ungolfed (posix - with builtins):

A=$1 shift for B;do case$I in
1)C=-;;
2)C=*;;
3)C=/;;
4)C=^;;
*)C=+;I=
esac
I=$((I+1)) A=echo$A$C$B|bc -l
done
echo $A  ungolfed (posix - with 'cut'): S=+-x/^ A=$1
shift
for B;do
C=echo $S|cut -b1 S=echo$S|cut -b2-5
S="$S$C"
A=echo $A$C$B|bc -l done echo$A


This is unfair!

We don't have real division in language 'sh',
so we must use 'bc' which is...lame 8-)

hint: your directory must have no files, otherwise the asterisk expands to filenames (◔_◔)

# Tests:

# f 1 2 3 4 5
0
# f 5 12 23 2 4 4 2 6 7
539
# f -8 50 3 3 -123 4 17 99 13
-1055.35
# f 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
256.00
# f 1 0 1 0 1 0
1
# f -9 -8 -1
-16
# f 0 -3
-3
# f -99
-99


# 05AB1E, 2928 27 bytes

Using 'Python eval' builtin (29 28 27 bytes):

g'(×svy')"+-*/"S„**ªNè}\J.E


Try it online or verify all test cases. (NOTE: ª is ¸« and we use the legacy version in the TIO, because .E is disabled in the new version of 05AB1E on TIO.)

Using 'Execute as 05AB1E' builtin (29 28 bytes):

vyD0‹i¦'(}N_iðë"m+-*/"Nè]J.V


Explanation:

In Python ** is used for exponentiation. In addition, *,/,** have operator precedence over +,-. So the code transforms [-1,2,-3,4,-5] to (((((-1)+2)--3)*4)**-5), and then uses .E to execute the string as Python eval.

g                  # Take the length of the (implicit) input
'(×              '# Create a string of "(" characters of that size
s                  # Swap so the (implicit) input is at the top of the stack again
v            }    # Loop y of each of its items:
y                #  Push y
')             '#  Push ")"
"+-*/"S       #  Push ["+","-","*","/"]
„**ª   #  Append a trailing "**": ["+","-","*","/","**"]
Nè #  Get a string from this list based on the index of the loop
#  (with automatic wraparound)
\                  # Discard the trailing operand from the stack
J                 # Join all strings on the stack together
.E               # Execute as Python eval (and output implicitly)


In 05AB1E negative values are with a trailing ( instead of leading -, and m is used for exponentiation. In addition, a Polish notation is used. So the program transforms [-1,2,-3,4,-5] to 1( 2+3-4*5(m, and then uses .V to execute the string as 05AB1E code.

v                  # Loop y of each of its items:
y                 #  Push y
D0‹i   }         #  If y is negative:
¦            #   Remove the first character (the minus sign)
'(         '#   And push a "("
N_i              #  If the index of the loop is 0:
ð             #   Push a space character
ë              #  Else:
"m+-*/"Nè     #   Push a character from "m+-*/" based on the index of the loop
#   (with automatic wraparound)
]                  # Close both the if-else and loop
J                 # Join all strings on the stack together
.V               # Execute as 05AB1E code (and output implicitly)


# 05AB1E, 15 bytes

ćsvy"+-*/m"Nè.V


Try it online! or as a Test Suite

Explanation

ć                # extract the head of the input list
sv              # for each (value y, index N) in the rest of the list
y             # push the element
"+-*/m"Nè    # push a string representation of the Nth operator (wraps around)
.V  # execute it as code


# C# (.NET Core), 130 bytes

Without LINQ.

s=>{var x=s[0];for(var j=1;j<s.Length;j++){int t=j%5;var z=s[j];x=t<1?x=Math.Pow(x,z):t<2?x+=z:t<3?x-=z:t<4?x*=z:x/=z;}return x;};


Try it online!

• 84 - use the interpreter because it imports LINQ (among other commonly used core libraries) for free Jan 8, 2019 at 2:04

# Runic Enchantments, 64 bytes

R31B~~?@+31B~~?@S-31B~~?@*31B~~?@S,31B~~?@Sp
\i<{1[lil1-{S{)]{{B


Try it online!

First line is the main program loop, which reads a number from input and performs the next math instruction. If no input, the attack is dumped to the output and the program terminates. Entry point is the < on the second line, which reads the first number from input prior to entering the main loop. Invalid input blindly accepted with unpredictable results (only + and * are defined for strings, other operations would result in an empty stack).

Woo, finally found a use for Branch command! The second line starting at index 3 acts like a function. In this case it takes in input, checks that it got input, and arranges the stack for return. Then 31B~~ invokes and cleans up after the invokation (as the Branch instruction leaves 2 values on top of the stack, add a return pointer). All told the overhead (8+5n) was less than in-line (9n). I think I'll be adding a modifier that cause B to not push those 2 values (overhead of 2 bytes to save 2n bytes). Happily, no directional commands are needed to insure consistent execution.

Also featured is the [ and ] stack-of-stacks commands, which lets the program temporarily remove the return location from the stack as it handles reading input. It saves several bytes worth of stack manipulation having to otherwise work around those 2 values. These do enforce a maximum input list of 9 values. Changing the entry to y<< increases that to 19 items (and as < acts like a NOP, the branch pointer doesn't need to update). A third line with \y<< (changing the existing \ to U) would double that again to 39 items.

Stack at the end of the Branch "function" would look like [v,i,1,x,y] where x,y are at the top and the 0-indexed location on the first line (y will always be 0) where the next instruction with execute. v is the value that started on the stack prior to entry into the Branch "function". And i is the value read from input. If no input was available, [i,1] would instead be [0] resulting in v being printed when ?@ is reached.

# x86-64 machine code (Linux), 90 bytes

0000000000000000 <weapons_asm>:
0:   48 89 f1                mov    %rsi,%rcx
3:   db 07                   fildl  (%rdi)

0000000000000005 <math_loop>:
5:   48 83 c7 04             add    $0x4,%rdi 9: 48 ff c9 dec %rcx c: e3 49 jrcxz 57 <done> e: da 07 fiaddl (%rdi) 10: 48 83 c7 04 add$0x4,%rdi
14:   48 ff c9                dec    %rcx
17:   e3 3e                   jrcxz  57 <done>
19:   da 27                   fisubl (%rdi)
1b:   48 83 c7 04             add    $0x4,%rdi 1f: 48 ff c9 dec %rcx 22: e3 33 jrcxz 57 <done> 24: da 0f fimull (%rdi) 26: 48 83 c7 04 add$0x4,%rdi
2a:   48 ff c9                dec    %rcx
2d:   e3 28                   jrcxz  57 <done>
2f:   da 37                   fidivl (%rdi)
31:   48 83 c7 04             add    $0x4,%rdi 35: 48 ff c9 dec %rcx 38: e3 1d jrcxz 57 <done> 000000000000003a <exp_rept>: 3a: 51 push %rcx 3b: 8b 0f mov (%rdi),%ecx 3d: d9 e8 fld1 3f: 83 f9 00 cmp$0x0,%ecx
42:   74 10                   je     54 <exp_rept.done>
44:   9c                      pushfq
45:   7f 02                   jg     49 <exp_rept.l>
47:   f7 d9                   neg    %ecx

0000000000000049 <exp_rept.l>:
49:   d8 c9                   fmul   %st(1),%st
4b:   e2 fc                   loop   49 <exp_rept.l>
4d:   9d                      popfq
4e:   7d 04                   jge    54 <exp_rept.done>
50:   d9 e8                   fld1
52:   de f9                   fdivrp %st,%st(1)

0000000000000054 <exp_rept.done>:
54:   59                      pop    %rcx
55:   eb ae                   jmp    5 <math_loop>

0000000000000057 <done>:
57:   dd 1a                   fstpl  (%rdx)
59:   c3


Firstly, credit to gwaugh's answer which is also submitted for this post. I started working on this solution before gwaugh posted, which can be seen in my git repo's log, but ultimately his approach to this problem was the most efficient (especially the exponentiation). If you feel inclined to upvote my submission, please check out his as well.

Like my other x86 solutions, this code is simply a function that's meant to be called from a C/C++ program, which can be seen at my git repo. This means that the input array, length, and return pointer are passed through rdi, rsi, and rdx. For x86-64, getting the output location as an argument saves bytes, because normally when a C/C++ function returns a double on this processor, it's passed back through xmm0. This means the result double has to be moved from the FPU stack to a place in memory, then moved into xmm0. If we specify a place in memory we want the result, then we can just move the result double directly from the FPU stack to the memory location.

Exponentiation is done through repeated multiplication, with the assumption that we'll only get integer exponents (though the exponent can be negative). If the problem requires handling floating point exponentiation, the solution becomes extremely complicated. The standard way to compute x^y on x86 is to compute 2^(y * log2(x)). However, if x is negative (which happens in test case 2), log2(x) is a complex number, which can't be directly handled by the FPU. If you're curious how pow(double x, double y) is solved in C, check out the glibc code here (hint: it's complicated).

# K (ngn/k), 42 bytes

{*x{?[x;0 2;y/]}/(#1_x)#(+;-;*;%;{*/y#x})}


Try it online!

Sets up a reduce with the original input as x, and a corresponding list of operations to apply.

• (+;-;*;%;{*/y#x}) initialize a list of the desired operations to apply, using {*/y#x} for pow (only works for raising values to integer powers)
• (#1_x)#... "overtake" this list, expanding it to match the length of the input x minus one (as the operations are applied between elements of x)
• x{...}/... set up the reduce, seeded with the original input and run over the list of operations to apply
• ?[x;0 2;y/] use ?[x;i;f] splice to apply the operation between the first two elements of the input, replacing those values with the result of applying the operation (y) between them

# C (gcc), 135 bytes

#include<math.h>
float r(float*a,int l){float z,v=*a;for(int p=1;p<l;v=(float[]){z?pow(v,z):1,v+z,v-z,v*z,v/z}[p++%5])z=a[p];return v;}


Try it online!

• 110 bytes Dec 16, 2021 at 16:21