From a474acea1eb1bdca5cf3d819a38aa01ca3a448d5 Mon Sep 17 00:00:00 2001 From: yxzzy-wtf <81079984+yxzzy-wtf@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:13:45 +0200 Subject: [PATCH] Initial commit --- .devcontainer.json | 11 ++ 2022/02/code.go | 143 +++++++++++++++++++++++++ 2022/04/code.go | 77 ++++++++++++++ 2022/07/code.go | 260 +++++++++++++++++++++++++++++++++++++++++++++ LICENSE | 21 ++++ README.md | 77 ++++++++++++++ go.mod | 18 ++++ go.sum | 118 ++++++++++++++++++++ run.sh | 54 ++++++++++ 9 files changed, 779 insertions(+) create mode 100644 .devcontainer.json create mode 100755 2022/02/code.go create mode 100755 2022/04/code.go create mode 100755 2022/07/code.go create mode 100644 LICENSE create mode 100644 README.md create mode 100644 go.mod create mode 100644 go.sum create mode 100755 run.sh diff --git a/.devcontainer.json b/.devcontainer.json new file mode 100644 index 0000000..db94056 --- /dev/null +++ b/.devcontainer.json @@ -0,0 +1,11 @@ +{ + "image": "mcr.microsoft.com/devcontainers/go", + "customizations": { + "codespaces": { + "extensions": ["golang.go"] + }, + "vscode": { + "extensions": ["golang.go"] + } + } +} diff --git a/2022/02/code.go b/2022/02/code.go new file mode 100755 index 0000000..dbe374b --- /dev/null +++ b/2022/02/code.go @@ -0,0 +1,143 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/jpillora/puzzler/harness/aoc" +) + +func main() { + aoc.Harness(run) +} + +func run(part2 bool, input string) any { + sum := 0 + for _, line := range strings.Split(strings.TrimSpace(input), "\n") { + pair := strings.SplitN(line, " ", 2) + var op move + op.unmarshal('A', pair[0]) + if op.String() == "unknown" { + panic("invalid opponent move") + } + if part2 { + var o outcome + o.unmarshal(pair[1]) + me := op.want(o) + sum += o.score() + me.score() + } else { + var me move + me.unmarshal('X', pair[1]) + s := op.play(me).score() + sum += me.score() + s + } + } + return sum +} + +type outcome byte + +const ( + lose outcome = iota + draw + win +) + +func (o *outcome) unmarshal(s string) { + *o = outcome(delta('X', s)) +} + +func (o outcome) String() string { + switch o { + case lose: + return "lose" + case draw: + return "draw" + case win: + return "win" + } + return "unknown" +} + +func (o outcome) score() int { + switch o { + case lose: + return 0 + case draw: + return 3 + case win: + return 6 + } + panic("invalid outcome") +} + +type move byte + +const ( + rock move = iota + paper + scissors +) + +func (m *move) unmarshal(base byte, s string) { + *m = move(delta(base, s)) +} + +func (m move) String() string { + switch m { + case rock: + return "rock" + case paper: + return "paper" + case scissors: + return "scissors" + } + return "unknown" +} + +func (m move) score() int { + return int(m) + 1 +} + +func (m move) play(against move) outcome { + if m == against { + return draw + } + if byte(m) == up(byte(against), 3) { + return lose + } + if byte(m) == down(byte(against), 3) { + return win + } + panic(fmt.Sprintf("invalid moves: %d plays %d", m, against)) +} + +func (m move) want(outcome outcome) move { + switch outcome { + case lose: + return move(down(byte(m), 3)) + case draw: + return m + case win: + return move(up(byte(m), 3)) + } + panic("invalid outcome") +} + +func delta(base byte, m string) byte { + if len(m) != 1 { + panic("invalid delta") + } + return m[0] - base +} + +func up(n, mod byte) byte { + return (n + 1) % mod +} + +func down(n, mod byte) byte { + if n == 0 { + return mod - 1 + } + return (n - 1) % mod +} diff --git a/2022/04/code.go b/2022/04/code.go new file mode 100755 index 0000000..102bf6e --- /dev/null +++ b/2022/04/code.go @@ -0,0 +1,77 @@ +package main + +import ( + "fmt" + "log" + "strconv" + "strings" + + "github.com/jpillora/puzzler/harness/aoc" +) + +func main() { + aoc.Harness(run) +} + +func run(part2 bool, input string) any { + if input == "" { + return "not implemented" + } + count := 0 + lines := strings.Split(strings.TrimSpace(input), "\n") + for _, line := range lines { + pair := strings.SplitN(line, ",", 2) + if len(pair) != 2 { + log.Panicf("invalid input %q", line) + } + a := parse(pair[0]) + b := parse(pair[1]) + if !part2 && a.subsetEither(b) { + count++ + } else if part2 && a.intersetsEither(b) { + count++ + } + } + return count +} + +type hilo struct { + lo, hi int +} + +func (h hilo) String() string { + return fmt.Sprintf("%d-%d", h.lo, h.hi) +} + +func parse(s string) hilo { + pair := strings.SplitN(s, "-", 2) + if len(pair) != 2 { + panic("bad pair") + } + lo, err := strconv.Atoi(pair[0]) + if err != nil { + panic(err) + } + hi, err := strconv.Atoi(pair[1]) + if err != nil { + panic(err) + } + return hilo{lo, hi} +} + +func (a hilo) subsetEither(b hilo) bool { + return a.subsetOf(b) || b.subsetOf(a) +} + +func (a hilo) subsetOf(b hilo) bool { + return a.lo >= b.lo && a.hi <= b.hi +} + +func (a hilo) intersetsEither(b hilo) bool { + return a.intersets(b) || b.intersets(a) +} + +func (a hilo) intersets(b hilo) bool { + return a.lo <= b.lo && b.lo <= a.hi || // b.lo in a OR + a.lo <= b.hi && b.hi <= a.hi // b.hi in a +} diff --git a/2022/07/code.go b/2022/07/code.go new file mode 100755 index 0000000..dbad12c --- /dev/null +++ b/2022/07/code.go @@ -0,0 +1,260 @@ +package main + +import ( + "fmt" + "math" + "strconv" + "strings" + + "github.com/jpillora/puzzler/harness/aoc" +) + +func main() { + aoc.Harness(run) +} + +func run(part2 bool, input string) any { + if input == "" { + return "skip" + } + var e *exec + execs := []*exec{} + for _, line := range strings.Split(strings.TrimSpace(input), "\n") { + if strings.HasPrefix(line, "$ ") { + command := strings.Split(line[2:], " ") + e = &exec{command: command} + execs = append(execs, e) + } else { + e.output = append(e.output, line) + } + } + fs := newFileSystem() + for _, e := range execs { + fs.simulate(e) + } + const draw = false + if draw { + fmt.Println(fs.root.tree()) + } + if part2 { + return fs.MinDeleteFor(updateSize) + } + return fs.root.Size100KB() +} + +type exec struct { + command []string + output []string +} + +func (e exec) prog() string { + return e.command[0] +} + +func (e exec) arg(i int) string { + return e.command[1+i] +} + +type fileSystem struct { + root *dir + wd *dir + total int64 +} + +const updateSize = 30000000 + +func newFileSystem() *fileSystem { + root := newDir("", nil) + return &fileSystem{ + root: root, + wd: root, + total: 70000000, + } +} + +func (fs *fileSystem) simulate(e *exec) { + switch e.prog() { + case "cd": + fs.changeDir(e.arg(0)) + case "ls": + fs.listDir(e.output) + default: + panic("unknown command") + } +} + +func (fs *fileSystem) unused() int64 { + return fs.total - fs.root.Size() +} + +func (fs *fileSystem) changeDir(target string) { + switch target { + case "/": + fs.wd = fs.root + case "..": + if fs.wd.parent == nil { + panic("nil parent") + } + fs.wd = fs.wd.parent + default: + fs.wd = fs.wd.subDir(target) + } +} + +func (fs fileSystem) listDir(output []string) { + for _, line := range output { + pair := strings.SplitN(line, " ", 2) + name := pair[1] + if pair[0] == "dir" { + fs.wd.subDir(name) + continue + } + size, err := strconv.ParseInt(pair[0], 10, 64) + if err != nil { + panic(err) + } + fs.wd.file(name, size) + } +} + +func (fs fileSystem) MinDeleteFor(target int64) int64 { + required := target - fs.unused() + if required < 0 { + panic("no min required") + } + min := int64(math.MaxInt64) + fs.root.forEach(func(d *dir) { + s := d.Size() + if s < required { + return + } + // d is a candidate + if s < min { + min = s + } + }) + if min == math.MaxInt64 { + panic("no min found") + } + return min +} + +type dir struct { + name string + children map[string]any + parent *dir +} + +func newDir(name string, parent *dir) *dir { + return &dir{ + name: name, + children: map[string]any{}, + parent: parent, + } +} + +func (d *dir) subDir(name string) *dir { + x, ok := d.children[name] + if !ok { + dir := newDir(name, d) + d.children[name] = dir + return dir + } + dir, ok := x.(*dir) + if !ok { + panic("file/dir mismatch") + } + return dir +} + +func (d dir) tree() string { + sb := strings.Builder{} + fmt.Fprintf(&sb, "%s (%d) {\n", d.path(), d.Size()) + for _, c := range d.children { + var out string + switch v := c.(type) { + case *dir: + out = v.tree() + case *file: + out = v.String() + default: + panic("invalid child") + } + ls := strings.Split(out, "\n") + for i := range ls { + ls[i] = " " + ls[i] + } + indented := strings.Join(ls, "\n") + sb.WriteString(indented) + sb.WriteRune('\n') + } + sb.WriteString("}") + return sb.String() +} + +func (d *dir) file(name string, size int64) { + d.children[name] = &file{ + name: name, + size: size, + } +} + +func (d *dir) path() string { + if d.name == "" { + return "/" + } + p := []string{d.name} + w := d.parent + for w != nil { + p = append([]string{w.name}, p...) + w = w.parent + } + return strings.Join(p, "/") +} + +func (d dir) Size() int64 { + sum := int64(0) + for _, c := range d.children { + switch v := c.(type) { + case *dir: + sum += v.Size() + case *file: + sum += v.size + default: + panic("invalid child") + } + } + return sum +} + +func (d *dir) forEach(fn func(*dir)) { + fn(d) + for _, c := range d.children { + sub, ok := c.(*dir) + if !ok { + continue + } + sub.forEach(fn) + } +} + +func (d dir) Size100KB() int64 { + const limit = 100000 + sum := int64(0) + d.forEach(func(sub *dir) { + size := sub.Size() + if size < limit { + sum += size + } + }) + return sum +} + +type file struct { + name string + size int64 +} + +func (f file) String() string { + return fmt.Sprintf("%s (%d)", f.name, f.size) +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8084288 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Jaime Pillora + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2aca063 --- /dev/null +++ b/README.md @@ -0,0 +1,77 @@ +# Advent of Code in Go + +A handy template repository to hold your [Advent of Code](https://adventofcode.com) solutions in Go (golang). + +Advent of Code (https://adventofcode.com) is a yearly series of programming questions based on the [Advent Calendar](https://en.wikipedia.org/wiki/Advent_calendar). For each day leading up to christmas, there is one question released, and from the second it is released, there is a timer running and a leaderboard showing who solved it first. + +--- + +### Features + +* A directory per question `/` +* Auto-download questions into `//README.md` +* Auto-download example input into `//input-example.txt` +* With env variable `AOC_SESSION` set: + * Auto-download part 2 of questions into `//README.md` + * Auto-download user input into `//input-user.md` +* When you save `code.go`, it will execute your `run` function 4 times: + * Input `input-example.txt` and `part2=false` + * Input `input-example.txt` and `part2=true` + * Input `input-user.txt` and `part2=false` + * Input `input-user.txt` and `part2=true` + * and, will show the results and timing of each + +--- + +### Usage + +1. Click "**Use this template**" above to fork it into your account +1. Setup repo, either locally or in codespaces + * Locally + * Install Go from https://go.dev/dl/ or from brew, etc + * Git clone your fork + * Open in VS Code, and install the Go extension + * Codespaces + * Click "Open in Codespaces" +1. Open a terminal and `./run.sh ` like this: + + ```sh + $ ./run.sh 2023 1 + [run.sh] created ./2023/01 + [run.sh] created ./2023/01/code.go + Created file README.md + Created file input-example.txt + run(part1, input-example) returned in 616µs => 42 + ``` + +1. Implement your solution in `./2023/01/code.go` inside the `run` function + * I have provided solutions for year `2022`, days `2`,`4`,`7` – however you can delete them and do them yourself if you'd like +1. Changes will re-run the code + * For example, update `code.go` to `return 43` instead you should see: + + ```sh + file changed code.go + run(part1, input-example) returned in 34µs => 43 + ``` + +1. The question is downloaded to `./2023/01/README.md` +1. Login to https://adventofcode.com +1. Find your question (e.g. https://adventofcode.com/2023/day/1) and **[get your puzzle input](https://adventofcode.com/2023/day/1/input)** and save it to `./2023/01/input-user.txt` + * See **Session** below to automate this step +1. Iterate on `code.go` until you get the answer +1. Submit it to https://adventofcode.com/2023/day/1 + +--- + +#### Session + +**Optionally**, you can set `export AOC_SESSION=` to your adventofcode.com `session` cookie. That is: + +* Login with your browser +* Open developer tools > Application/Storage > Cookies +* Retrieve the contents of `session` +* Export it as `AOC_SESSION` + +With your session set, running `code.go` will download your user-specifc `input-user.txt` and also update `README.md` with part 2 of the question once you've completed part 1. + +Currently, your session is NOT used to submit your answer. You still need to login to https://adventofcode.com to submit. \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..1ecd86d --- /dev/null +++ b/go.mod @@ -0,0 +1,18 @@ +module aoc-in-go + +go 1.21.3 + +require github.com/jpillora/puzzler v1.2.4 + +require ( + github.com/JohannesKaufmann/html-to-markdown v1.4.2 // indirect + github.com/PuerkitoBio/goquery v1.8.1 // indirect + github.com/andybalholm/cascadia v1.3.2 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/jpillora/ansi v1.0.3 // indirect + github.com/jpillora/maplock v0.0.0-20160420012925-5c725ac6e22a // indirect + github.com/maruel/panicparse/v2 v2.3.1 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.15.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..407b761 --- /dev/null +++ b/go.sum @@ -0,0 +1,118 @@ +github.com/JohannesKaufmann/html-to-markdown v1.3.6 h1:i3Ma4RmIU97gqArbxZXbFqbWKm7XtImlMwVNUouQ7Is= +github.com/JohannesKaufmann/html-to-markdown v1.3.6/go.mod h1:Ol3Jv/xw8jt8qsaLeSh/6DBBw4ZBJrTqrOu3wbbUUg8= +github.com/JohannesKaufmann/html-to-markdown v1.4.2 h1:Jt3i/2l98+yOb5uD0ovoIGwccF4DfNxBeUye4P5KP9g= +github.com/JohannesKaufmann/html-to-markdown v1.4.2/go.mod h1:AwPLQeuGhVGKyWXJR8t46vR0iL1d3yGuembj8c1VcJU= +github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U= +github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= +github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= +github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= +github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= +github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= +github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= +github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/jpillora/ansi v1.0.3 h1:nn4Jzti0EmRfDxm7JtEs5LzCbNwd5sv+0aE+LdS9/ZQ= +github.com/jpillora/ansi v1.0.3/go.mod h1:D2tT+6uzJvN1nBVQILYWkIdq7zG+b5gcFN5WI/VyjMY= +github.com/jpillora/maplock v0.0.0-20160420012925-5c725ac6e22a h1:40K0UjFKjfaXcJaGMgf9C0fOzwDxPZMOI0CPbNP89cQ= +github.com/jpillora/maplock v0.0.0-20160420012925-5c725ac6e22a/go.mod h1:bn3xq9G+QDq2j6fczyaTq47L6980t7/NnqCnCK7kqD0= +github.com/jpillora/puzzler v1.2.4 h1:GqvRA7yMWWYXyLx+WXhkZjTldvEdQ4F5z+86rCHzjpQ= +github.com/jpillora/puzzler v1.2.4/go.mod h1:OQ/o2V9d+0kZhtOwAZ/x3n91i0seYWvMfVLa6M9riUQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/maruel/panicparse/v2 v2.3.1 h1:NtJavmbMn0DyzmmSStE8yUsmPZrZmudPH7kplxBinOA= +github.com/maruel/panicparse/v2 v2.3.1/go.mod h1:s3UmQB9Fm/n7n/prcD2xBGDkwXD6y2LeZnhbEXvs9Dg= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y= +github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.4.14 h1:jwww1XQfhJN7Zm+/a1ZA/3WUiEBEroYFNTiV3dKwM8U= +github.com/yuin/goldmark v1.4.14/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= +github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..f32fbc4 --- /dev/null +++ b/run.sh @@ -0,0 +1,54 @@ +#!/bin/bash +set -euf -o pipefail + +# functions +function template() { + cat < " + exit 1 +fi +# pad DAY to 2 digits +DAY=$(printf "%02d" $DAY) +DIR="./$YEAR/$DAY" +# create missing files as needed +if [ ! -d "$DIR" ]; then + mkdir -p "$DIR" + echo "[run.sh] created $DIR" +fi +if [ ! -f "$DIR/code.go" ]; then + template >"$DIR/code.go" + echo "[run.sh] created $DIR/code.go" +fi +# go run +cd "$DIR" && go run code.go