2022-12-06 21:10:52 +00:00
|
|
|
package utils
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
2023-12-07 14:30:39 +00:00
|
|
|
"sort"
|
2022-12-06 21:10:52 +00:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Copies the given string to the clipboard.
|
2022-12-10 09:12:29 +00:00
|
|
|
// The tool 'xclip' needs to be installed
|
2022-12-06 21:10:52 +00:00
|
|
|
func CopyToClipboard(text string) {
|
|
|
|
command := fmt.Sprintf("echo '%s' | xclip -selection clipboard", strings.ReplaceAll(text, "'", "''"))
|
|
|
|
cmd := exec.Command("bash", "-c", command)
|
|
|
|
|
|
|
|
if err := cmd.Start(); err != nil {
|
|
|
|
PrintError("Error while executing command: %s", err)
|
|
|
|
}
|
|
|
|
|
2022-12-10 09:12:29 +00:00
|
|
|
fmt.Print(text + "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets the content of the clipboard.
|
|
|
|
// The tool 'xclip' needs to be installed
|
|
|
|
func GetFromClipboard() string {
|
|
|
|
out, err := exec.Command("bash", "-c", "xclip -o -selection clipboard").Output()
|
|
|
|
if err != nil {
|
|
|
|
PrintError("Error while getting clipboard content: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return string(out)
|
2022-12-06 21:10:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get's the input data for the task
|
|
|
|
func GetInputData(year int, day int) string {
|
|
|
|
// Check if the ressource was already requested
|
|
|
|
fileLocation := fmt.Sprintf("./inputData/%d/day_%02d", year, day)
|
|
|
|
cachedInput, err := os.ReadFile(fileLocation)
|
|
|
|
if err == nil {
|
|
|
|
return string(cachedInput)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make a request to get the input from advent of code and save it in a file
|
2023-12-01 12:12:28 +00:00
|
|
|
url := fmt.Sprintf("https://adventOfCode.com/%d/day/%d/input", year, day)
|
2022-12-06 21:10:52 +00:00
|
|
|
|
|
|
|
// Read cookie session vaue
|
|
|
|
session, err := os.ReadFile("./session.txt")
|
|
|
|
if err != nil {
|
|
|
|
PrintError("Failed to read cookie session file: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
client := http.Client{Timeout: 10 * time.Second}
|
|
|
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
|
|
|
if err != nil {
|
|
|
|
PrintError("%s", err)
|
|
|
|
}
|
|
|
|
req.AddCookie(&http.Cookie{Name: "session", Value: string(session)})
|
|
|
|
|
|
|
|
// Execute the query
|
|
|
|
res, err := client.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
PrintError("Failed to execute request: %s", err)
|
|
|
|
}
|
|
|
|
defer res.Body.Close()
|
|
|
|
|
|
|
|
if res.StatusCode != 200 {
|
|
|
|
PrintError("Incorrect status code: %d", res.StatusCode)
|
|
|
|
}
|
|
|
|
inputData, _ := io.ReadAll(res.Body)
|
|
|
|
err = os.WriteFile(fileLocation, inputData, 0644)
|
|
|
|
if err != nil {
|
|
|
|
PrintError("Failed to write input data to file: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return string(inputData)
|
|
|
|
}
|
|
|
|
|
|
|
|
func PrintError(format string, a ...any) {
|
|
|
|
fmt.Printf(format, a...)
|
|
|
|
os.Exit(-1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ToInt(val string) int {
|
|
|
|
value, err := strconv.Atoi(val)
|
|
|
|
if err != nil {
|
2023-12-07 14:30:39 +00:00
|
|
|
panic(fmt.Sprintf("Failed to convert %q to a number: %s", val, err))
|
2022-12-06 21:10:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return value
|
|
|
|
}
|
2023-12-03 08:49:00 +00:00
|
|
|
|
|
|
|
func IsInt(val string) bool {
|
|
|
|
_, err := strconv.Atoi(val)
|
|
|
|
return err == nil
|
|
|
|
}
|
2023-12-05 19:43:44 +00:00
|
|
|
|
|
|
|
// GetMinValue returns the smallest number
|
|
|
|
// within the given array
|
|
|
|
func GetMinValue(values []int) int {
|
|
|
|
if len(values) == 0 {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
min := values[0]
|
|
|
|
for _, val := range values {
|
|
|
|
if val < min {
|
|
|
|
min = val
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return min
|
|
|
|
}
|
|
|
|
|
|
|
|
// ConvertToInt converts each number within
|
|
|
|
// []string to a number and returns the resulting array.
|
|
|
|
// Empty string values are ignored
|
|
|
|
func ConvertArrayToInt(values []string) []int {
|
|
|
|
rtc := make([]int, 0)
|
|
|
|
|
|
|
|
// Convert each value
|
|
|
|
for _, nmbString := range values {
|
|
|
|
if nmbString == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
nmb := ToInt(nmbString)
|
|
|
|
rtc = append(rtc, nmb)
|
|
|
|
}
|
|
|
|
|
|
|
|
return rtc
|
|
|
|
}
|
2023-12-07 14:30:39 +00:00
|
|
|
|
|
|
|
// SortRunes sorts a string based on the rune value
|
|
|
|
// of every character
|
|
|
|
func SortRunes(value string) string {
|
|
|
|
runeSlice := []rune(value)
|
|
|
|
sort.Slice(runeSlice, func(i, j int) bool {
|
|
|
|
return runeSlice[i] < runeSlice[j]
|
|
|
|
})
|
|
|
|
return string(runeSlice)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReplaceCharacterInString replaces the character at the given index with
|
|
|
|
// the provided value
|
|
|
|
func ReplaceCharacterInString(str, replace string, index int) string {
|
|
|
|
return str[:index] + replace + str[index+1:]
|
|
|
|
}
|
2023-12-08 12:28:54 +00:00
|
|
|
|
|
|
|
// CalculateGCD (greates common divisor) calculates the biggest
|
|
|
|
// positive integer that is divisible by a and b
|
|
|
|
func CalculateGCD(a, b int) int {
|
|
|
|
for b != 0 {
|
|
|
|
t := b
|
|
|
|
b = a % b
|
|
|
|
a = t
|
|
|
|
}
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
|
|
|
|
// CalculateLCM (least common multiple) calculates the smallest
|
|
|
|
// positive integer that is divisible by all numbers
|
|
|
|
func CalculateLCM(ints ...int) int {
|
|
|
|
if len(ints) == 1 {
|
|
|
|
return ints[0]
|
|
|
|
} else if len(ints) == 2 {
|
|
|
|
return ints[0] * ints[1] / CalculateGCD(ints[0], ints[1])
|
|
|
|
}
|
|
|
|
|
|
|
|
return CalculateLCM(ints[0], CalculateLCM(ints[1:]...))
|
|
|
|
}
|
2023-12-09 08:33:59 +00:00
|
|
|
|
|
|
|
func AreAllElementsEqual[T any](vals []T) bool {
|
|
|
|
if len(vals) == 0 {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
prev := vals[0]
|
|
|
|
for i := 0; i < len(vals); i++ {
|
|
|
|
if any(prev) != any(vals[i]) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
prev = vals[i]
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|