GuilinDev

Lc0631

05 August 2008

631. Design Excel Sum Formula

设计基本的excel功能

Brute-Force

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class Excel {
    class Value {
        int val;
        String[] numbers;
        boolean isFormulae;

        Value(int val) {
            this.val = val;
            isFormulae = false;
        }

        Value(String[] numbers) {
            this.numbers = numbers;
            isFormulae = true;
        }

        int getValue(Value[][] mat) {
            if (!isFormulae) {
                return val;
            } else {
                int sum = 0;
                for (String s : numbers) {
                    String splittedNumbers[] = s.split(":");
                    if (splittedNumbers.length == 1) {
                        int row = getRow(splittedNumbers[0]), col = splittedNumbers[0].charAt(0) - 'A';
                        sum += mat[row][col].getValue(mat);
                    } else {
                        int r1 = getRow(splittedNumbers[0]), c1 = splittedNumbers[0].charAt(0) - 'A';
                        int r2 = getRow(splittedNumbers[1]), c2 = splittedNumbers[1].charAt(0) - 'A';
                        for (int i = r1; i <= r2; i++) {
                            for (int j = c1; j <= c2; j++) {
                                sum += mat[i][j].getValue(mat);
                            }
                        }
                    }
                }
                return sum;
            }
        }

        private int getRow(String s) {
            int row = 0;
            for (int i = 1; i < s.length(); i++) {
                row = row * 10 + (s.charAt(i) - '0');
            }
            return row;
        }
    }

    Value[][] mat;

    public Excel(int height, char width) {
        mat = new Value[height + 1][width - 'A' + 1];
        for (int i = 1; i <= height; i++) {
            for (int j = 0; j < width - 'A'; j++) {
                mat[i][j] = new Value(0);
            }
        }
    }

    public void set(int row, char column, int val) {
        mat[row][column - 'A'] = new Value(val);
    }

    public int get(int row, char column) {
        return mat[row][column - 'A'].getValue(mat);
    }

    public int sum(int row, char column, String[] numbers) {
        mat[row][column - 'A'] = new Value(numbers);
        return get(row, column);
    }
}

/**
 * Your Excel object will be instantiated and called as such:
 * Excel obj = new Excel(height, width);
 * obj.set(row,column,val);
 * int param_2 = obj.get(row,column);
 * int param_3 = obj.sum(row,column,numbers);
 */

观察者模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
class Excel {
    private Cell[][] sheet;

    public Excel(int height, char width) {
        sheet = new Cell[height][width - 'A' + 1];
    }

    public void set(int row, char column, int val) {
        getCell(row - 1, column - 'A').setValue(val);
    }

    public int get(int row, char column) {
        return getCell(row - 1, column - 'A').getValue();
    }

    public int sum(int row, char column, String[] numbers) {
        getCell(row - 1, column - 'A').setFormula(numbers);
        return getCell(row - 1, column - 'A').getValue();
    }

    private Cell getCell(int row, int col) {
        if (sheet[row][col] == null) {
            sheet[row][col] = new Cell();
        }
        return sheet[row][col];
    }

    private int[] parse(String s) {
        int[] result = new int[2];
        result[0] = Integer.parseInt(s.substring(1, s.length())) - 1;
        result[1] = s.charAt(0) - 'A';
        return result;
    }

    private List<Cell> parseRange(String s) {
        int[] left = parse(s.split(":")[0]);
        int[] right = parse(s.split(":")[1]);
        List<Cell> result = new ArrayList<>();
        for (int i = left[0]; i <= right[0]; i++) {
            for (int j = left[1]; j <= right[1]; j++) {
                result.add(getCell(i, j));
            }
        }
        return result;
    }

    class Cell {
        int value = 0;
        //Maintained by Observer
        Map<Cell, Integer> observables = new HashMap<>();
        //Maintained by Observables
        Set<Cell> observers = new HashSet<>();

        void setValue(int value) {
            unRegister();
            int oldValue = this.value;
            this.value = value;
            for (Cell cell : observers) {
                cell.notify(this, value - oldValue);
            }
        }

        int getValue() {
            return value;
        }

        void setFormula(String[] numbers) {
            unRegister();
            List<Cell> observables = new ArrayList<>();
            for (String s : numbers) {
                if (!s.contains(":")) {
                    int[] cellPos = parse(s);
                    observables.add(getCell(cellPos[0], cellPos[1]));
                } else {
                    observables.addAll(parseRange(s));
                }
            }
            register(observables);
            int oldValue = this.value;
            computeValue();
            for (Cell cell : observers) {
                cell.notify(this, value - oldValue);
            }
        }

        private void computeValue() {
            value = 0;
            for (Map.Entry<Cell, Integer> entry : observables.entrySet()) {
                value += (entry.getKey().getValue() * entry.getValue());
            }
        }

        //Called by Observable.
        void notify(Cell cell, int valueChange) {
            int oldValue = value;
            value += (valueChange * observables.get(cell));
            for (Cell cell1 : observers) {
                cell1.notify(this, value - oldValue);
            }
        }

        //Unregistered by Observer
        void unRegister() {
            for (Cell cell : observables.keySet()) {
                cell.observers.remove(this);
            }
            observables.clear();
        }

        //Registered by Observer
        void register(List<Cell> _observables) {
            for (Cell cell : _observables) {
                cell.observers.add(this);
                observables.put(cell, observables.getOrDefault(cell, 0) + 1);
            }
        }

    }
}