| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- package main
- import (
- "bufio"
- "fmt"
- "log"
- "os"
- "sort"
- )
- type Point struct {
- X, Y int
- }
- type PointList []Point
- func (p PointList) Len() int {
- return len(p)
- }
- func (p PointList) Swap(i, j int) {
- p[i], p[j] = p[j], p[i]
- }
- func Area2(a, b, c Point) int {
- return (b.X-a.X)*(c.Y-a.Y) - (c.X-a.X)*(b.Y-a.Y)
- }
- func abs(a int) int {
- if a < 0 {
- return -a
- }
- return a
- }
- func (p PointList) Less(i, j int) bool {
- area := Area2(p[0], p[i], p[j])
- if area == 0 {
- x := abs(p[i].X-p[0].X) - abs(p[j].X-p[0].X)
- y := abs(p[i].Y-p[0].Y) - abs(p[j].Y-p[0].Y)
- if x < 0 || y < 0 {
- return true
- } else if x > 0 || y > 0 {
- return false
- } else {
- return false
- }
- }
- return area > 0
- }
- func (p PointList) FindLowestPoint() {
- m := 0
- for i := 1; i < len(p); i++ {
- //If lowest points are on the same line, take the rightmost point
- if (p[i].Y < p[m].Y) || ((p[i].Y == p[m].Y) && p[i].X > p[m].X) {
- m = i
- }
- }
- p[0], p[m] = p[m], p[0]
- }
- func isLeft(p0, p1, p2 Point) bool {
- return Area2(p0, p1, p2) > 0
- }
- func (points PointList) Compute() (PointList, bool) {
- if len(points) < 3 {
- return nil, false
- }
- stack := new(Stack)
- points.FindLowestPoint()
- sort.Sort(&points)
- stack.Push(points[0])
- stack.Push(points[1])
- i := 2
- for i < len(points) {
- pi := points[i]
- p1 := stack.top.next.value.(Point)
- p2 := stack.top.value.(Point)
- if isLeft(p1, p2, pi) {
- stack.Push(pi)
- i++
- } else {
- stack.Pop()
- }
- }
- //Copy the hull
- ret := make(PointList, stack.Len())
- top := stack.top
- count := 0
- for top != nil {
- ret[count] = top.value.(Point)
- top = top.next
- count++
- }
- return ret, true
- }
- func readInput(file *os.File) []Point {
- scanner := bufio.NewScanner(file)
- var tiles []Point
- for scanner.Scan() {
- line := scanner.Text()
- if line == "" {
- continue
- }
- var x, y int
- n, err := fmt.Sscanf(line, "%d,%d", &x, &y)
- if n != 2 || err != nil {
- log.Fatalf("Bad input: %s", line)
- }
- tiles = append(tiles, Point{X: x, Y: y})
- }
- return tiles
- }
- func part1(tiles []Point) int {
- end := len(tiles)
- var maxArea int
- for i := range tiles {
- for j := i + 1; j < end; j++ {
- area := (abs(tiles[j].X-tiles[i].X) + 1) * (abs(tiles[j].Y-tiles[i].Y) + 1)
- if area > maxArea {
- maxArea = area
- }
- }
- }
- return maxArea
- }
- func main() {
- if len(os.Args) < 2 {
- log.Fatal("You need to specify a file!")
- }
- filePath := os.Args[1]
- file, err := os.Open(filePath)
- if err != nil {
- log.Fatalf("Failed to open %s!\n", filePath)
- }
- tiles := readInput(file)
- fmt.Println("Part1:", part1(tiles))
- }
|