-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Also add puzzle.yaml cache object from the adventofcode.com information Signed-off-by: Rodolfo Sanchez <[email protected]>
- Loading branch information
Showing
30 changed files
with
1,808 additions
and
276 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# How to work with Puzzles | ||
|
||
With a functional programing model we are going to help people working with Advent of Code problems. | ||
|
||
## Init | ||
|
||
What questions should we ask? | ||
- Name or default | ||
- Language runtime from list of supported languages | ||
- version of the supported language | ||
- want git? | ||
- if yes, repository in mind? | ||
- | ||
|
||
## Get | ||
The user will write `aoctl puzzle get/sync` with some informaation | ||
|
||
|
||
Information needed: | ||
- Year // if year is not provided it will go over 2015-lastDecemberyear | ||
- Day // if day is not provided it will go over 1-25. If we are between dec 1 and dec 25 and YEAR is current, only do until "TODAY's day" | ||
- Part // if part is not provided it will try to get both parts (if first part is not solved it will only get one | ||
|
||
> Alert the user if bulk of information is going to be created (in order words, if any information is missing and multiple parts are going to be downlaoded request confirmation from user) | ||
The user should expect a file structure for each year/day | ||
|
||
- A puzzle.yaml file with the current state of the puzzle | ||
- For each part (there are two) there should be a file of the selected language of the project that has a main function where the user will write the business logic | ||
- inputs folder. The user will use this folder for testing or submit purposes. [TODO: not full flesh out yet] | ||
- Test files for each part with the description of the part as comments in the file. | ||
- Readme file that explains how to use each file of this puzzle solver | ||
|
||
|
||
puzzle.yaml | ||
- language this overwrites the root language runtime | ||
- Language version | ||
- depedencies | ||
- Parts | ||
- solver: filename | ||
input: inputname | ||
submitted: bool | ||
|
||
## File Structure | ||
|
||
Example of a aocproject files: | ||
|
||
/<custom-name-for-project> | ||
README.md | ||
.gitignore // the session cookie file should be here | ||
.git/ // initialized git with provided remote or empty | ||
.aoc.yaml // configuration like language, and other preferences | ||
/src | ||
/<year> | ||
/<day> | ||
README.md | ||
puzzle.yaml | ||
part1.go | ||
part1_test.go | ||
part2.go | ||
part2_test.go | ||
/inputs | ||
input.txt | ||
|
||
For language especific things | ||
- Golang: work directory in a go.mod root file that adds every day of every year? | ||
- Golang: Do we need a main runner? // TODO: Think about the main runner. Example we can replace it with Makefiles | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package day1 | ||
|
||
import ( | ||
"testing" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/suite" | ||
"github.com/dolfolife/aoctl/pkg/puzzle" | ||
) | ||
|
||
type Day1Suite struct { | ||
suite.Suite | ||
SubjectPart1 Day1Part1Solver | ||
SubjectPart2 Day1Part2Solver | ||
} | ||
|
||
func (suite *Day1Suite) SetupTest() { | ||
suite.SubjectPart1 = Day1Part1Solver{} | ||
suite.SubjectPart2 = Day1Part2Solver{} | ||
} | ||
|
||
func (suite *Day1Suite) TestDayOnePart1NoTimeForaTaxicab1() { | ||
suite.SubjectPart1.Puzzle = puzzle.PuzzlePart{ | ||
RawInput: []byte("R2, L3"), | ||
} | ||
actualValues, errs := suite.SubjectPart1.Solve() | ||
if errs != nil { | ||
suite.T().Errorf("Unexpected error: %s\n", errs) | ||
} | ||
|
||
assert.Equal(suite.T(), "5", actualValues) | ||
} | ||
|
||
func (suite *Day1Suite) TestDayOnePart1NoTimeForaTaxicab2() { | ||
suite.SubjectPart1.Puzzle = puzzle.PuzzlePart{ | ||
RawInput: []byte("R2, R2, R2"), | ||
} | ||
actualValues, errs := suite.SubjectPart1.Solve() | ||
if errs != nil { | ||
suite.T().Errorf("Unexpected error: %s\n", errs) | ||
} | ||
assert.Equal(suite.T(), "2", actualValues) | ||
} | ||
|
||
func (suite *Day1Suite) TestDayOnePart1NoTimeForaTaxicab3() { | ||
suite.SubjectPart1.Puzzle = puzzle.PuzzlePart{ | ||
RawInput: []byte("R5, L5, R5, R3"), | ||
} | ||
actualValues, errs := suite.SubjectPart1.Solve() | ||
if errs != nil { | ||
suite.T().Errorf("Unexpected error: %s\n", errs) | ||
} | ||
assert.Equal(suite.T(), "12", actualValues) | ||
} | ||
|
||
func (suite *Day1Suite) TestDayOnePart1NoTimeForaTaxicab4() { | ||
suite.SubjectPart1.Puzzle = puzzle.PuzzlePart{ | ||
RawInput: []byte("L2, L2, L2"), | ||
} | ||
actualValues, errs := suite.SubjectPart1.Solve() | ||
if errs != nil { | ||
suite.T().Errorf("Unexpected error: %s\n", errs) | ||
} | ||
assert.Equal(suite.T(), "2", actualValues) | ||
} | ||
|
||
func (suite *Day1Suite) TestDayOnePart1NoTimeForaTaxicabVisitedTwice() { | ||
suite.SubjectPart1.Puzzle = puzzle.PuzzlePart{ | ||
RawInput: []byte("R8, R4, R4, R8"), | ||
} | ||
actualValues, errs := suite.SubjectPart1.Solve() | ||
if errs != nil { | ||
suite.T().Errorf("Unexpected error: %s\n", errs) | ||
} | ||
assert.Equal(suite.T(), "8", actualValues) | ||
} | ||
|
||
func (suite *Day1Suite) TestDayOnePart2NoTimeForaTaxicabVisitedTwice() { | ||
suite.SubjectPart2.Puzzle = puzzle.PuzzlePart{ | ||
RawInput: []byte("R8, R4, R4, R8"), | ||
} | ||
actualValues, errs := suite.SubjectPart2.Solve() | ||
if errs != nil { | ||
suite.T().Errorf("Unexpected error: %s\n", errs) | ||
} | ||
assert.Equal(suite.T(), "4", actualValues) | ||
} | ||
|
||
func TestSuite(t *testing.T) { | ||
suite.Run(t, new(Day1Suite)) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package day1 | ||
|
||
import ( | ||
|
||
. "github.com/dolfolife/aoctl/pkg/math" | ||
) | ||
|
||
func newSegmentPath(orientation rune, p Point, steps float64) Segment { | ||
startingPoint := p | ||
switch orientation { | ||
case 'N': | ||
p.Y += steps | ||
startingPoint.Y += 1 | ||
case 'E': | ||
p.X += steps | ||
startingPoint.X += 1 | ||
case 'S': | ||
p.Y -= steps | ||
startingPoint.Y -= 1 | ||
case 'W': | ||
p.X -= steps | ||
startingPoint.X -= 1 | ||
} | ||
return Segment{A: startingPoint, B: p} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package day1 | ||
|
||
import ( | ||
"fmt" | ||
"path/filepath" | ||
"github.com/dolfolife/aoctl/pkg/puzzle" | ||
"github.com/dolfolife/aoctl/pkg/aoc" | ||
) | ||
|
||
func Solve() { | ||
|
||
aocConfig := aoc.GetAoCConfig() | ||
|
||
file := filepath.Join(aocConfig.ProjectPath, "01/puzzle.yaml") | ||
inputfile1 := filepath.Join(aocConfig.ProjectPath, "01/input.txt") | ||
inputfile2 := filepath.Join(aocConfig.ProjectPath, "01/input.txt") | ||
p := puzzle.NewPuzzleFromCache(file, []string{ inputfile1, inputfile2 }) | ||
|
||
part1 := Day1Part1Solver{} | ||
part1.Puzzle = p.Puzzles[0] | ||
answer1, err := part1.Solve() | ||
if err != nil { | ||
fmt.Println(err) | ||
} | ||
fmt.Printf("For the Year %s on the day %s, -- %s\n", p.Metadata.Year, p.Metadata.Day, p.Metadata.Title) | ||
fmt.Printf("Part 1 -- \n Actual Answer: %s and last recorded answer is %s\n", answer1, p.Puzzles[0].Answer) | ||
|
||
part2 := Day1Part2Solver{} | ||
part2.Puzzle = p.Puzzles[1] | ||
answer2, err2 := part2.Solve() | ||
if err2 != nil { | ||
fmt.Println(err2) | ||
} | ||
fmt.Printf("Part 2 -- \n Actual Answer: %s and last recorded answer is %s\n", answer2, p.Puzzles[1].Answer) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package day1 | ||
|
||
import ( | ||
"strings" | ||
"strconv" | ||
|
||
. "github.com/dolfolife/aoctl/pkg/math" | ||
"github.com/dolfolife/aoctl/pkg/puzzle" | ||
) | ||
|
||
func part1(input []string) (string, error) { | ||
var orientation = []rune{ 'N', 'E', 'S', 'W' } | ||
posCurrentOrientation := 0 | ||
|
||
var pos = Point{X: 0, Y: 0} | ||
for _, v := range input { | ||
if v[0] == 'R' { | ||
posCurrentOrientation = (posCurrentOrientation + 1) % len(orientation) | ||
} else { | ||
posCurrentOrientation = (posCurrentOrientation - 1) % len(orientation) | ||
} | ||
|
||
if posCurrentOrientation < 0 { | ||
posCurrentOrientation = len(orientation) + posCurrentOrientation | ||
} | ||
steps, _ := strconv.Atoi(v[1:]) | ||
segment := newSegmentPath(orientation[posCurrentOrientation], pos, float64(steps)) | ||
pos = segment.B | ||
} | ||
return CalDistancePoints(Point{X: 0, Y: 0}, pos), nil | ||
} | ||
|
||
type Day1Part1Solver struct { | ||
Puzzle puzzle.PuzzlePart | ||
} | ||
|
||
func (s *Day1Part1Solver) NormalizeInput(input string) []string { | ||
return strings.Split(input, ", ") | ||
} | ||
|
||
func (s *Day1Part1Solver) Solve() (string, error) { | ||
return part1(s.NormalizeInput(string(s.Puzzle.RawInput))) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package day1 | ||
|
||
import ( | ||
"strings" | ||
"strconv" | ||
"errors" | ||
|
||
. "github.com/dolfolife/aoctl/pkg/math" | ||
"github.com/dolfolife/aoctl/pkg/puzzle" | ||
) | ||
|
||
func part2(input []string) (string, error) { | ||
var orientation = []rune{ 'N', 'E', 'S', 'W' } | ||
posCurrentOrientation := 0 | ||
|
||
path := make([]Segment, 0) | ||
|
||
var pos = Point{X: 0, Y: 0} | ||
for _, v := range input { | ||
if v[0] == 'R' { | ||
posCurrentOrientation = (posCurrentOrientation + 1) % len(orientation) | ||
} else { | ||
posCurrentOrientation = (posCurrentOrientation - 1) % len(orientation) | ||
} | ||
|
||
if posCurrentOrientation < 0 { | ||
posCurrentOrientation = len(orientation) + posCurrentOrientation | ||
} | ||
steps, _ := strconv.Atoi(v[1:]) | ||
newPath := newSegmentPath(orientation[posCurrentOrientation], pos, float64(steps)) | ||
|
||
for _, segment := range path { | ||
intersect, intersectionPoint := CalIntersectionPoint(segment.A, segment.B, newPath.A, newPath.B) | ||
if intersect { | ||
return CalDistancePoints(Point{X: 0, Y: 0}, intersectionPoint), nil | ||
} | ||
} | ||
path = append(path, newPath) | ||
pos = newPath.B | ||
} | ||
return "", errors.New("No intersection found") | ||
} | ||
|
||
type Day1Part2Solver struct { | ||
Puzzle puzzle.PuzzlePart | ||
} | ||
|
||
func (s *Day1Part2Solver) NormalizeInput(input string) []string { | ||
return strings.Split(input, ", ") | ||
} | ||
|
||
func (s *Day1Part2Solver) Solve() (string, error) { | ||
return part2(s.NormalizeInput(string(s.Puzzle.RawInput))) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
--- | ||
metadata: | ||
day: 1 | ||
year: 2016 | ||
title: No Time for a Taxicab | ||
puzzles: | ||
- description: | | ||
Santa's sleigh uses a very high-precision clock to guide its movements, and the clock's oscillator is regulated by stars. Unfortunately, the stars have been stolen... by the Easter Bunny. To save Christmas, Santa needs you to retrieve all fifty stars by December 25th. | ||
Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck! | ||
You're airdropped near Easter Bunny Headquarters in a city somewhere. "Near", unfortunately, is as close as you can get - the instructions on the Easter Bunny Recruiting Document the Elves intercepted start here, and nobody had time to work them out further. | ||
The Document indicates that you should start at the given coordinates (where you just landed) and face North. Then, follow the provided sequence: either turn left (L) or right (R) 90 degrees, then walk forward the given number of blocks, ending at a new intersection. | ||
There's no time to follow such ridiculous instructions on foot, though, so you take a moment and work out the destination. Given that you can only walk on the street grid of the city, how far is the shortest path to the destination? | ||
For example: | ||
Following R2, L3 leaves you 2 blocks East and 3 blocks North, or 5 blocks away. | ||
R2, R2, R2 leaves you 2 blocks due South of your starting position, which is 2 blocks away. | ||
R5, L5, R5, R3 leaves you 12 blocks away. | ||
How many blocks away is Easter Bunny HQ? | ||
answer: 332 | ||
status: solved | ||
- description: | | ||
Then, you notice the instructions continue on the back of the Recruiting Document. Easter Bunny HQ is actually at the first location you visit twice. | ||
For example, if your instructions are R8, R4, R4, R8, the first location you visit twice is 4 blocks away, due East. | ||
How many blocks away is the first location you visit twice? | ||
status: solved | ||
answer: 166 |
Oops, something went wrong.