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:
#[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);
}