## 631. Design Excel Sum Formula

Your task is to design the basic function of Excel and implement the function of sum formula. Specifically, you need to implement the following functions:

`Excel(int H, char W):` This is the constructor. The inputs represents the height and width of the Excel form. H is a positive integer, range from 1 to 26. It represents the height. W is a character range from 'A' to 'Z'. It represents that the width is the number of characters from 'A' to W. The Excel form content is represented by a height * width 2D integer array `C`, it should be initialized to zero. You should assume that the first row of `C` starts from 1, and the first column of `C` starts from 'A'.

`void Set(int row, char column, int val):` Change the value at `C(row, column)` to be val.

`int Get(int row, char column):` Return the value at `C(row, column)`.

`int Sum(int row, char column, List of Strings : numbers):` This function calculate and set the value at `C(row, column)`, where the value should be the sum of cells represented by `numbers`. This function return the sum result at `C(row, column)`. This sum formula should exist until this cell is overlapped by another value or another sum formula.

`numbers` is a list of strings that each string represent a cell or a range of cells. If the string represent a single cell, then it has the following format : `ColRow`. For example, "F7" represents the cell at (7, F).

If the string represent a range of cells, then it has the following format : `ColRow1:ColRow2`. The range will always be a rectangle, and ColRow1 represent the position of the top-left cell, and ColRow2 represents the position of the bottom-right cell.

Example 1:

```Excel(3,"C");
// construct a 3*3 2D array with all zero.
//   A B C
// 1 0 0 0
// 2 0 0 0
// 3 0 0 0

Set(1, "A", 2);
// set C(1,"A") to be 2.
//   A B C
// 1 2 0 0
// 2 0 0 0
// 3 0 0 0

Sum(3, "C", ["A1", "A1:B2"]);
// set C(3,"C") to be the sum of value at C(1,"A") and the values sum of the rectangle range whose top-left cell is C(1,"A") and bottom-right cell is C(2,"B"). Return 4.
//   A B C
// 1 2 0 0
// 2 0 0 0
// 3 0 0 4

Set(2, "B", 2);
// set C(2,"B") to be 2. Note C(3, "C") should also be changed.
//   A B C
// 1 2 0 0
// 2 0 2 0
// 3 0 0 6
```

Note:

1. You could assume that there won't be any circular sum reference. For example, A1 = sum(B1) and B1 = sum(A1).
2. The test cases are using double-quotes to represent a character.
3. Please remember to RESET your class variables declared in class Excel, as static/class variables are persisted across multiple test cases. Please see here for more details.

## Rust Solution

``````#[derive(Debug, Clone)]
enum Cell {
Value(i32),
Sum(Vec<(usize, usize)>),
}
struct Excel {
mat: Vec<Vec<Cell>>,
}

impl Excel {
fn new(h: i32, w: char) -> Self {
let n = h as usize;
let m = (w as u8 - b'A' + 1) as usize;
let mat = vec![vec![Cell::Value(0); m]; n];
Excel { mat }
}

fn set(&mut self, r: i32, c: char, v: i32) {
let i = Self::row(r);
let j = Self::col(c);
self.mat[i][j] = Cell::Value(v);
}

fn get(&self, r: i32, c: char) -> i32 {
let i = Self::row(r);
let j = Self::col(c);
self.get_by_index(i, j)
}

fn get_by_index(&self, i: usize, j: usize) -> i32 {
match &self.mat[i][j] {
Cell::Value(v) => *v,
Cell::Sum(nums) => nums.iter().map(|&(i, j)| self.get_by_index(i, j)).sum(),
}
}

fn sum(&mut self, r: i32, c: char, strs: Vec<String>) -> i32 {
let i = Self::row(r);
let j = Self::col(c);
let mut nums = vec![];
for s in strs {
let parts: Vec<&str> = s.split(':').collect();
if parts.len() == 1 {
nums.push(Self::cell(parts[0]));
} else {
let top_left = Self::cell(parts[0]);
let bottom_right = Self::cell(parts[1]);
for i in top_left.0..=bottom_right.0 {
for j in top_left.1..=bottom_right.1 {
nums.push((i, j));
}
}
}
}
self.mat[i][j] = Cell::Sum(nums);
self.get_by_index(i, j)
}

fn row(r: i32) -> usize {
(r - 1) as usize
}

fn col(c: char) -> usize {
(c as u8 - b'A') as usize
}

fn cell(s: &str) -> (usize, usize) {
let mut col = 0;
let mut row = 0;
for (i, c) in s.char_indices() {
if i == 0 {
col = (c as u8 - b'A') as usize;
} else {
row *= 10;
row += (c as u8 - b'0') as usize;
}
}
row -= 1;
(row, col)
}
}

#[test]
fn test() {
let mut obj = Excel::new(3, 'C');
obj.set(1, 'A', 2);
assert_eq!(obj.get(1, 'A'), 2);
assert_eq!(obj.sum(3, 'C', vec_string!["A1", "A1:B2"]), 4);
obj.set(2, 'B', 2);
assert_eq!(obj.get(3, 'C'), 6);
}
``````

Having problems with this solution? Click here to submit an issue on github.