advent-of-code/math.go

97 lines
1.5 KiB
Go

package aoc
import "cmp"
type uinteger interface {
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}
type sinteger interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
}
type integer interface {
sinteger | uinteger
}
type float interface {
complex64 | complex128 | float32 | float64
}
type number interface{ integer | float }
// greatest common divisor (GCD) via Euclidean algorithm
func GCD[T integer](a, b T) T {
for b != 0 {
t := b
b = a % b
a = t
}
return a
}
// find Least Common Multiple (LCM) via GCD
func LCM[T integer](integers ...T) T {
if len(integers) == 0 {
return 0
}
if len(integers) == 1 {
return integers[0]
}
a, b := integers[0], integers[1]
result := a * b / GCD(a, b)
for _, c := range integers[2:] {
result = LCM(result, c)
}
return result
}
func Sum[T number](arr ...T) T {
var acc T
for _, a := range arr {
acc += a
}
return acc
}
func SumFunc[T any, U number](fn func(T) U, input ...T) U {
return Sum(SliceMap(fn, input...)...)
}
func SumIFunc[T any, U number](fn func(int, T) U, input ...T) U {
return Sum(SliceIMap(fn, input...)...)
}
func Power2(n int) int {
if n == 0 {
return 1
}
p := 2
for ; n > 1; n-- {
p *= 2
}
return p
}
func ABS[I integer](i I) I {
if i < 0 {
return -i
}
return i
}
func Max[T cmp.Ordered](a T, v ...T) T {
for _, b := range v {
if b > a {
a = b
}
}
return a
}
func Min[T cmp.Ordered](a T, v ...T) T {
for _, b := range v {
if b < a {
a = b
}
}
return a
}