package main
import (
	"bufio"
	"log"
	"os"
	"regexp"
	"strconv"
	"strings"
)
type cuboid struct {
	state      string
	xmin, xmax int
	ymin, ymax int
	zmin, zmax int
}
func main() {
	if err := myMain(); err != nil {
		log.Println(err)
	}
}
func myMain() error {
	cbs, err := parseInput("input.txt")
	if err != nil {
		return err
	}
	log.Println(solveFirst(cbs))
	log.Println(solveSecond(cbs))
	return nil
}
type point struct {
	x, y, z int
}
func solveFirst(cbs []cuboid) int {
	const (
		rangeMin = -50
		rangeMax = 50
	)
	m := map[point]struct{}{}
	for _, cb := range cbs {
		for x := max(cb.xmin, rangeMin); x <= min(cb.xmax, rangeMax); x++ {
			for y := max(cb.ymin, rangeMin); y <= min(cb.ymax, rangeMax); y++ {
				for z := max(cb.zmin, rangeMin); z <= min(cb.zmax, rangeMax); z++ {
										switch cb.state {
					case "on":
						m[point{x, y, z}] = struct{}{}
					case "off":
						delete(m, point{x, y, z})
					default:
						log.Panicln("no such state")
					}
				}
			}
		}
	}
	return len(m)
}
type subcubes map[cuboid]int
func solveSecond(cbs []cuboid) int {
	m := subcubes{}
	for _, cube := range cbs {
		subMap := subcubes{}
		for orig := range m {
			ovrlp := overlap(cube, orig)
			if ovrlp.state == "noop" {
				continue
			}
																		subMap[ovrlp] -= m[orig]
		}
		if cube.state == "on" {
			subMap[cube] += 1
		}
		for c := range subMap {
			m[c] += subMap[c]
		}
	}
	var sum int
	for cube, v := range m {
		sum += cube.size() * v
	}
	return sum
}
func (c cuboid) size() int {
	return (c.xmax - c.xmin + 1) * (c.ymax - c.ymin + 1) * (c.zmax - c.zmin + 1)
}
func overlap(first, second cuboid) cuboid {
		if first.xmax < second.xmin || second.xmax < first.xmin ||
		first.ymax < second.ymin || second.ymax < first.ymin ||
		first.zmax < second.zmin || second.zmax < first.zmin {
		return cuboid{state: "noop"}
	}
	return cuboid{"",
		max(first.xmin, second.xmin), min(first.xmax, second.xmax),
		max(first.ymin, second.ymin), min(first.ymax, second.ymax),
		max(first.zmin, second.zmin), min(first.zmax, second.zmax),
	}
}
func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}
func parseInput(fileName string) ([]cuboid, error) {
	ret := []cuboid{}
	fd, err := os.Open(fileName)
	if err != nil {
		return ret, err
	}
	defer fd.Close()
	re := regexp.MustCompile(`[-]*\d+`)
	buf := bufio.NewScanner(fd)
	for buf.Scan() {
		line := cuboid{}
		state := strings.Split(buf.Text(), " ")
		line.state = state[0]
		tmp := re.FindAllString(buf.Text(), -1)
		line.xmin, err = strconv.Atoi(tmp[0])
		if err != nil {
			return ret, err
		}
		line.xmax, err = strconv.Atoi(tmp[1])
		if err != nil {
			return ret, err
		}
		line.ymin, err = strconv.Atoi(tmp[2])
		if err != nil {
			return ret, err
		}
		line.ymax, err = strconv.Atoi(tmp[3])
		if err != nil {
			return ret, err
		}
		line.zmin, err = strconv.Atoi(tmp[4])
		if err != nil {
			return ret, err
		}
		line.zmax, err = strconv.Atoi(tmp[5])
		if err != nil {
			return ret, err
		}
		ret = append(ret, line)
	}
	return ret, nil
}