48
\$\begingroup\$

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.
  • If possible, please add a link with a test for your code.

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
\$\endgroup\$
15
  • \$\begingroup\$ Not integer division? \$\endgroup\$
    – Leaky Nun
    Jun 13, 2016 at 7:01
  • \$\begingroup\$ @LeakyNun No. Perhaps I should change the input to a list with decimals instead of integers due to division (and test case 3)? \$\endgroup\$ Jun 13, 2016 at 7:02
  • \$\begingroup\$ Was this in the sandbox? \$\endgroup\$
    – Bálint
    Jun 13, 2016 at 7:12
  • 9
    \$\begingroup\$ 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. \$\endgroup\$
    – user45941
    Jun 13, 2016 at 8:14
  • 1
    \$\begingroup\$ @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. \$\endgroup\$
    – user45941
    Jun 13, 2016 at 9:12

40 Answers 40

19
\$\begingroup\$

Javascript ES7 49 bytes

a=>a.reduce((c,d,e)=>[c**d,c+d,c-d,c*d,c/d][e%5])

Saved 9 bytes thanks to Dom Hastings, saved another 6 thanks to Leaky Nun

Uses the new exponentiation operator.

\$\endgroup\$
6
  • \$\begingroup\$ @LeakyNun won't that just produce Infinity, not an error? \$\endgroup\$ Jun 13, 2016 at 9:10
  • \$\begingroup\$ Try using eval it might be shorter \$\endgroup\$
    – Downgoat
    Jun 13, 2016 at 16:02
  • \$\begingroup\$ @Upgoat It used eval first, then Leaky Nun showed me, that it is better, to do it like this \$\endgroup\$
    – Bálint
    Jun 13, 2016 at 18:09
  • \$\begingroup\$ @Bálint you, like, using so many, commas? \$\endgroup\$
    – Riker
    Jun 14, 2016 at 15:40
  • 1
    \$\begingroup\$ @EᴀsᴛᴇʀʟʏIʀᴋ Non-native speaker. Bálint often does that. English grammar is silly at the best of times. \$\endgroup\$
    – wizzwizz4
    Jun 14, 2016 at 16:32
11
\$\begingroup\$

Haskell, 76 65 64 62 bytes

Thanks to @Damien for removing another two bytes=)

f(u:v)=foldl(\x(f,y)->f x y)u(zip(v>>[(+),(-),(*),(/),(**)])v)

This uses the >> which here just appends the list [(+),...] to itself length v times. The rest still works still the same as the old versions.

Old versions:

These solutions make use of the infinite lists, as cycle[...] just repeats the given list infinitely. Then it basically gets ziped with the list of numbers, and we just fold (reduce in other languages) the zipped list via a lambda, that applies the operators to the accumulator/current list element.

f(u:v)=foldl(\x(f,y)->f x y)u(zip(cycle[(+),(-),(*),(/),(**)])v)

f(u:v)=foldl(\x(y,f)->f x y)u(zip v(cycle[(+),(-),(*),(/),(**)]))

f l=foldl(\x(y,f)->f x y)(head l)(zip(drop 1l)(cycle[(+),(-),(*),(/),(**)]))
\$\endgroup\$
5
  • \$\begingroup\$ you can replace cycle by: v>> \$\endgroup\$
    – Damien
    Jun 13, 2016 at 11:38
  • \$\begingroup\$ @Damien Thank you very much! \$\endgroup\$
    – flawr
    Jun 13, 2016 at 12:08
  • \$\begingroup\$ Hm, foldl(&)u$zipWith(&)v(flip<$>v>>[…])? \$\endgroup\$
    – Bergi
    Jun 14, 2016 at 0:22
  • \$\begingroup\$ @Bergi I honestly cannot read what this is doing anymore=) Anyway, we need an import for &, so that would be longer again, but thanks anyway! \$\endgroup\$
    – flawr
    Jun 14, 2016 at 9:24
  • \$\begingroup\$ @flawr: Actually my idea was quite the same as what Lazersmoke posted as an answer, I just hadn't read it. I got to it when trying to simplify that lamda of yours with something like uncurry. Didn't work out, but I noticed you should be able to save another byte by using $ instead of parenthesis. \$\endgroup\$
    – Bergi
    Jun 14, 2016 at 13:02
8
\$\begingroup\$

Pyke, 22 21 bytes

lt5L%"+-*/^"L@\RJQ_XE

Try it here!

lt5L%                 -    map(len(input)-1, %5)
     "+-*/^"L@        -   map(^, "+-*/^"[<])
              \RJ     -  "R".join(^)
                    E - pyke_eval(^, V)
                 Q_X  -  splat(reversed(input))
\$\endgroup\$
0
7
\$\begingroup\$

Jelly, 13 bytes

“+_×÷*”ṁṖ⁸żFV

Try it online! or verify all test cases.

How it works

“+_×÷*”ṁṖ⁸żFV  Main link. Argument: A (list of integers)

“+_×÷*”        Yield the list of operations as a string.
        Ṗ      Yield A popped, i.e., with its last element removed.
       ṁ       Mold; reshape the string as popped A.
               This repeats the characters of the string until it contains
               length(A)-1 characters.
         ⁸ż    Zipwith; pairs the integers of A with the corresponding characters.
           F   Flatten the result.
            V  Eval the resulting Jelly code.
               Jelly always evaluates left-to-right (with blatant disregard towards
               the order of operations), so this returns the desired result.
\$\endgroup\$
5
  • \$\begingroup\$ Nice, that's 8 lower byte-count than Pyke, which was currently in the lead. \$\endgroup\$ Jun 13, 2016 at 16:33
  • 3
    \$\begingroup\$ Nobody outgolfs Dennis. Never. \$\endgroup\$
    – Blue
    Jun 13, 2016 at 18:24
  • 1
    \$\begingroup\$ Just a question: does it really count as 13 bytes with all those non-ascii characters? \$\endgroup\$ Jun 17, 2016 at 7:23
  • 3
    \$\begingroup\$ @XavierDury Yes. The bytes link in the header leads to Jelly's very own code page, which encodes the 256 characters Jelly understands as a single byte each. \$\endgroup\$
    – Dennis
    Jun 17, 2016 at 7:25
  • \$\begingroup\$ @Dennis Thank you for the precision! \$\endgroup\$ Jun 17, 2016 at 7:28
7
\$\begingroup\$

Haskell, 61 Bytes

foldl(flip id)0.zipWith flip((+):cycle[(+),(-),(*),(/),(**)])

Creates a series of transformations in a list, as in [add 1, add 2, subtract 3, ...], starting with 2 additions because we start with 0 in the fold. Next, we do what I call the List Application Fold, or foldl (flip id), which applies a list of homomorphisms in series. This starts with zero, adds the initial value, then does all of the above computed transformations to get a final result.

Note that (flip id) is the same as (\x y->y x), just shorter.

Sample usage:

f = foldl(flip id)0.zipWith flip((+):cycle[(+),(-),(*),(/),(**)])
f [1,2,3,4,5] -- Is 0.0
\$\endgroup\$
2
  • \$\begingroup\$ Instead of flip id, you could simply use &. Or flip($). Wow, I never realised ($) = id \$\endgroup\$
    – Bergi
    Jun 14, 2016 at 0:30
  • 1
    \$\begingroup\$ @Bergi: & is defined in Data.Function, so you need the import, too. Maybe some online interpreter imports it by default, but then you need to specify which one you use. \$\endgroup\$
    – nimi
    Jun 14, 2016 at 5:03
7
\$\begingroup\$

TSQL 116 115 88 bytes

Thanks to Ross Presser suggestion I was able to golf this down to 88 characters

-- In Try-it code, this must be DECLARE @y TABLE 
CREATE TABLE T(a real, i int identity)
INSERT T values(5),(12),(23),(2),(4),(4),(2),(6),(7)

DECLARE @ REAL SELECT @=CHOOSE(i%5+1,@/a,ISNULL(POWER(@,a),a),@+a,@-a,@*a)FROM T
PRINT @

Try it online

\$\endgroup\$
10
  • 1
    \$\begingroup\$ 1 less byte: require the input table to be named T instead of @y. The PL/SQL solution had this, so why not TSQL. \$\endgroup\$ Jun 13, 2016 at 16:15
  • \$\begingroup\$ @RossPresser yes of course. how did I miss that. It is not possible in the test link, no permissions to create tables, and it will only run correctly the first time on a database. But what does that matter when a character can be golfed. Thanks for your hint, your improvement has been added \$\endgroup\$ Jun 13, 2016 at 19:51
  • \$\begingroup\$ Golfed out another 12 bytes: use CHOOSE instead of nested IIF, leaving one IIF for the i=1 case. With your permission, I will edit the answer. \$\endgroup\$ Jun 13, 2016 at 20:31
  • \$\begingroup\$ answer edited. Here's the try-it link -- I'm anonymous so it has no name after it: data.stackexchange.com/stackoverflow/query/edit/499612 \$\endgroup\$ Jun 13, 2016 at 20:34
  • 1
    \$\begingroup\$ @RossPresser I didn't know CHOOSE. included your suggestion and golfed it a bit further \$\endgroup\$ Jun 14, 2016 at 8:01
6
\$\begingroup\$

Pyth, 27 26 25 bytes

.v+>tlQ*lQ"^c*-+":jdQ\-\_

Test suite.

Pyth uses prefix notation: 1+2 is written as +1 2 (space needed to separate numbers).

Therefore, for the first testcase, the expression would be (((1+2)-3)*4)/5, which in prefix notation, would be written as /*-+ 1 2 3 4 5.

In Pyth, float division is c instead of /, so it becomes c*-+ 1 2 3 4 5.

Also, in Pyth, -100 is written as _100 instead.

Therefore, for the third test case, which is ((((((((-8+50)-3)*3)/-123)^4)+17)-99)*13), it becomes: *-+^c*-+ _8 50 3 3 _123 4 17 99 13.

.v+>tlQ*lQ"^c*-+":jdQ\-\_
                  jdQ       Join input by space.
                 :   \-\_   Replace "-" with "_".
   >tlQ*lQ"^c*-+"           Generate the string "...^c*-+" of suitable length.
  +                         Join the two strings above.
.v                          Evaluate as a Pyth expression.

History

\$\endgroup\$
3
  • \$\begingroup\$ You're fast! Seems like I succeeded in making an easier challenge. Or you're just THAT good. ;) \$\endgroup\$ Jun 13, 2016 at 7:11
  • 1
    \$\begingroup\$ Because it's similar to this. \$\endgroup\$
    – Leaky Nun
    Jun 13, 2016 at 7:20
  • 2
    \$\begingroup\$ 24 bytes \$\endgroup\$
    – Maltysen
    Jun 13, 2016 at 18:06
6
\$\begingroup\$

Actually, 23 bytes

;l"+-*/ⁿ"*@R':j':+'?o+ƒ

Try it online!

Actually uses postfix notation for mathematics, and operators that only ever take two arguments (such as the operators for addition, subtraction, multiplication, division, and exponentiation) do nothing when there is only one element on the stack. Thus, turning the input into Actually code is as simple as reversing the input, formatting it as numerics, and appending the operations. Then, the resultant code can be executed, giving the desired output.

Explanation:

;l"+-*/ⁿ"*@R':j':+'?o+ƒ
;l"+-*/ⁿ"*               repeat the operations a number of times equal to the length of the input
                            (since extraneous operations will be NOPs, there's no harm in overshooting)
          @R             reverse the input
            ':j          join on ":" (make a string, inserting ":" between every pair of elements in the list)
               ':+       prepend a ":" (for the first numeric literal)
                  '?o    append a "?"
                           (this keeps the poor numeric parsing from trying to gobble up the first + as part of the numeric literal, since ? isn't interpreted as part of the literal, and is a NOP)
                     +   append the operations string
                      ƒ  cast as a function and call it

Example of translated code for input 1,2,3,4,5:

:5:4:3:2:1?+-*/ⁿ+-*/ⁿ+-*/ⁿ+-*/ⁿ+-*/ⁿ
\$\endgroup\$
2
  • 3
    \$\begingroup\$ Love the way the name of the language merges with the byte count \$\endgroup\$ Jun 13, 2016 at 11:38
  • 3
    \$\begingroup\$ s/Actually uses postfix notation/Actually actually uses postfix notation/ \$\endgroup\$
    – Leaky Nun
    Jun 13, 2016 at 12:54
6
\$\begingroup\$

Julia, 53 50 bytes

!x=(i=0;foldl((a,b)->(+,-,*,/,^)[i=i%5+1](a,b),x))

Try it online!

\$\endgroup\$
5
\$\begingroup\$

J, 40 bytes

^~`(%~)`*`(-~)`+/@(|.@,7#:~#&2)(5-5|4+#)

Finds the number of values needed to use a multiple of 5 operators, than pads with the identity values of those operators. In order, + is 0, - is 0, * is 1, % is 1, and ^ is 1, which can be a bit value 00111, or 7 in base 10. Then operates on that list while cycling through operators.

Usage

   f =: ^~`(%~)`*`(-~)`+/@(|.@,7#:~#&2)(5-5|4+#)
   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.36
   f 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
256
   f 1 0 1 0 1 0
1
   f _9 _8 _1
_16
   f 0 _3
_3
   f _99
_99

Explanation

^~`(%~)`*`(-~)`+/@(|.@,7#:~#&2)(5-5|4+#) Input: A
                                      #  Get length of A
                                    4+   Add four to it
                                  5|     Take it mod 5
                                5-       Find 5 minus its value, call it x
                           #&2           Create x copies of 2
                       7#:~              Convert 7 to base 2 and take the last x digits
                      ,                  Append those x digits to the end of A
                   |.@                   Reverse it, call it A'
^~                                       Power, reversed operators
    %~                                   Division, reversed operators
       *                                 Multiplication
         -~                              Subtraction, reversed operators
            +                            Addition
             /@                          Insert the previous operations, separated by `,
                                         into A' in order and cycle until the end
                                         Then evaluate the equation from right-to-left
                                         and return
\$\endgroup\$
5
\$\begingroup\$

Python 2, 81 67 64 bytes

i=10
for n in input():exec'r%s=n'%'*+-*/*'[i::5];i=-~i%5
print r

Input is an array of floats. Test it on Ideone.

How it works

'*+-*/*'[i::5] selects every fifth character of the string, starting with the one at index i, so this yields ** if i = 0, + if i = 1, - if i = 2, * if i = 3 and / if i = 4. Since the string has length 6, the expression will yield an empty string if i > 5.

We initialize the variable i to 10. For each number n in the input array, we construct the string r<op>=n, which exec executes.

Initially, i = 10, so <op> is the empty string, and it initializes r with r+=n. After each step, we increment i modulo 5 with i=-~i%5, so the next step will retrieve the proper operator.

When all input numbers has been processed, and we print r, which holds the desired output.

\$\endgroup\$
5
\$\begingroup\$

Matlab - 95 91 85 bytes / Octave - 81 bytes

Input is in such form: a = ['1' '2' '3' '4' '5'];, I hope this is covered by "string representing an array with integers/decimals", else there are 2 num2str needed additionally.

Every intermediate result gets printed to console because that saves me some semicolons. a(1) is executed so its value is then saved to ans. Also of course using ans in code is bad practice.

b='+-*/^'
a(1)
for i=2:length(a)
  ['(',ans,')',b(mod(i-2,5)+1),a(i)]
end
eval(ans)

In Octave, '+-*/^'(mod(i+2,5)+1) also works, which saves another 4 bytes, thanks Adám and Luis Mendo:

a(1)
for i=2:length(a)
  strcat('(',ans,')','+-*/^'(mod(i-2,5)+1),a(i))
end
eval(ans)

Changelog:

  • Removed spaces where possible
  • added Octave solution
  • replaced strcat() with []
\$\endgroup\$
4
  • \$\begingroup\$ Hi, welcome to PPCG! The input is fine like that, since it's still easily distinguishable what the input is. Hmm, I never used Matlab, so maybe I'm saying idiotic things here, but can't b = '+-*/^' be golfed to b='+-*/^' and for i = 2:length(a) to for i=2:length(a) (removing the spaces)? Also, perhaps Tips for golfing in MATLAB might be interesting for you. :) \$\endgroup\$ Jun 14, 2016 at 9:27
  • \$\begingroup\$ Is '+-*/^'(mod(i+2,5)+1) valid? \$\endgroup\$
    – Adám
    Jun 14, 2016 at 9:46
  • \$\begingroup\$ @Adám No, but it probably is in Octave \$\endgroup\$
    – Luis Mendo
    Jun 14, 2016 at 10:57
  • \$\begingroup\$ @Adám: it works in Octave, I added it. \$\endgroup\$
    – LimaKilo
    Jun 15, 2016 at 11:00
4
\$\begingroup\$

Mathematica, 67 66 65 bytes

Fold[{+##,#-#2,#2#,#/#2,If[#2==0,1,#^#2]}[[i++~Mod~5+1]]&,i=0;#]&

Simple Fold with a variable i holding the index.

\$\endgroup\$
1
  • \$\begingroup\$ A byte can be saved by +## instead of #+#2 \$\endgroup\$
    – LLlAMnYP
    Jun 13, 2016 at 13:57
4
\$\begingroup\$

CJam, 18 bytes

q~{"+-*/#"W):W=~}*

Input is an array of floats. Try it online!

How it works

q~                  Read and evaluate all input.
  {             }*  Reduce:
   "+-*/#"            Push the string of operators.
          W           Push W (initially -1).
           ):W        Increment and save in W.
              =       Retrieve the character at that index.
               ~      Evaluate.
\$\endgroup\$
4
\$\begingroup\$

R, 87 78 70 bytes

i=0
Reduce(function(a,j)get(substr("+-*/^",i<<-i%%5+1,i))(a,j),scan())

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ at some point I really need to learn how to use do.call...I probably shouldn't consider myself an R programmer until I do! \$\endgroup\$
    – Giuseppe
    Jul 19, 2018 at 16:18
  • 1
    \$\begingroup\$ @Giuseppe Advanced R by Hadley Wickam is a great beach read :) \$\endgroup\$
    – JayCe
    Jul 19, 2018 at 17:03
  • \$\begingroup\$ @Giuseppe thanks for pointing out do.call - made me realize I was looking for get. \$\endgroup\$
    – JayCe
    Jul 19, 2018 at 17:16
3
\$\begingroup\$

Haskell - 74

f(x:xs)=foldl(\x(o,y)->o x y)x(zip(cycle[(+),(-),(*),(/),flip(^).floor])xs)

Test cases:

λ> f[1,2,3,4,5] -> 0.0
λ> f[5,12,23,2,4,4,2,6,7] -> 539.0
λ> f[-8,50,3,3,-123,4,17,99,13] -> -1055.356943846277
λ> f [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2] -> 256.0

It could probably be shorter; Haskell's support for infinite lists and higher order functions make the direct solution quite pleasant, though. A version of ^ :: Double -> Double -> Double would be nicer for golfing, but I couldn't find one. Thankfully, I didn't need a full lambda, so pointless style shaved off a few bytes.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ You can prepend a single (+) to the list of operators and start the foldl with 0 to go completely pointfree and save the function name and parameters: foldl(\x(o,y)->o x y)0.zip((+):cycle[(+),(-),(*),(/),(**)]). \$\endgroup\$
    – nimi
    Jun 13, 2016 at 14:52
3
\$\begingroup\$

PowerShell v2+, 124 bytes

param($n)$o=$n[0];if($y=$n.count-1){1..$y|%{$o=if(($x=$i++%5)-4){"$o"+'+-*/'[$x]+$n[$_]|iex}else{[math]::pow($o,$n[$_])}}}$o

Long because PowerShell doesn't have a ^ or ** operator, so we have to account for a separate case and use a .NET call.

Takes input $n as an array, sets our output $o to be the first digit. We then check the .count of the array, and so long as it's greater than one we enter the if. Otherwise, we skip the if.

Inside the if we loop through the array 1..$y|%{...} and each iteration we re-set $o to a new value, the result of another if/else statement. So long as our counter $i++ isn't modulo-5 equal to 4 (i.e., we're not at the ^ operator), we simply take $o and concatenate it with the appropriate symbol '+-*/'[$x] and the next number in the input array $n[$_]. We pipe that to iex (alias for Invoke-Expression and similar to eval), and that gets re-saved to $o. If we're on the ^ operator, we're in the else, so we execute a [math]::Pow() call, and that result gets re-saved back into $o.

In either case, we simply output $o to the pipeline and exit, with output implicit.

\$\endgroup\$
3
\$\begingroup\$

Rust, 123, 117 bytes

Original answer:

fn a(v:&[f32])->f32{v.iter().skip(1).enumerate().fold(v[0],|s,(i,&x)|match i%5{0=>s+x,1=>s-x,2=>s*x,3=>s/x,_=>s.powf(x)})}

stupid long method names ^^ ahh much better

fn f(v:&[f32])->f32{v[1..].iter().zip(0..).fold(v[0],|s,(&x,i)|match i%5{0=>s+x,1=>s-x,2=>s*x,3=>s/x,_=>s.powf(x)})}

ungolfed

fn f(values : &[f32]) -> f32 {
    values[1..].iter().zip(0..)
    .fold(values[0], |state,(&x,i)|
        match i%5 {
            0=>state+x,
            1=>state-x,
            2=>state*x,
            3=>state/x,
            _=>state.powf(x)
        }
    )
}
\$\endgroup\$
3
\$\begingroup\$

Perl 6,  70 68 65  62 bytes

{$/=[(|(&[+],&[-],&[*],&[/],&[**])xx*)];.reduce: {$/.shift.($^a,$^b)}}
{(@_ Z |(&[+],&[-],&[*],&[/],&[**])xx*).flat.reduce: {&^b($^a,$^c)}}
{(@_ Z |(*+*,*-*,&[*],*/*,&[**])xx*).flat.reduce: {&^b($^a,$^c)}}
{reduce {&^b($^a,$^c)},flat @_ Z |(*+*,*-*,&[*],*/*,&[**])xx*}

Explanation:

-> *@_ {
  reduce
    -> $a, &b, $c { b($a,$c) },

    flat       # flatten list produced from zip
      zip
        @_,    # input

        slip(  # causes the list of operators to flatten into the xx list

          # list of 5 infix operators
          &infix:<+>, &infix:<->, &infix:<*>, &infix:</>, &infix:<**>

        ) xx * # repeat the list of operators infinitely
}

Technically * + * is a Whatever lambda, but is effectively the same as &[+] which is short for &infix:<+> the set of subroutines that handle infix numeric addition.
I didn't use that for multiplication or exponentiation as the ways to write them like that is at least as long as what I have (*×* or * * * and * ** *)

Test:

Test it on ideone.com
(after they upgrade to a Rakudo version that isn't from a year and a half before the official release of the Perl 6 spectests)

#! /usr/bin/env perl6

use v6.c;
use Test;

my @tests = (
  [1,2,3,4,5] => 0,
  [5,12,23,2,4,4,2,6,7] => 539,
  [-8,50,3,3,-123,4,17,99,13] => -1055.35694385, # -2982186493/2825761
  [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2] => 256,
  [1,0,1,0,1,0] => 1,
  [-9,-8,-1] => -16,
  [0,-3] => -3,
  [-99] => -99,
);

plan +@tests;

my &code = {reduce {&^b($^a,$^c)},flat @_ Z |(*+*,*-*,&[*],&[/],&[**])xx*}

for @tests -> $_ ( :key(@input), :value($expected) ) {
  is code(@input), $expected, .gist
}
1..8
ok 1 - [1 2 3 4 5] => 0
ok 2 - [5 12 23 2 4 4 2 6 7] => 539
ok 3 - [-8 50 3 3 -123 4 17 99 13] => -1055.35694385
ok 4 - [2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2] => 256
ok 5 - [1 0 1 0 1 0] => 1
ok 6 - [-9 -8 -1] => -16
ok 7 - [0 -3] => -3
ok 8 - [-99] => -99
\$\endgroup\$
1
  • \$\begingroup\$ 51 bytes \$\endgroup\$
    – Jo King
    Jan 8, 2019 at 0:29
3
\$\begingroup\$

Python 3, 88 93 bytes

f=lambda x:eval('('*(len(x)-1)+'){}'.join(map(str,x)).format(*['+','-','*','/','**']*len(x)))

It started off being much shorter but then operator precedence defeated me and I had to include lots of parenthesis...

\$\endgroup\$
0
3
\$\begingroup\$

Oracle PL/SQL, 275 254 Bytes

declare r number;begin for x in (select n,mod(rownum,5)r from t) loop if r is null then r:=x.n;elsif x.r=2then r:=r+x.n;elsif x.r=3then r:=r-x.n;elsif x.r=4then r:=r*x.n;elsif x.r=0then r:=r/x.n;else r:=r**x.n;end if;end loop;DBMS_OUTPUT.PUT_LINE(r);end;

The data must be inserted in a table called T with a column N of type NUMBER

Usage:

drop table t;
create table t (n number);
insert into t values (-8);
insert into t values (50);
insert into t values (3);
insert into t values (3);
insert into t values (-123);
insert into t values (4);
insert into t values (17);
insert into t values (99);
insert into t values (13);

declare r number;begin for x in (select n,mod(rownum,5)r from t) loop if r is null then r:=x.n;elsif x.r=2then r:=r+x.n;elsif x.r=3then r:=r-x.n;elsif x.r=4then r:=r*x.n;elsif x.r=0then r:=r/x.n;else r:=r**x.n;end if;end loop;DBMS_OUTPUT.PUT_LINE(r);end;

Output:

-1055,356943846277162152071601242992595623

275 Bytes version:

declare r number;cursor c is select n,mod(rownum,5) r from t;begin for x in c loop if r is null then r:=x.n;else case x.r when 2 then r:=r+x.n;when 3 then r:=r-x.n;when 4 then r:=r*x.n;when 0 then r:=r/x.n;else r:=r**x.n; end case;end if;end loop;DBMS_OUTPUT.PUT_LINE(r);end;
\$\endgroup\$
3
\$\begingroup\$

Java 8, 173 172 167 138 137 118 113 bytes

a->{double r=a[0],t;for(int i=1;i<a.length;r=new double[]{Math.pow(r,t),r+t,r-t,r*t,r/t}[i++%5])t=a[i];return r;}

Explanation:

Try it here.

a->{                     // Method with double-array parameter and double return-type
  double r=a[0],         //  Result-double, starting at the first item of the input
         t;              //  Temp double
  for(int i=1;           //  Index-integer, starting at the second item
      i<a.length;        //  Loop over the input-array
      r=new double[]{    //    After every iteration, change `r` to:
         Math.pow(r,t),  //      If `i%5` is 0: `r^t`
         r+t,            //      Else-if `i%5` is 1: `r+t`
         r-t,            //      Else-if `i%5` is 2: `r-t`
         r*t,            //      Else-if `i%5` is 3: `r*t`
         r/t}[i++%5])    //      Else-if `i%5` is 4: `r/t`
                         //      And increase `i` by 1 afterwards with `i++`
    t=a[i];              //   Change `t` to the next item in the array
  return r;}             //  Return result-double
\$\endgroup\$
11
  • 2
    \$\begingroup\$ Because, ya know, java.1.5 times longer than the current longest answer....wich is in SQL \$\endgroup\$
    – Bálint
    Jun 13, 2016 at 8:11
  • 1
    \$\begingroup\$ You can change double r=a[0]; to double r=a[0],b; to save some bytes. \$\endgroup\$
    – Leaky Nun
    Jun 13, 2016 at 8:58
  • 1
    \$\begingroup\$ @LeakyNun Originally I had float, but there isn't a Math.pow for floats, hence the double instead. Thanks for the ,b. And with i++<a.length I get an ArrayOutOfBoundsException at b=a[i]; (unless I do i++<a.length-1 instead, which is one byte longer instead of shorter). \$\endgroup\$ Jun 13, 2016 at 10:43
  • 1
    \$\begingroup\$ You can change == 4 to > 3 and == 0 to < 1. I'm not sure but I think you could save a bit by creating a variable for i % 5. \$\endgroup\$
    – Frozn
    Jun 13, 2016 at 14:11
  • 1
    \$\begingroup\$ I figured you can change the whole thing to a concatenation of ternaries. In all comparisons you can then use the <x trick, shrinking the whole function to 137 characters. \$\endgroup\$
    – Frozn
    Jun 13, 2016 at 14:28
3
\$\begingroup\$

A few tricks can reduce @Willmore´s approach by 23 to 174 bytes (requires php 5.6 or later). The most saving part is removing unneccessary parentheses (-10 bytes).

function f($a){while(count($a)>1){$l=array_shift($a);$r=array_shift($a);array_unshift($a,($j=$i++%5)?($j==1?$l-$r:($j==2?$l*$r:($j==3?$l/$r:$l**$r))):$l+$r);}return end($a);}

But using the ** operator instead of pow() also allows to use eval with an array for the operations; and with a few more tricks ...

PHP >= 5.6, 82 bytes

while(--$argc)eval('$x'.['/','**','+','-','*'][$i++?$i%5:2]."=$argv[$i];");echo$x;

takes list from command line parameters. Run with php -nr '<code>' or try it online.

old version, 161 157 151 145 144 140 137 117 bytes

function f($a){while(count($a)>1)eval('$a[0]=array_shift($a)'.['+','-','*','/','**'][$i++%5].'$a[0];');return$a[0];}

The most effective golfing came from writing the intermediate result directly to the first element - after shifting the previous result from the array.

breakdown

function f($a)
{
    while(count($a)>1)  // while array has more than one element ...
        eval('$a[0]='                           // future first element :=
            . 'array_shift($a)'                 // = old first element (removed)
            . ['+','-','*','/','**'][$i++%5]    // (operation)
            .'$a[0];'                           // new first element (after shift)
        );
    return$a[0];        // return last remaining element
}

test suite

$cases = array (
    0=>[1,2,3,4,5],
    539=>[5,12,23,2,4,4,2,6,7],
    '-1055.356...' => [-8,50,3,3,-123,4,17,99,13],
    256 => [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],
    1 => [1,0,1,0,1,0],
    -16 => [-9,-8,-1],
    -3 => [0, -3],
    -99 => [-99]
);
echo '<table border=1><tr><th>values</th><th>expected</th><th>actual result</th></tr>';
foreach ($cases as $expect=>$a)
{
    $result=f($a);
    echo "<tr><td>[", implode(',',$a),"]</td><td>$expect</td><td>$result</td></tr>";
}
echo '</table>';
\$\endgroup\$
3
  • \$\begingroup\$ Nicely done. You could remove 3 more bytes by returning the last value as an array (change 'return $a[0]' to 'return$a'), which I'm not seeing is specifically against the rules. :) \$\endgroup\$
    – 640KB
    Jan 7, 2019 at 19:22
  • \$\begingroup\$ @gwaugh Imo If the array contains just a single number, we return that as the result. is pretty clear. But thanks for letting me revisit this. \$\endgroup\$
    – Titus
    Jan 10, 2019 at 13:29
  • \$\begingroup\$ One could make a semantic argument that the "that" in the sentence can refer to "the array". Regardless, your answer is by far the shortest PHP. Very nicely done, and thx again for pointers on my longer submission. \$\endgroup\$
    – 640KB
    Jan 10, 2019 at 17:32
3
\$\begingroup\$

PHP, 135 130 bytes

Thanks @titus, -5 bytes, plus 0 case fix!

function f($z){return array_reduce($z,function($c,$x)use(&$i){eval('$c'.['/','**','+','-','*'][$i++?$i%5:5].'=$x;');return$c;});};

Try it online!

Less golfy:

function f( $t ) {
    return array_reduce( $t,
        function( $c, $x ) use( &$i ) {
            eval('$c'.['/','**','+','-','*'][$i++?$i%5:5].'=$x;');
            return $c;
        }
    );
};

Was really rooting for array_reduce() to work for this, but requires too many chars to beat the current lowest PHP score.

Posting it anyway in case anyone has any suggestions!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Nice approach; but I reckon it will fail whenever $c hits 0. Save two bytes with an anonymous function instead of w. eval('$c'.['/','**','+','-','*'][$i++?$i%5:5].'=$x');return$c; is six bytes shorter and should resolve the zero issue. \$\endgroup\$
    – Titus
    Jan 10, 2019 at 14:15
  • \$\begingroup\$ Thanks @Titus! You are absolutely right about the 0 case. I had to add back the ; after the =$x because eval wouldn't run without it. If I made it an anon function I'd have to have a variable assignment to it or run it within the test code, right? Wouldn't want to call the byte count into question. :D \$\endgroup\$
    – 640KB
    Jan 10, 2019 at 17:20
2
\$\begingroup\$

Brachylog, 68 bytes

hI,?bL,1:+:-:*:/:^b:L:I{bhv?t.|[O:L:I]h$(P,LbM,OhA,Lh:Ir:A&:M:Pr&.}.

That's long… but it uses no evaluation predicate.

Explanation

  • Main predicate

    hI,                                  Unify I with the first element of the input
       ?bL,                              L is the input minus the first element
           1:+:-:*:/:^b                  Construct the list of predicates [+:-:*:/:^]
                       :L:I{...}.        Call predicate 1 with [[+:-:*:/:^]:L:I] as input
    
  • Predicate 1

    bhv?t.                               If the second element of Input is empty (i.e. L),
                                         unify Output with the last element of Input
    |                                    Or
    [O:L:I]                              Input = [O:L:I]
           h$(P,                         P is O circularly permutated to the left
                LbM,                     M is L minus the first element
                    OhA,                 A is the first element of O
                        Lh:Ir:A&         Call predicate A on [I:First element of L]
                                :M:Pr&.  Call predicate 1 recursively with P:M:
    
\$\endgroup\$
1
  • \$\begingroup\$ Beat you by 1̶ ̶b̶y̶t̶e̶ 2 bytes ;) \$\endgroup\$ Jun 13, 2016 at 10:50
2
\$\begingroup\$

APL (Dyalog Unicode), 29 27 bytesSBCS

Anomymous tacit prefix function. Note that * is exponentiation in APL.

≢{⍎3↓⍕⌽⍵,¨⍨⍺⍴'+-×÷*',¨'⍨'}⊢

Try it online!

Because APL executes right to left, we can just reverse the order of arguments of the inserted operations and reverse the entire expression. Postfix reverses arguments. After doing a perfect shuffle of numbers and operations, we only just need to reverse, flatten, and evaluate:

≢{}⊢ call the following function with count of and actual numbers as and :

'⍨' this character

'+-×÷*',¨ prepend each of these characters to that; ["+⍨","-⍨","×⍨","÷⍨","*⍨"]

⍺⍴ use the left argument (count of numbers) to cyclically reshape that

 reverse

 format as flat string

3↓ drop leading 3 characters (a space and a symbol and )

 execute as APL code

\$\endgroup\$
2
\$\begingroup\$

Japt, 16 bytes

r@[XY]r"p+-*/"gZ

Try it online!

Explanation:

r@                  #Reduce the input list:
       "p+-*/"      # The list of functions to apply (offset by one due to the behavior of Z)
              gZ    # Choose the one at the current index, wrapping
  [  ]r             # Apply that function to:
   X                #  The result of the previous step
    Y               #  and the current number
                    #Implicitly return the result of the final step
\$\endgroup\$
1
  • \$\begingroup\$ Ah, feck, was just working on this myself, trying to figure out why it was giving me incorrect results - I'd missed the fecking exponentiation! :\ \$\endgroup\$
    – Shaggy
    Jan 10, 2019 at 17:40
2
\$\begingroup\$

x86-16 + 8087 FPU, 65 bytes

00000000: 9bdf 04ad 499b de04 ad49 e334 9bde 24ad  ....I....I.4..$.
00000010: 49e3 2d9b de0c ad49 e326 9bde 34ad 49e3  I.-....I.&..4.I.
00000020: 1fad 919b d9e8 85c9 7413 9c7f 02f7 d99b  ........t.......
00000030: d8c9 e2fb 9d7d 069b d9e8 9bd8 f191 e2c5  .....}..........
00000040: c3                                       .

Callable function: input array at DS:SI, length in CX. Output to ST top 8087 register stack.

Listing:

9B DF 04    FILD    WORD PTR [SI]   ; load first item to 8087 stack 
AD          LODSW 
49          DEC     CX 
                 
        CALC:
            ; Add 
9B DE 04    FIADD   WORD PTR [SI]   ; add 
AD          LODSW                   ; SI = next input 
49          DEC     CX              ; decrement counter 
E3 34       JCXZ    WOMI_DONE       ; exit if end of input array 
                 
            ; Subtract 
9B DE 24    FISUB   WORD PTR [SI]   ; subtract 
AD          LODSW                   ; SI = next input 
49          DEC     CX 
E3 2D       JCXZ    WOMI_DONE 
                 
            ; Multiply 
9B DE 0C    FIMUL   WORD PTR [SI]   ; multiply 
AD          LODSW                   ; SI = next input 
49          DEC     CX 
E3 26       JCXZ    WOMI_DONE 
                 
            ; Divide 
9B DE 34    FIDIV   WORD PTR [SI]   ; divide 
AD          LODSW                   ; SI = next input
49          DEC     CX 
E3 1F       JCXZ    WOMI_DONE 
                 
            ; Exponent 
AD          LODSW                   ; AX = exponent, SI = next input 
91          XCHG    AX, CX          ; CX = counter for loop (exponent), save CX 
9B D9 E8    FLD1                    ; load 1 into ST 
85 C9       TEST    CX, CX          ; is exponent pos, neg or 0? 
74 13       JZ      EXP_DONE        ; exit (with value 1) if exponent is 0 
9C          PUSHF                   ; save result flags for later 
7F 02       JG      EXP_REP         ; if exp > 1 start calculation 
F7 D9       NEG     CX              ; make exponent positive for loop 
        EXP_REP: 
9B D8 C9    FMUL    ST(0), ST(1)    ; multiply ST0 = ST0 * ST1 
E2 FB       LOOP    EXP_REP 
9D          POPF                    ; restore sign flag from earlier 
7D 06       JGE     EXP_DONE        ; if exponent was neg, divide 1 by result 
9B D9 E8    FLD1                    ; push 1 into numerator 
9B D8 F1    FDIV    ST(0), ST(1)    ; ST0 = 1 / ST1 
        EXP_DONE: 
91          XCHG    AX, CX          ; restore CX 
                 
E2 C5       LOOP    CALC            ; if more input, start again 
             
        WOMI_DONE: 
C3          RET 

Sample Output:

enter image description here

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This is great! I've written a similar solution for x86-64 (linux) but I haven't golfed it much yet which will probably change a lot of the logic around. For your exponent calculation, even though the tests given don't test receiving a negative exponent, I felt that it was a necessary part of the program logic, especially since it's as simple as pushing 1 to st0 and then doing a div between st0 and st1 (at least on x86 this is two instructions). \$\endgroup\$
    – davey
    Jan 9, 2019 at 10:42
  • \$\begingroup\$ Thanks @davey -- very good point! I've updated the code to handle negative exponents and added another test case for it. \$\endgroup\$
    – 640KB
    Jan 9, 2019 at 15:40
1
\$\begingroup\$

c#, 238, 202 bytes

double d(double[]a){Array.Reverse(a);var s=new Stack<double>(a);int i=0,j;while(s.Count>1){double l=s.Pop(),r=s.Pop();j=i++%5;s.Push(j==0?l+r:j==1?l-r:j==2?l*r:j==3?l/r:Math.Pow(l,r));}return s.Peek();}

I didn't see any c# solution so I will give one. This is my first codegolf. I started writing in c# "two months ago" (though I know Java to some extent).

It uses Stack

Try online!

Ungolfed and test cases

using System;
using System.Collections.Generic;

class M 
{
    double d(double[]a) {
        Array.Reverse(a);
        var s = new Stack<double>(a);
        int i=0,j;
        while (s.Count>1)
        {
            double l=s.Pop(),r=s.Pop();
            j=i++%5;
            s.Push(j==0?l+r:j==1?l-r:j==2?l*r:j==3?l/r:Math.Pow(l, r));
        }
        return s.Peek();
    }

    public static void Main()
    {
        int[][] a = new int[][]{
            new int[]{1,2,3,4,5},
            new int[]{5,12,23,2,4,4,2,6,7},
            new int[]{-8,50,3,3,-123,4,17,99,13},
            new int[]{2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
            new int[]{1,0,1,0,1,0},
            new int[]{-9,-8,-1},
            new int[]{0,-3},
            new int[]{-99}
        };

        for (int i = 0; i < a.Length; i++)
        {
            Console.WriteLine(new M().d(Array.ConvertAll(a[i], e => Convert.ToDouble(e))));
        }
        Console.ReadKey();
    }
}

Output:

0
539
-1055,35694384628
256
1
-16
-3
-99
\$\endgroup\$
2
  • \$\begingroup\$ Hi, and welcome to PPCG! This might be a nice topic to look at: Tips for code-golfing in C#. Some things that can be golfed down in your code: spaces (a, Double.Parse -> a,Double.Parse; while (s.Count -> while(s.Count; Pow(l, r) -> Pow(l,r)). Also, you can remove int in front of the j= and put it behind the int i=0,j;. Great first answer though, and once again welcome. :) \$\endgroup\$ Jun 16, 2016 at 7:36
  • \$\begingroup\$ @KevinCruijssen Hi! Ty! Spaces removed and j moved as you suggested :) \$\endgroup\$ Jun 16, 2016 at 7:52
1
\$\begingroup\$

PHP, 206,198,197 bytes

function f($a){while(count($a)>1){$l=array_shift($a);$r=array_shift($a);array_unshift($a,($j=$i++%5)==0?($l+$r):($j==1?($l-$r):($j==2?($l*$r):($j==3?($l/$r):(pow($l,$r))))));}return array_pop($a);}

Try online!

Ungolfed

<?php
 
function f($a)
{
    while(count($a)>1)
    {
        $l = array_shift($a); $r = array_shift($a);
        array_unshift($a,($j=$i++%5)==0?($l+$r):($j==1?($l-$r):($j==2?($l*$r):($j==3?($l/$r):(pow($l,$r))))));
    }
    return array_pop($a);
}
 
echo f([1,2,3,4,5])."\n";
echo f([5,12,23,2,4,4,2,6,7])."\n";
echo f([-8,50,3,3,-123,4,17,99,13])."\n";
echo f([2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2])."\n";
echo f([1,0,1,0,1,0])."\n";
echo f([-9,-8,-1])."\n";
echo f([0,-3])."\n";
echo f([-99])."\n";

In PHP, logic similar to my c# answer (202 bytes) :) .

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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