package main

import (
	"bufio"
	"log"
	"os"
	"regexp"
	"strconv"
)

type gridPoint [2]int

type Line struct {
	x1, y1, x2, y2 int
}

type Lines []Line

func main() {
	if err := myMain(); err != nil {
		log.Println(err)
	}
}

func myMain() error {
	// parse input.txt
	lines, err := parseInput("input.txt")
	if err != nil {
		return err
	}

	log.Println(solveFirst(lines))

	log.Println(solveSecond(lines))

	return nil
}

func solveFirst(lines Lines) int {
	var counter int
	for _, v := range genGridHV(lines) {
		if v >= 2 {
			counter++
		}
	}
	return counter
}

func solveSecond(lines Lines) int {
	var counter int
	for _, v := range genGrid(lines) {
		if v >= 2 {
			counter++
		}
	}
	return counter
}

func genGridHV(lines Lines) map[gridPoint]int {
	var ret = map[gridPoint]int{}
	for _, line := range lines {
		if line.y1 == line.y2 {
			if line.x1 < line.x2 {
				for i := line.x1; i <= line.x2; i++ {
					ret[gridPoint{i, line.y1}]++
				}
			} else {
				for i := line.x2; i <= line.x1; i++ {
					ret[gridPoint{i, line.y1}]++
				}
			}
		} else if line.x1 == line.x2 {
			if line.y1 < line.y2 {
				for i := line.y1; i <= line.y2; i++ {
					ret[gridPoint{line.x1, i}]++
				}
			} else {
				for i := line.y2; i <= line.y1; i++ {
					ret[gridPoint{line.x1, i}]++
				}
			}
		}
	}
	return ret
}

func genGrid(lines Lines) map[gridPoint]int {
	var ret = genGridHV(lines)

	for _, line := range lines {
		diffx := line.x2 - line.x1
		diffy := line.y2 - line.y1
		if abs(diffx) == abs(diffy) {
			for x, y, i := line.x1, line.y1, 0; i <= abs(diffx); x, y, i = x+diffx/abs(diffx), y+diffy/abs(diffy), i+1 {
				ret[gridPoint{x, y}]++
			}
		}
	}
	return ret
}

func abs(in int) int {
	if in < 0 {
		return -in
	}
	return in
}

func parseInput(fileName string) (Lines, error) {
	var ret = Lines{}
	fd, err := os.Open(fileName)
	if err != nil {
		return ret, err
	}
	defer fd.Close()

	var re = regexp.MustCompile(`(\d+),(\d+)`)

	buf := bufio.NewScanner(fd)
	for line := 0; buf.Scan(); line++ {
		line := Line{}
		tmp := re.FindAllStringSubmatch(buf.Text(), -1)
		line.x1, err = strconv.Atoi(tmp[0][1])
		if err != nil {
			return ret, err
		}
		line.y1, err = strconv.Atoi(tmp[0][2])
		if err != nil {
			return ret, err
		}
		line.x2, err = strconv.Atoi(tmp[1][1])
		if err != nil {
			return ret, err
		}
		line.y2, err = strconv.Atoi(tmp[1][2])
		if err != nil {
			return ret, err
		}
		ret = append(ret, line)
	}

	return ret, nil
}