Initial commit
This commit is contained in:
11
.devcontainer.json
Normal file
11
.devcontainer.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"image": "mcr.microsoft.com/devcontainers/go",
|
||||
"customizations": {
|
||||
"codespaces": {
|
||||
"extensions": ["golang.go"]
|
||||
},
|
||||
"vscode": {
|
||||
"extensions": ["golang.go"]
|
||||
}
|
||||
}
|
||||
}
|
||||
143
2022/02/code.go
Executable file
143
2022/02/code.go
Executable file
@@ -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
|
||||
}
|
||||
77
2022/04/code.go
Executable file
77
2022/04/code.go
Executable file
@@ -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
|
||||
}
|
||||
260
2022/07/code.go
Executable file
260
2022/07/code.go
Executable file
@@ -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)
|
||||
}
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -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.
|
||||
77
README.md
Normal file
77
README.md
Normal file
@@ -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 `<year>/<day>`
|
||||
* Auto-download questions into `<year>/<day>/README.md`
|
||||
* Auto-download example input into `<year>/<day>/input-example.txt`
|
||||
* With env variable `AOC_SESSION` set:
|
||||
* Auto-download part 2 of questions into `<year>/<day>/README.md`
|
||||
* Auto-download user input into `<year>/<day>/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 <year> <day>` 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=<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.
|
||||
18
go.mod
Normal file
18
go.mod
Normal file
@@ -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
|
||||
)
|
||||
118
go.sum
Normal file
118
go.sum
Normal file
@@ -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=
|
||||
54
run.sh
Executable file
54
run.sh
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
set -euf -o pipefail
|
||||
|
||||
# functions
|
||||
function template() {
|
||||
cat <<EOF
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/jpillora/puzzler/harness/aoc"
|
||||
)
|
||||
|
||||
func main() {
|
||||
aoc.Harness(run)
|
||||
}
|
||||
|
||||
// on code change, run will be executed 4 times:
|
||||
// 1. with: false (part1), and example input
|
||||
// 2. with: true (part2), and example input
|
||||
// 3. with: false (part1), and user input
|
||||
// 4. with: true (part2), and user input
|
||||
// the return value of each run is printed to stdout
|
||||
func run(part2 bool, input string) any {
|
||||
// when you're ready to do part 2, remove this "not implemented" block
|
||||
if part2 {
|
||||
return "not implemented"
|
||||
}
|
||||
// solve part 1 here
|
||||
return 42
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# two args YEAR and DAY
|
||||
YEAR="${1:-}"
|
||||
DAY="${2:-}"
|
||||
if [ -z "$YEAR" ] || [ -z "$DAY" ]; then
|
||||
echo "Usage: $0 <YEAR> <DAY>"
|
||||
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
|
||||
Reference in New Issue
Block a user