Skip to content

Commit 71b3daa

Browse files
authored
Merge pull request #2 from igorwulff/feature/style-processing-improvements
Improved Benchmarking and added a total counter.
2 parents dba4061 + f33c42c commit 71b3daa

File tree

5 files changed

+94
-77
lines changed

5 files changed

+94
-77
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ This repository provides a framework and helper tools to streamline the process
2020

2121
## Example
2222

23+
The tool can be given 3 arguments:
24+
```sh
25+
-day string
26+
Day of the challenge. 0 to run all days. (default "0")
27+
-part string
28+
Part of the challenge. 0 to run all parts (default "0")
29+
-year string
30+
Year of the challenge (default "2024")
31+
```
32+
33+
Where days and parts are optional:
34+
* If no days are provided, all days will be run.
35+
* If a day is provided but no parts, all parts of that day will be run.
36+
2337
To run the tool, use the following command:
2438

2539
```sh

internal/benchmark.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package internal
2+
3+
import "time"
4+
5+
type BenchmarkResult struct {
6+
TotalTimeInMs int64
7+
Start int64
8+
}
9+
10+
func (b *BenchmarkResult) StartTimer() {
11+
b.Start = time.Now().UnixMilli()
12+
}
13+
14+
func (b *BenchmarkResult) StopTimer() {
15+
b.TotalTimeInMs = time.Now().UnixMilli() - b.Start
16+
}
17+
18+
func (b BenchmarkResult) GetTotalTimeInMs() int64 {
19+
return b.TotalTimeInMs
20+
}

internal/input.go

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type Args struct {
1818
func ProcessArgs() Args {
1919
year := flag.String("year", fmt.Sprint(time.Now().Year()), "Year of the challenge")
2020
day := flag.String("day", "0", "Day of the challenge. 0 to run all days.")
21-
part := flag.String("part", "1", "Part of the challenge")
21+
part := flag.String("part", "0", "Part of the challenge. 0 to run all parts")
2222
flag.Parse()
2323

2424
args := Args{
@@ -27,22 +27,10 @@ func ProcessArgs() Args {
2727
Year: *year,
2828
}
2929

30-
path, err := args.getPath()
31-
if err != nil {
32-
fmt.Println(err)
33-
os.Exit(1)
34-
}
35-
36-
args.path = path
37-
3830
return args
3931
}
4032

4133
func (args Args) getPath() (string, error) {
42-
if args.Day == "0" {
43-
return "", nil
44-
}
45-
4634
path := filepath.Join("./", args.Year, "day"+args.Day, "part"+args.Part)
4735
if _, err := os.Stat(filepath.Dir(path)); os.IsNotExist(err) {
4836
return "", fmt.Errorf("the directory %s does not exist", filepath.Dir(path))

internal/processor.go

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@ import (
1010
)
1111

1212
type PluginProcessor struct {
13-
Args Args
13+
Args Args
14+
Benchmark *BenchmarkResult
1415
}
1516

1617
func (p PluginProcessor) Build() error {
1718
cmd := exec.Command("go", "build", "-buildmode=plugin", "-o", p.Args.path+".so", p.Args.path+".go")
1819
cmd.Stdout = os.Stdout
1920
cmd.Stderr = os.Stderr
2021

21-
fmt.Printf("\nCreating plugin: %s\n", cmd.String())
22+
fmt.Printf("\nBuilding: %s", cmd.String())
2223
if err := cmd.Run(); err != nil {
2324
return fmt.Errorf("error running command: %v", err)
2425
}
@@ -41,7 +42,7 @@ func (p PluginProcessor) CallFunc(input *[]byte) (string, error) {
4142
// Assert that the symbol is a function with the expected signature
4243
processFunc, ok := symProcess.(func(string) string)
4344
if !ok {
44-
return "", fmt.Errorf("unexpected function signature")
45+
return "", fmt.Errorf("expected func(string) string, got %T", symProcess)
4546
}
4647

4748
// Call the function with an input variable
@@ -80,11 +81,19 @@ func (p PluginProcessor) GetInput() (*[]byte, error) {
8081
return &data, nil
8182
}
8283

83-
func GetAllPluginProcessors(args Args) ([]PluginProcessor, error) {
84-
var baseDir = filepath.Join("./", args.Year)
85-
var processors []PluginProcessor
84+
type Path int
8685

87-
err := filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
86+
const (
87+
year Path = iota
88+
day
89+
part
90+
)
91+
92+
func GetProcessors(args Args) ([]PluginProcessor, error) {
93+
dir := filepath.Join("./", args.Year)
94+
processors := make([]PluginProcessor, 0)
95+
96+
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
8897
if err != nil {
8998
return err
9099
}
@@ -98,38 +107,38 @@ func GetAllPluginProcessors(args Args) ([]PluginProcessor, error) {
98107
return nil
99108
}
100109

101-
if !strings.HasPrefix(parts[1], "day") {
110+
if !strings.HasPrefix(parts[day], "day") || (args.Day != "0" && parts[day] != "day"+args.Day) {
102111
return nil
103112
}
104113

105-
if !strings.HasPrefix(parts[2], "part") || strings.Contains(parts[2], "test") || !strings.HasSuffix(parts[2], ".go") {
114+
if !strings.HasPrefix(parts[part], "part") || strings.Contains(parts[part], "test") || !strings.HasSuffix(parts[part], ".go") {
106115
return nil
107116
}
108117

109-
year := parts[0]
110-
day := parts[1][3:]
111-
part := parts[2][4 : len(parts[2])-3]
118+
if args.Part != "0" && parts[part] != "part"+args.Part+".go" {
119+
return nil
120+
}
112121

113122
args := Args{
114-
Year: year,
115-
Day: day,
116-
Part: part,
123+
Year: parts[year],
124+
Day: parts[day][3:],
125+
Part: parts[part][4 : len(parts[part])-3],
117126
}
118127
args.path, err = args.getPath()
119128
if err != nil {
120129
return err
121130
}
122131

123132
processors = append(processors, PluginProcessor{
124-
Args: args,
133+
Args: args,
134+
Benchmark: &BenchmarkResult{},
125135
})
126136

127137
return nil
128138
})
129139

130140
if err != nil {
131141
fmt.Println("Error scanning directories:", err)
132-
133142
return nil, err
134143
}
135144

runner.go

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,75 +4,61 @@ import (
44
"fmt"
55
"os"
66
"text/tabwriter"
7-
"time"
87

98
internal "github.com/igorwulff/aoc/internal"
109
)
1110

12-
type BenchmarkResult struct {
13-
TotalTimeInMs int64
14-
}
15-
16-
func Run() ([]BenchmarkResult, error) {
11+
func Run() {
1712
args := internal.ProcessArgs()
18-
var plugins []internal.PluginProcessor
19-
// Benchmarking mode
20-
if args.Day == "0" {
21-
allPlugins, err := internal.GetAllPluginProcessors(args)
22-
if err != nil {
23-
fmt.Println(err)
24-
return nil, err
25-
}
26-
plugins = append(plugins, allPlugins...)
27-
} else {
28-
plugins = append(plugins, internal.PluginProcessor{Args: args})
13+
plugins, err := internal.GetProcessors(args)
14+
if err != nil {
15+
fmt.Println(err)
16+
return
2917
}
3018

31-
results := make([]BenchmarkResult, len(plugins))
32-
for i, plugin := range plugins {
33-
input, err := plugin.GetInput()
19+
for _, p := range plugins {
20+
input, err := p.GetInput()
3421
if err != nil {
35-
fmt.Printf("Could not find input.txt for Day %s Part %s\n", plugin.Args.Day, plugin.Args.Part)
36-
return nil, err
22+
fmt.Printf("Could not find input.txt for Day %s Part %s\n", p.Args.Day, p.Args.Part)
23+
return
3724
}
3825

39-
fmt.Printf("Building day %s part %s... ", plugin.Args.Day, plugin.Args.Part)
40-
if err := plugin.Build(); err != nil {
41-
fmt.Print("ERROR!\n")
42-
fmt.Println(err)
43-
return nil, err
26+
fmt.Printf("Running day %s, part %s", p.Args.Day, p.Args.Part)
27+
28+
if err := p.Build(); err != nil {
29+
fmt.Print("ERROR!\n", err)
30+
return
4431
}
45-
fmt.Print("OK!\n")
4632

47-
fmt.Print("Executing tests... ")
48-
if err := plugin.RunTests(); err != nil {
49-
fmt.Print("ERROR!\n")
50-
fmt.Println(err)
51-
return nil, err
33+
if err := p.RunTests(); err != nil {
34+
fmt.Print("ERROR!\n", err)
35+
return
5236
}
5337

54-
fmt.Print("Executing main function... ")
55-
timeBeforeExec := time.Now().UnixMilli()
56-
output, err := plugin.CallFunc(input)
38+
fmt.Println("Trying to solve puzzle...")
39+
40+
p.Benchmark.StartTimer()
41+
output, err := p.CallFunc(input)
5742
if err != nil {
58-
fmt.Print("ERROR!\n")
59-
fmt.Println(err)
60-
return nil, err
43+
fmt.Print("ERROR!\n", err)
44+
return
6145
}
62-
timeAfterExec := time.Now().UnixMilli()
63-
results[i] = BenchmarkResult{TotalTimeInMs: timeAfterExec - timeBeforeExec}
46+
p.Benchmark.StopTimer()
6447

65-
fmt.Printf("Solution: %s\n", output)
48+
fmt.Printf("Solution: %s\n\n", output)
6649
}
6750

68-
fmt.Println("Execution finished! Total time:")
51+
fmt.Println("Execution finished!")
6952
w := tabwriter.NewWriter(os.Stdout, 0, 4, 4, ' ', 0)
70-
fmt.Fprintln(w, "Day\tPart\tTime (ms)")
71-
for i, plugin := range plugins {
53+
fmt.Fprintln(w, "\nDay\tPart\tTime (ms)")
54+
55+
var sum int64 = 0
56+
for _, p := range plugins {
57+
sum += p.Benchmark.GetTotalTimeInMs()
7258
// @TODO: would be nice to join day & parts in a single row, but for now it's already nice they're alphabetically sorted
73-
fmt.Fprintf(w, "%s\t%s\t%d\n", plugin.Args.Day, plugin.Args.Part, results[i].TotalTimeInMs)
59+
fmt.Fprintf(w, "%s\t%s\t%d\n", p.Args.Day, p.Args.Part, p.Benchmark.GetTotalTimeInMs())
7460
}
7561
w.Flush()
7662

77-
return results, nil
63+
fmt.Printf("\nTotal time: %d ms\n", sum)
7864
}

0 commit comments

Comments
 (0)