Day_1
This commit is contained in:
207
2023/gareth/utils/utils.go
Normal file
207
2023/gareth/utils/utils.go
Normal file
@@ -0,0 +1,207 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
func PanicOnErr(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
const MaxInt = int(^uint(0) >> 1)
|
||||
const MinInt = ^MaxInt
|
||||
|
||||
func Max[T constraints.Ordered](a, b T) T {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func Min[T constraints.Ordered](a, b T) T {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func SliceMinMax[T constraints.Ordered](slice []T) (*T, *T) {
|
||||
if len(slice) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
min := &slice[0]
|
||||
max := &slice[0]
|
||||
for i, v := range slice {
|
||||
if v < *min {
|
||||
min = &slice[i]
|
||||
}
|
||||
if v > *max {
|
||||
max = &slice[i]
|
||||
}
|
||||
}
|
||||
return min, max
|
||||
}
|
||||
|
||||
func MustAtoi(s string) int {
|
||||
v, err := strconv.Atoi(s)
|
||||
PanicOnErr(err)
|
||||
return v
|
||||
}
|
||||
|
||||
// Returns key from map[T]int which has the max value
|
||||
func MapFindMax(m interface{}) interface{} {
|
||||
var maxK interface{} = nil
|
||||
var maxV = MinInt
|
||||
iter := reflect.ValueOf(m).MapRange()
|
||||
for iter.Next() {
|
||||
k := iter.Key()
|
||||
v := int(iter.Value().Int())
|
||||
if v > maxV {
|
||||
maxV = v
|
||||
maxK = k.Interface()
|
||||
}
|
||||
}
|
||||
return maxK
|
||||
}
|
||||
|
||||
// Returns key from map[T]int which has the min value
|
||||
func MapFindMin(m interface{}) interface{} {
|
||||
var minK interface{} = nil
|
||||
var minV = MaxInt
|
||||
iter := reflect.ValueOf(m).MapRange()
|
||||
for iter.Next() {
|
||||
k := iter.Key()
|
||||
v := int(iter.Value().Int())
|
||||
if v < minV {
|
||||
minV = v
|
||||
minK = k.Interface()
|
||||
}
|
||||
}
|
||||
return minK
|
||||
}
|
||||
|
||||
func Readfile(day int) string {
|
||||
filename := fmt.Sprintf("day%02d/input.txt", day)
|
||||
file, err := os.Open(filename)
|
||||
PanicOnErr(err)
|
||||
defer file.Close()
|
||||
|
||||
reader := bufio.NewReader(file)
|
||||
contents, err := io.ReadAll(reader)
|
||||
PanicOnErr(err)
|
||||
|
||||
return strings.TrimSuffix(string(contents), "\n")
|
||||
}
|
||||
|
||||
func ParseToStruct(re *regexp.Regexp, input string, target interface{}) bool {
|
||||
m := re.FindStringSubmatch(input)
|
||||
if m == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var useOffset bool
|
||||
|
||||
for i, name := range re.SubexpNames() {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
var field reflect.Value
|
||||
if name == "" {
|
||||
// use offset
|
||||
if i == 1 {
|
||||
useOffset = true
|
||||
} else if !useOffset {
|
||||
panic("can't mix named and unnamed subexpressions")
|
||||
}
|
||||
field = reflect.ValueOf(target).Elem().Field(i - 1)
|
||||
} else {
|
||||
// use name
|
||||
if i == 1 {
|
||||
useOffset = false
|
||||
} else if useOffset {
|
||||
panic("can't mix named and unnamed subexpressions")
|
||||
}
|
||||
field = reflect.ValueOf(target).Elem().FieldByName(name)
|
||||
}
|
||||
if field.Kind() == reflect.String {
|
||||
field.SetString(m[i])
|
||||
} else if field.Kind() == reflect.Int {
|
||||
v, err := strconv.Atoi(m[i])
|
||||
PanicOnErr(err)
|
||||
field.SetInt(int64(v))
|
||||
} else if field.Kind() == reflect.Uint8 {
|
||||
if len(m[i]) != 1 {
|
||||
panic(fmt.Sprintf("expecting 1 char, got: %s", m[i]))
|
||||
}
|
||||
field.SetUint(uint64(m[i][0]))
|
||||
} else {
|
||||
panic(fmt.Sprintf("unknown kind: %s", field.Kind()))
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func MustParseToStruct(re *regexp.Regexp, input string, target interface{}) {
|
||||
if !ParseToStruct(re, input, target) {
|
||||
panic(fmt.Errorf("failed to parse: %s", input))
|
||||
}
|
||||
}
|
||||
|
||||
func CharToLower(c byte) byte {
|
||||
return strings.ToLower(string(c))[0]
|
||||
}
|
||||
|
||||
func CharToUpper(c byte) byte {
|
||||
return strings.ToUpper(string(c))[0]
|
||||
}
|
||||
|
||||
func Contains(haystack []string, needle string) bool {
|
||||
for _, s := range haystack {
|
||||
if s == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func Abs[T constraints.Signed](x T) T {
|
||||
if x < 0 {
|
||||
return -x
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func Gcd(x, y int) int {
|
||||
if x <= 0 || y <= 0 {
|
||||
panic(fmt.Errorf("invalid input: %d, %d", x, y))
|
||||
}
|
||||
if x == y {
|
||||
return x
|
||||
}
|
||||
if x > y {
|
||||
return Gcd(x-y, y)
|
||||
} else {
|
||||
return Gcd(x, y-x)
|
||||
}
|
||||
}
|
||||
|
||||
func Sign[T constraints.Signed](x T) int {
|
||||
if x < 0 {
|
||||
return -1
|
||||
} else if x > 0 {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user