package main import ( "fmt" "strconv" "strings" ) type Vec2 struct { X int64 Y int64 } func NewVec2(axis ...int64) *Vec2 { if len(axis) == 0 { return &Vec2{X: 0, Y: 0} } else if len(axis) == 1 { return &Vec2{X: axis[0], Y: axis[0]} } else { return &Vec2{X: axis[0], Y: axis[1]} } } func (v *Vec2) Clone() *Vec2 { if v == nil { return nil } return &Vec2{X: v.X, Y: v.Y} } func (v *Vec2) Add(axis ...int64) *Vec2 { if v == nil { return nil } if len(axis) == 0 { return v } else if len(axis) == 1 { v.X += axis[0] v.Y += axis[0] return v } else { v.X += axis[0] v.Y += axis[1] return v } } func (v *Vec2) Sub(axis ...int64) *Vec2 { if v == nil { return nil } if len(axis) == 0 { return v } else if len(axis) == 1 { v.X -= axis[0] v.Y -= axis[0] return v } else { v.X -= axis[0] v.Y -= axis[1] return v } } func (v *Vec2) Mul(axis ...int64) *Vec2 { if v == nil { return nil } if len(axis) == 0 { return v } else if len(axis) == 1 { v.X *= axis[0] v.Y *= axis[0] return v } else { v.X *= axis[0] v.Y *= axis[1] return v } } func (v *Vec2) Div(axis ...int64) *Vec2 { if v == nil { return nil } if len(axis) == 0 { return v } else if len(axis) == 1 { v.X /= axis[0] v.Y /= axis[0] return v } else { v.X /= axis[0] v.Y /= axis[1] return v } } func (v *Vec2) Rem(axis ...int64) *Vec2 { if v == nil { return nil } if len(axis) == 0 { return v } else if len(axis) == 1 { v.X %= axis[0] v.Y %= axis[0] return v } else { v.X %= axis[0] v.Y %= axis[1] return v } } func (v *Vec2) Set(axis ...int64) *Vec2 { if v == nil { return nil } if len(axis) == 0 { v.X = 0 v.Y = 0 return v } else if len(axis) == 1 { v.X = axis[0] v.Y = axis[0] return v } else { v.X = axis[0] v.Y = axis[1] return v } } func (v *Vec2) AddBy(o *Vec2) *Vec2 { if v == nil { return nil } if o == nil { return v } v.X += o.X v.Y += o.Y return v } func (v *Vec2) SubBy(o *Vec2) *Vec2 { if v == nil { return nil } if o == nil { return v } v.X -= o.X v.Y -= o.Y return v } func (v *Vec2) MulBy(o *Vec2) *Vec2 { if v == nil { return nil } if o == nil { return v } v.X *= o.X v.Y *= o.Y return v } func (v *Vec2) DivBy(o *Vec2) *Vec2 { if v == nil { return nil } if o == nil { return v } v.X /= o.X v.Y /= o.Y return v } func (v *Vec2) RemBy(o *Vec2) *Vec2 { if v == nil { return nil } if o == nil { return v } v.X -= o.X v.Y -= o.Y return v } func (v *Vec2) SetTo(o *Vec2) *Vec2 { if v == nil { return nil } if o == nil { return v } v.X = o.X v.Y = o.Y return v } func (v *Vec2) Abs() *Vec2 { if v == nil { return nil } v.X = I64Abs(v.X) v.Y = I64Abs(v.Y) return v } func I64Abs(i int64) int64 { if i < 0 { return -i } return i } func (v *Vec2) Negate() *Vec2 { if v == nil { return nil } v.X = -v.X v.Y = -v.Y return v } func (v *Vec2) Less(axis ...int64) bool { if v == nil || len(axis) == 0 { return false } if len(axis) == 1 { return v.X < axis[0] && v.Y < axis[0] } else { return v.X < axis[0] && v.Y < axis[1] } } func (v *Vec2) Great(axis ...int64) bool { if v == nil || len(axis) == 0 { return false } if len(axis) == 1 { return v.X > axis[0] && v.Y > axis[0] } else { return v.X > axis[0] && v.Y > axis[1] } } func (v *Vec2) Eq(axis ...int64) bool { if v == nil { return false } if len(axis) == 0 { return v.X == 0 && v.Y == 0 } else if len(axis) == 1 { return v.X == axis[0] && v.Y == axis[0] } else { return v.X == axis[0] && v.Y == axis[1] } } func (v *Vec2) LessThan(o *Vec2) bool { if v == nil || o == nil { return false } return v.X < o.X && v.Y < o.Y } func (v *Vec2) GreatThan(o *Vec2) bool { if v == nil || o == nil { return false } return v.X > o.X && v.Y > o.Y } func (v *Vec2) EqTo(o *Vec2) bool { if v == nil || o == nil { return false } return v.X == o.X && v.Y == o.Y } func (v *Vec2) Dist(axis ...int64) int64 { if v == nil { return -1 } if len(axis) == 0 { return I64Abs(v.X) + I64Abs(v.Y) } else if len(axis) == 1 { a := I64Abs(v.X) + I64Abs(v.Y) b := I64Abs(axis[0]) + I64Abs(axis[0]) return I64Abs(a - b) } else { a := I64Abs(v.X) + I64Abs(v.Y) b := I64Abs(axis[0]) + I64Abs(axis[1]) return I64Abs(a - b) } } func (v *Vec2) DistTo(o *Vec2) int64 { if v == nil || o == nil { return -1 } a := I64Abs(v.X) + I64Abs(v.Y) b := I64Abs(o.X) + I64Abs(o.Y) return I64Abs(a - b) } func (v *Vec2) String() string { return fmt.Sprintf("(%d, %d)", v.X, v.Y) } var ( ErrVec2Format error = fmt.Errorf("missing parentheses and/or comma") ErrTooManyCommas error = fmt.Errorf("missing or too many commas") ErrInvalidAxisX error = fmt.Errorf("missing or invalid X-axis") ErrInvalidAxisY error = fmt.Errorf("missing or invalid Y-axis") ) func StrToVec2(s string) (*Vec2, error) { if !strings.Contains(s, "(") || !strings.Contains(s, ")") || !strings.Contains(s, ",") { return nil, ErrVec2Format } work := strings.ReplaceAll(s, "(", "") work = strings.ReplaceAll(work, ")", "") commas := strings.Count(work, ",") if commas != 1 { return nil, ErrTooManyCommas } parts := strings.Split(work, ",") for idx, part := range parts { parts[idx] = strings.TrimSpace(part) } if len(parts) != 2 { return nil, ErrTooManyCommas } x, err := strconv.ParseInt(parts[0], 10, 64) if err != nil { return nil, ErrInvalidAxisX } y, err := strconv.ParseInt(parts[1], 10, 64) if err != nil { return nil, ErrInvalidAxisY } return &Vec2{X: x, Y: y}, nil }