Untitled

 avatar
unknown
plain_text
a month ago
2.4 kB
8
Indexable
package main

import (
	"strconv"
	"strings"
)

type Cell struct {
	r, c int
}

type Formula struct {
	present bool
	counts  map[Cell]int
	effects map[Cell]bool
}

type Excel struct {
	h, w   int
	m      [][]int
	formula [][]Formula
}

func Constructor(height int, width byte) Excel {
	w := int(width-'A') + 1

	m := make([][]int, height)
	f := make([][]Formula, height)

	for i := 0; i < height; i++ {
		m[i] = make([]int, w)
		f[i] = make([]Formula, w)

		for j := 0; j < w; j++ {
			f[i][j] = Formula{
				counts:  map[Cell]int{},
				effects: map[Cell]bool{},
			}
		}
	}

	return Excel{height, w, m, f}
}

func (e *Excel) dfs(r, c int, vis [][]bool, st *[]Cell) {
	vis[r][c] = true

	for next := range e.formula[r][c].effects {
		if !vis[next.r][next.c] {
			e.dfs(next.r, next.c, vis, st)
		}
	}

	*st = append(*st, Cell{r, c})
}

func (e *Excel) compute(r, c int) {
	f := e.formula[r][c]

	if !f.present {
		return
	}

	sum := 0

	for cell, count := range f.counts {
		sum += e.m[cell.r][cell.c] * count
	}

	e.m[r][c] = sum
}

func (e *Excel) topo(r, c int) {
	vis := make([][]bool, e.h)

	for i := range vis {
		vis[i] = make([]bool, e.w)
	}

	st := []Cell{}

	e.dfs(r, c, vis, &st)

	for len(st) > 0 {
		last := st[len(st)-1]
		st = st[:len(st)-1]

		e.compute(last.r, last.c)
	}
}

func (e *Excel) Set(row int, column byte, val int) {
	r := row - 1
	c := int(column - 'A')

	e.m[r][c] = val

	e.formula[r][c].present = false
	e.formula[r][c].counts = map[Cell]int{}

	e.topo(r, c)
}

func (e *Excel) Get(row int, column byte) int {
	return e.m[row-1][int(column-'A')]
}

func (e *Excel) Sum(row int, column byte, numbers []string) int {
	r := row - 1
	c := int(column - 'A')

	f := &e.formula[r][c]

	f.present = true
	f.counts = map[Cell]int{}

	for _, s := range numbers {

		if !strings.Contains(s, ":") {

			col := int(s[0] - 'A')
			rowNum, _ := strconv.Atoi(s[1:])
			rowNum--

			cell := Cell{rowNum, col}

			f.counts[cell]++
			e.formula[rowNum][col].effects[Cell{r, c}] = true

		} else {

			parts := strings.Split(s, ":")

			s1 := parts[0]
			s2 := parts[1]

			c1 := int(s1[0] - 'A')
			r1, _ := strconv.Atoi(s1[1:])
			r1--

			c2 := int(s2[0] - 'A')
			r2, _ := strconv.Atoi(s2[1:])
			r2--

			for i := r1; i <= r2; i++ {
				for j := c1; j <= c2; j++ {

					cell := Cell{i, j}

					f.counts[cell]++
					e.formula[i][j].effects[Cell{r, c}] = true
				}
			}
		}
	}

	e.topo(r, c)

	return e.m[r][c]
}
Editor is loading...
Leave a Comment