## Rules

1. No cell range references (A2:B3).

2. Maximum 9 rows and 9 columns.

3. No circular references or formula errors.

4. Empty cells evaluate to 0.

5. Data are numbers only, but may be taken as strings.

6. Formulas are strings.

## Implementation choices

You must state your choices in these matters:

1. Require formulas to be prefixed with any single character, e.g. = – or not.

2. The leftmost cell of the second row is A2 or R2C1, as per the two conventions used by Excel et al.

3. Require any single-character pre- or suffix in cell references, e.g. $ – or not. 4. One of null, empty string, empty list, etc., (but not 0) to represent empty cells. 5. Language of your submission (spreadsheet managers are not allowed). 6. Language for the formulas (may differ from the above).* 7. Brownie points or cookies for explaining your solution. ## Examples Choices: 7: =; 8: A2; 9: none; 10: ""; 12: Excel Formula Language ### In: [[ 2, 3], ["=A1+B1",""]]  ### Out: [[2,3], [5,0]]  ### In: [[ 2,"=A1+B2"], ["=A1+B1", ""]]  ### Out: [[2,2], [4,0]]  ### In: [[ 3, 4,"=A1*B1"], [ 2, 5,"=A2*B2"], ["","","=C1+C2"]]  ### Out: [[3,4,12], [2,5,10], [0,0,22]]  ### In: [["","=2*B2*B3" ,""], [ 3,"=A1+(A2+C2)/2", 2], [ 1,"=C1+(A3+C3)/2", 5]]  ### Out: [[0,15, 0], [3, 2.5,2], [1, 3 ,5]]  * The formula language must be PPCG admissible, but you only have to support cell references plus criteria 3 and 4 there, wiz. addition and primeness determination. • Is submitted an answer in Excel/VBA disallowed? Expand array to cells, evaluate. Commented Apr 6, 2017 at 17:15 • @carusocomputing If you are not just letting Excel do its thing, then feel free to post. – Adám Commented Apr 7, 2017 at 5:08 • Can we have cells be zero-based? As in, R0C0? Commented Apr 7, 2017 at 15:57 • @ConorO'Brien No, it has to be one of the two conventions used by Excel et al. – Adám Commented Apr 9, 2017 at 4:42 ## 6 Answers # JavaScript, 125112 105 bytes To use, add f= at the beginning and invoke like f(argument). a=>a.map(b=>b.map(p=>+p?p:p?eval(p.replace(/[A-I][1-9]/g,m=>a[${m[1]-1}][${(m.charCodeAt(0)-65)}])):0))  ### Choices: 1. Does not require =. 2. The left most cell of second row is A2. 3. Does not require any prefix or suffix. 4. "" (Empty String) to denote empty cell. 5. JavaScript. 6. JavaScript. 7. Cookies. 🍪🍪🍪 ### Explanation: This solution iterates over all the cells of the worksheet (each element of the sub-arrays of the given array) and if non-empty String is found, replaces its cell references with the corresponding references in terms of the given array and evaluates the expression with eval() (yeah, that evil thing that haunts you in your nightmares). This solution assumes that the constants provided in the input array are of Integer type. ### Test Cases f=a=>a.map(b=>b.map(p=>+p?p:p?eval(p.replace(/[A-I][1-9]/g,m=>a[${m[1]-1}][${(m.charCodeAt(0)-65)}])):0)) console.log(f([[1,2,3],["A1+B1+C1",10,11]])); console.log(f([[1,2,5,4,6,89,0],[0,1,2,3,"A2+A1",5,6]])); console.log(f([[1,2,4,5],["A1/B1*C1+A1+Math.pow(5,B1)",2,3,4]])); • Very nice. Here: 🍪. – Adám Commented Mar 27, 2017 at 13:51 • Any reason you can't use /\w\d/g for your regex? Commented Mar 27, 2017 at 18:23 • @powelles \w matches digits too, and \d matches 0 too, both things you don't want in this case. /[A-I][1-9]/g should work though Commented Mar 27, 2017 at 18:44 • @LarsW /\w\d/g produces the exact same results in the test cases. Also using a template literal in the eval portion could save a handful of bytes. Commented Mar 27, 2017 at 19:55 • @powelles yes, but the test cases may be incomplete. Anyway, I assumed the chosen rules need to be followed; but they may just be input restrictions (or both), so that can be the problem too Commented Mar 27, 2017 at 20:01 # PHP, 265 263 259 258 257 240 224 222 213 202 196 bytes function f(&$a){array_walk_recursive($a,$p=function(&$c)use($a,&$p){eval('$c='.preg_replace_callback("#R(.)C(.)#",function($m)use($a,&$p){$d=$a[$m[1]-1][$m[2]-1];$p($d);return$d;},$c?:0).';');});}  or function f(&$a){array_walk_recursive($a,$p=function(&$c)use($a,&$p){eval('$c='.preg_replace_callback("#R(.)C(.)#",function($m)use($a,&$p){return$p($a[$m[1]-1][$m[2]-1]);},$c?:0).';');return$c;});}  operates on input: call by reference. Test it online. • no expression prefix • reference format R2C1, no prefix • anything falsy for empty cell • evaluates any (lowercase) PHP expression, including all arithmetics breakdown (first version) function f(&$a)
{
array_walk_recursive($a, # walk through elements ...$p=function(&$c)use($a,&$p){ # use array$a and recursive $p eval('$c='.                             # 3. evaluate expression
preg_replace_callback('#R(.)C(.)#', # 2. replace references with ...
function($m)use($a,&$p){$d=$a[$m[1]-1][$m[2]-1]; #$d=content of referenced cell
$p($d);                             # recursive evaluation
return$d; # return$d
},$c?:0) # 1. replace empty with 0 .';' ); } ); }  • +1 Very nice; 🍪. You say standard arithmetics, but really any reasonable PHP expression would work, no? – Adám Commented Mar 27, 2017 at 12:46 • @Adám Now that you mention it ... as long as it´s lowercase, yes. Though max(range(A1,A3)) might be confusing. :D Commented Mar 27, 2017 at 16:15 • Nice golf took me quite long to find anything: $d=$c;preg_match($x="#[A-Z](.)#",$c=$c[0] to preg_match($x="#[A-Z](.)#",$c=($d=$c)[0] should save 1 byte. Commented Mar 28, 2017 at 7:42
• Would it be possible to include a Try it online! link?
Commented Mar 28, 2017 at 8:22
• @Christoph took me a new approach to fix the second example ... and saved a lot in the process ... plus further golfing Commented Mar 28, 2017 at 14:23

## Clojure, 263 281 bytes

Oh damn without that apply map vector the result is in transpose, as A2 is alphabetically before B1.

#(apply map vector(partition(count(% 1))(for[v(vals(loop[C(into{}(mapcat(fn[i r](map(fn[j v][(str j i)(or v"0")])"ABCDEFGHI"r))(rest(range))%))P[]](if(= C P)C(recur(into(sorted-map)(for[[k v]C][k(reduce(fn[r[K V]](clojure.string/replace r K V))v C)]))C))))](eval(read-string v)))))


Examples:

(def f #(...))

(f [["2" "3"]["(+ A1 B1)" nil]])
([2 3] [5 0])

(f [[nil ,"(* 2 B2 B3)"                ,nil],
["3" ,"(+ A1 (/ (+ A2 C2) 2))"     ,"2"],
["1" ,"(-> A3 (+ C3) (/ 2) (+ C1))","5"]])
([0 15N 0] [3 5/2 2] [1 3 5])

1. Formulas are S-expressions
2. A2
3. No, (+ A1 A2) is fine
4. nil and false work as empty cells, but empty string do not
5. Clojure
6. S-expressions (Clojure + any built-in macros)

An example of thread first macro:

(macroexpand '(-> A3 (+ C3) (/ 2) (+ C1)))
(+ (/ (+ A3 C3) 2) C1)


Starting value of C in the loop is a hash-map, keys are cell names and values are original values. Then all cell references are replaced by contents of referenced cells until we have converged (Previous = Current), then cells are evaluated and the flat structure is partitioned back into a nested list.

Would be cool to find a solution where A1, A2 etc. are actually callable functions, then (* 2 B2 B3) could be rewritten to (* 2 (B2) (B3)) and executed.

Try it online!

## Mathematica, 119115 95 bytes

(m=#/.""->0)//.s_String:>ToExpression@StringReplace[s,"R"~~x_~~"C"~~y_:>"m[["<>{x,",",y,"]]"}]&


Choices:

1. No prefix.
2. R2C1 style.
3. No prefix or suffix.
4. "" for empty cells.
5. Mathematica.
6. Mathematica. Arbitrary arithmetic expressions that don't use variables of the form RxCy and don't have side effects should work.

### Explanation

(m=#/.""->0)


We start by replacing all empty strings in the input (#) with zeros and storing the result in m, because we'll need this again in another place.

...//.s_String:>...


Repeatedly replace any remaining string s with the following...

...StringReplace[s,"R"~~x_~~"C"~~y_:>...]


Match any substrings of the form RxCy in s and replace them with...

..."m[["<>{x,",",y,"]]"}


Which gives m[[x,y]], which uses x and y as indices into the matrix m.

...ToExpression@...


Finallz, evaluate this string as a Mathematica expression.

• Cool. I thought that it would take a little longer than that... Any way to try this?
Commented Mar 27, 2017 at 9:47
• @Adám Unfortunately, it doesn't seem to work in Mathics, so without a copy of Mathematica, probably not. Commented Mar 27, 2017 at 9:51
• Still waiting for the builtin...
– YSC
Commented Mar 27, 2017 at 14:22
• @YSC Excel, 0 bytes.
Commented Mar 27, 2017 at 14:57
• @Adám That would not be competing per the rules of this challenge. Also, I think Martin deserves a cookie. Commented Apr 5, 2017 at 13:02

# APL (Dyalog), 51 bytes

⍎¨({((⍴⍵)↑⍉⎕A∘.,1↓⎕D),¨'←',¨⍵}{0::⍵⋄×≢⍵:⍕⍎⍕⍵⋄0}¨)⍣≡

1. None

2. A2

3. None

4. Empty string

5. APL

6. APL

Try it online!

⍎¨ Evaluate each cell of the result from

()⍣≡ continuous application of the following two functions until nothing more changes

{ first anonymous function to be applied…

0 on any
:: error:
⍵ return the argument unmodified

⋄ now try;

⍵ if the argument's
≢ tally:
× is positive
: then:
⍕ stringify
⍎ the evaluated
⍕ stringified
⍵ argument

⋄ else;

0 return zero

}¨ … to each cell

{ second anonymous function to be applied…

'←',¨ prepend an assignment arrow to each cell of
⍵ the argument

(),¨ prepend the following to each cell of that

1↓ drop the first of
⎕D the string of all Digits (i.e. zero)

⎕A With all the letters of the Alphabet going down,
∘., make a concatenation table (with the remaining digits going right)

⍉ transpose (to get increasing numbers down, progressing letters right)

()↑ take the upper left submatrix with the size of…

⍴ the size of
⍵ the argument

} … to the the previous function's result.

• Your explanations are always beautiful, thanks, makes me want to learn APL beyond what little I know from reading these answers. Commented Apr 6, 2017 at 17:12
• @carusocomputing Thank you. I'll be happy to assist you. Feel free to questions and requests in the APL chat room. I'll help you get set up too if you need that.
Commented Apr 7, 2017 at 5:07

# Python 2273,265,263, 259 bytes

import re
def g(m):x=m.group();return's[%d][%d]'%(int(x[1])-1,ord(x[0])-65)
e=enumerate
while'='ins:
for x,i in e(s):
for i,j in e(i):
try:s[x][i]=0if not j else float(eval(re.sub('\w\d',g,str(j)).strip('=')))
except:pass


Try it online!

Choices:

1. =

2. A2

3. none

4. ""

5. Python 2.7

6. Python expressions

Basic explanation:

For every formula in the sublist, substitute it with the corresponding list (that is, for B1 s[0][1]) index and evaluate the result!

• -4 bytes by changing str() to backticks!
• You didn't add import of re in your answer. Also it doesn't pass this input: s=[[ 3, 4,"max(A1,B1)"],[ 2, 5,"A2**B2"],[ "", "","C1+C2"]] Commented Mar 28, 2017 at 7:50
• The input format is [[ 3, 4,"=max(A1,B1)"],[ 2, 5,"=A2**B2"],[ "", "","=C1+C2"]] That is there as a part of headers! Check it on the try it online link! Commented Mar 28, 2017 at 7:54
• It should be included in byte count. Just check out other python answers on this site Commented Mar 28, 2017 at 7:57
• Is it? I'm net to codeglof. Thanks for the comment. Will add it. Commented Mar 28, 2017 at 7:57
• As far as the other answers are considered, they havent included the input! I've edit with the bye count of import! Commented Mar 28, 2017 at 7:58