advent-of-code/runner.go

100 lines
2.2 KiB
Go

package aoc
import (
"bufio"
"flag"
"fmt"
"io"
"log"
"os"
"path/filepath"
"runtime"
"runtime/pprof"
"strings"
"time"
)
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to `file`")
func runnerFile[R any, F func(*os.File) (R, error)]() *os.File {
if len(os.Args) < 2 {
Log("Usage:", filepath.Base(os.Args[0]), "FILE")
os.Exit(22)
}
inputFilename := os.Args[1]
os.Args = append(os.Args[:1], os.Args[2:]...)
flag.Parse()
Log(cpuprofile, memprofile, *cpuprofile, *memprofile)
if *cpuprofile != "" {
Log("enabled cpu profile")
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal("could not create CPU profile: ", err)
}
defer f.Close() // error handling omitted for example
Log("write cpu profile to", f.Name())
if err := pprof.StartCPUProfile(f); err != nil {
log.Fatal("could not start CPU profile: ", err)
}
defer pprof.StopCPUProfile()
}
if *memprofile != "" {
Log("enabled mem profile")
defer func() {
f, err := os.Create(*memprofile)
if err != nil {
log.Fatal("could not create memory profile: ", err)
}
Log("write mem profile to", f.Name())
defer f.Close() // error handling omitted for example
runtime.GC() // get up-to-date statistics
if err := pprof.WriteHeapProfile(f); err != nil {
log.Fatal("could not write memory profile: ", err)
}
}()
}
input, err := os.Open(inputFilename)
if err != nil {
Log(err)
os.Exit(1)
}
return input
}
func Runner[R any, F func(*bufio.Scanner) (R, error)](run F) (R, error) {
return run(bufio.NewScanner(runnerFile[R]()))
}
func RunnerReader[R any, F func(io.Reader) (R, error)](run F) (R, error) {
return run(runnerFile[R]())
}
func MustResult[T any](result T, err error) {
if err != nil {
fmt.Println("ERR", err)
os.Exit(1)
}
Log("result", result)
}
func Log(v ...any) {
fmt.Fprint(os.Stderr, time.Now(), ": ")
fmt.Fprintln(os.Stderr, v...)
}
func Logf(format string, v ...any) {
if !strings.HasSuffix(format, "\n") {
format += "\n"
}
fmt.Fprintf(os.Stderr, format, v...)
}
func ReadStringToInts(fields []string) []int {
return SliceMap(Atoi, fields...)
}