Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
204 commits
Select commit Hold shift + click to select a range
9724adb
Let the sorting begin...
GPKyte Jan 14, 2021
ca71d8c
Wait. Check this sort out for lolz
GPKyte Jan 14, 2021
1649546
Correct package name in wait.go
GPKyte Jan 16, 2021
22ecd1b
Impl (incorrect) soln to sort from partial sorts
GPKyte Jan 16, 2021
1a60cdb
Revisit Radix conversation in the docs
GPKyte Jan 17, 2021
c0193b8
Deprecate strategy and pursue OrderedMap Design
GPKyte Feb 2, 2021
b0e83e3
Mess around and make a Filter process
GPKyte Feb 7, 2021
8bbe0ba
Interface correction & cast.
GPKyte Feb 11, 2021
c84cbb1
Improve test data log & debranch else
GPKyte Feb 11, 2021
5eb2f08
Compile collect.go
GPKyte Feb 11, 2021
42c1881
Just to make sure the test data is good...
GPKyte Feb 11, 2021
50983a0
Correct the list nesting issue
GPKyte Feb 11, 2021
8461737
Test string filter (flow.Short)
GPKyte Feb 11, 2021
b18da72
Fix runtime type is int error
GPKyte Feb 11, 2021
d748bf8
Deletion and comments on next steps
GPKyte Feb 11, 2021
1699b49
Some Headers and ExtendRangeImplementation
GPKyte Feb 18, 2021
c200b7e
Merge branch 'feature.sort.stuck' into feature.sort
GPKyte Feb 18, 2021
b0e3ee7
Just editing to compile radix.go
GPKyte Feb 18, 2021
13736ac
Red light on flow test
GPKyte Feb 18, 2021
02c6ad1
Green light on flow
GPKyte Feb 18, 2021
157ced8
Testing increment strategy
GPKyte Feb 18, 2021
db66874
Implement Example of syncing increments
GPKyte Feb 18, 2021
facdf3e
Fix non incrementing bug
GPKyte Feb 18, 2021
12973db
Create the test for example usage
GPKyte Feb 20, 2021
ac8d01f
Improve documentation, no changes
GPKyte Feb 20, 2021
7f22041
Implement ExampleFlow
GPKyte Feb 20, 2021
2f9d035
Passed tests, but discovered logical error
GPKyte Feb 22, 2021
465139a
Pond challenge begun
GPKyte Feb 22, 2021
accfe32
Too many errors. Taking Break
GPKyte Feb 22, 2021
3ecb99d
Scanner to Reader per conventions
GPKyte Feb 24, 2021
2643aeb
Progressing towards solution
GPKyte Feb 24, 2021
6390103
Simplify and expand Pond test
GPKyte Feb 24, 2021
88bc107
Iterate on pond
GPKyte Feb 26, 2021
cd274f3
Iterate on solution
GPKyte Feb 26, 2021
1b5acc4
Force set height of matrix
GPKyte Apr 14, 2021
837ebb9
Beginning's of test for a large matrix
GPKyte Apr 14, 2021
5c9e58e
Add helper function
GPKyte Apr 14, 2021
4fd8c32
Fill process explicitly written into solution
GPKyte Apr 14, 2021
bbbe637
Partial changes
GPKyte Apr 14, 2021
b74644d
Alternate matrix def added
GPKyte Apr 29, 2021
aab4311
Correct 'perimiter' typo
GPKyte Apr 29, 2021
4ff500e
Implement an Expand Pond method
GPKyte Apr 29, 2021
3a30e0b
Improve iter var name and document
GPKyte Apr 29, 2021
47f4ad1
Rethink the cluster and layer traversal logic
GPKyte Apr 29, 2021
c79ebf0
Stuck on next change
GPKyte Apr 29, 2021
aeec160
Remove Matrix.Group
GPKyte Apr 29, 2021
e02401a
Mess around and make a Tile Queue
GPKyte Apr 29, 2021
77e0113
Edit error message to include other case
GPKyte Apr 29, 2021
d480017
Did we need an Equality check for Matrix?
GPKyte May 7, 2021
b5069e5
Enable test with a number scanner
GPKyte May 13, 2021
61e218f
Simplify goals of test
GPKyte May 13, 2021
d97aacb
Impl rand scanner for very large test
GPKyte May 13, 2021
b99e657
Whitespace edit
GPKyte May 13, 2021
c8f3348
Fix logging parameters
GPKyte May 13, 2021
7c657ae
Fix errors in Q.serve()
GPKyte May 13, 2021
2f8401f
Fix Q.wait(here)
GPKyte May 13, 2021
63d2e95
Fix FindAdjacent typo x2
GPKyte May 17, 2021
6c86249
Revisit clustering solution
GPKyte May 17, 2021
229bade
Maybe we cant return that type
GPKyte May 17, 2021
1869ecc
Correct interface fulfillment and type usage
GPKyte May 17, 2021
d99eb1a
Pointer correction for Matrix ref in Test
GPKyte May 17, 2021
8f60da1
Re-implement clusterTogether
GPKyte May 17, 2021
d4959a7
Fix OOB error
GPKyte May 17, 2021
c8aaf02
Remove explicit redundancy
GPKyte May 17, 2021
b97d804
A test was broken
GPKyte May 17, 2021
907815b
Test broken for same reason as last.
GPKyte May 17, 2021
d774122
Play around with SelectCommonMembers
GPKyte Jun 3, 2021
221f175
Small fix squashes previous bug.
GPKyte Jun 3, 2021
c73d2f4
Checking in draft of OrdinalTree
GPKyte Jun 12, 2021
9d97724
Play with sequencing
GPKyte Jun 13, 2021
df29bc9
Move sum func out and store calc
GPKyte Jun 14, 2021
f7e4d7a
Expand on Stack test
GPKyte Jun 14, 2021
635b8a7
End unwarranted permutation length increases
GPKyte Jun 14, 2021
8b7c79a
Successful trials of permute()
GPKyte Jun 14, 2021
ad71818
Add the scramble component
GPKyte Jun 14, 2021
b3e1aaf
Test larger series
GPKyte Jun 14, 2021
e3793db
Hard limit on the channel exposes new issue
GPKyte Jun 14, 2021
4ccebd1
Testing Modulo stuff
GPKyte Jun 18, 2021
aa5fc19
Write up modulo thing
GPKyte Jun 18, 2021
59958e9
The test had an order bug
GPKyte Jun 18, 2021
030480a
Reference digitmodulo by * to correct memory
GPKyte Jun 18, 2021
0480b64
Add some counters to the permutation generation
GPKyte Jun 18, 2021
42f3ab7
Testing the factorial sequence
GPKyte Jun 18, 2021
235e735
Add digitmodulo to the main counter
GPKyte Jun 18, 2021
c44ea3d
Test digitmodulo on base 10
GPKyte Jun 18, 2021
71847bb
Remove OrdinalTree code
GPKyte Jun 18, 2021
f7f9b50
Rename files tree -> permute
GPKyte Jun 18, 2021
40dc685
Merge branch 'feature.sort' into dev
GPKyte Jun 18, 2021
a694225
Merge branch 'pond' into dev
GPKyte Jun 18, 2021
61b5cb8
Change package name challenge->main
GPKyte Jun 21, 2021
31a1cbc
Revert "Merge branch 'pond' into dev"
GPKyte Jun 21, 2021
8ad7914
Revert "Change package name challenge->main"
GPKyte Jun 23, 2021
1811fc2
Export permute methods for permute_test
GPKyte Jun 23, 2021
70f5083
Test use of Interfaces in Param and Return
GPKyte Jun 23, 2021
babfb59
Fix SEGSEVR nil pointer dereference
GPKyte Jun 23, 2021
5c21948
Apply new insights to Equals method
GPKyte Jun 23, 2021
f234b66
Fix type of m in typecheck for Equals(m)
GPKyte Jun 23, 2021
b38465e
Fix Index [0] Out of Bounds in generateTwoDimArray()
GPKyte Jun 23, 2021
3b450b6
Fix assignment to entry in nil map
GPKyte Jun 23, 2021
4e7d964
Add boundary check for Matrix.Get(x,y)
GPKyte Jun 23, 2021
36ea424
Add Test for unexported clusterTogether()
GPKyte Jun 27, 2021
1487e3c
Mispelled Matrix with a c
GPKyte Jun 27, 2021
e4b6bbb
Remove alias
GPKyte Jun 27, 2021
b950ea7
Delete Test Case that Ruins the rest
GPKyte Jun 27, 2021
11f868e
Boundary check the basic matrix
GPKyte Jul 6, 2021
c3e5e7c
Minor corrections on unit_test
GPKyte Jul 6, 2021
88aa38d
Fix comment. Break method.
GPKyte Jul 6, 2021
50e40f5
BasicVisitor could be useful for clustering
GPKyte Jul 7, 2021
d53af91
Implement a successful cluster together
GPKyte Jul 8, 2021
fa80b7b
Lay groundwork for shortcut
GPKyte Jul 8, 2021
50a9d55
Leverage clusterTogether method to solve challenge
GPKyte Jul 8, 2021
9ed4b83
Zen
GPKyte Jul 11, 2021
4d4e170
Separate setup from execution
GPKyte Jul 11, 2021
a56fc18
Stringify my BasicMatrix
GPKyte Jul 11, 2021
b1b9a4b
Testing PermutePlus on a Buffered Writer
GPKyte Jul 12, 2021
60e656d
Merge branch 'pond' into dev
GPKyte Jul 12, 2021
cb8c02a
Finish the Big Permutation Test
GPKyte Jul 12, 2021
3f3e081
Minor tweaks to permute test file
GPKyte Jul 12, 2021
0d21530
Implement PermutePlus and a QuickQueue
GPKyte Jul 12, 2021
8ea8a59
Improve visibility of potential errors
GPKyte Jul 16, 2021
ef69e6a
Change name of main() to ExamplePermute()
GPKyte Jul 16, 2021
dc8bbfe
Practice on recursion conversion
GPKyte Jul 16, 2021
80f4854
Messing around with idea for range model
GPKyte Jan 29, 2022
9447f8c
Ignore Finder config file .DS_Store
GPKyte Dec 5, 2022
bbb41ec
Implement parsing for food input
GPKyte Dec 5, 2022
e127952
Implement parsing for elves
GPKyte Dec 5, 2022
39a71fe
Include test data
GPKyte Dec 5, 2022
efca2b3
Implement main executable
GPKyte Dec 5, 2022
a7ff18b
Set dependency versions for module
GPKyte Dec 5, 2022
2f09c18
Add sorting to elves collection
GPKyte Dec 5, 2022
3907b97
Test finding top three calorie contributions
GPKyte Dec 5, 2022
c6e3452
Use new elf methods in main and tests
GPKyte Dec 6, 2022
6ff0bd9
Add RPS rounds input and handling code
GPKyte Dec 6, 2022
ff6f0d9
Add a player construct for score keeping
GPKyte Dec 6, 2022
83f7a3e
Add Tournament for connecting players and rounds
GPKyte Dec 6, 2022
71cc2ba
Prepare tournament and players for usage and display
GPKyte Dec 6, 2022
352a06c
Implment main method for RPS
GPKyte Dec 6, 2022
cace68d
Adapt gesture parsing to react to first gesture and an outcome.
GPKyte Dec 7, 2022
5d61b03
Use adapted parsing strategy in tournament preparation.
GPKyte Dec 7, 2022
d421f12
Add convenient file opener
GPKyte Dec 10, 2022
2a3c78f
Day four(1, 2) complete
GPKyte Dec 10, 2022
96f75ec
Day 5 testing checkpoint
GPKyte Dec 10, 2022
8b58d85
Begin day 5
GPKyte Dec 15, 2022
3112227
Complete day 5-1
GPKyte Dec 15, 2022
0c73eb4
Add feature control
GPKyte Dec 15, 2022
d75ca39
Feature for order-preserving multi crate transfer
GPKyte Dec 15, 2022
4546d95
Complete part two of day three
GPKyte Dec 15, 2022
accc70a
Tests built for day 6 part 1
GPKyte Dec 15, 2022
4da6fba
Complete day 6
GPKyte Dec 15, 2022
bdee72c
Begin day seven with method headers and tests
GPKyte Dec 15, 2022
4b91ead
Add new module
GPKyte Dec 15, 2022
242585f
Add input test logging and package header
GPKyte Dec 17, 2022
127fd40
Lengthen and Shorten method headers per preferences
GPKyte Dec 17, 2022
1e94f3f
Syntax check and remediation
GPKyte Dec 17, 2022
d6e4de0
Add readme for day five
GPKyte Dec 17, 2022
8717dee
Update modules
GPKyte Dec 17, 2022
12e8dc0
Track go.sum file
GPKyte Dec 17, 2022
345af14
Add files for day three
GPKyte Dec 17, 2022
4b0d4ca
Add README for day two
GPKyte Dec 17, 2022
1247e2c
Addd day seven README
GPKyte Dec 17, 2022
259a3e2
Dev functions for four types
GPKyte Dec 17, 2022
50a69a8
Use dir references in place of directories
GPKyte Dec 17, 2022
977c86b
Expand logging for func TestDirectoryAwareness
GPKyte Dec 17, 2022
a02c359
Add Include Dir and other dir usage
GPKyte Dec 17, 2022
1d16ae5
Include dirs files in size calc
GPKyte Dec 17, 2022
c4c4653
Add NewPath and edge case for string method
GPKyte Dec 17, 2022
9b2cf5f
TestPathUpAndDown
GPKyte Dec 17, 2022
aa4eb45
Use path reference in place of path
GPKyte Dec 17, 2022
80c5547
Add Testing for example
GPKyte Dec 17, 2022
35c4ba4
Command parsing index correction
GPKyte Dec 17, 2022
f512938
Adjust output expectations for filesystem and path
GPKyte Dec 17, 2022
f195e28
Move DirectoryTraversal next to other *Directory methods
GPKyte Dec 17, 2022
4d3dd20
Remove unwanted appendature
GPKyte Dec 17, 2022
05ca71d
Implement String() for FileSystem
GPKyte Dec 17, 2022
a555624
Use path references in place of paths
GPKyte Dec 17, 2022
fdfe32d
main() implementation
GPKyte Dec 17, 2022
ae806d7
Cache size of directory after calc
GPKyte Dec 18, 2022
07d0486
Solve part two of day seven
GPKyte Dec 18, 2022
cfc62d0
Include resource file for day seven
GPKyte Dec 18, 2022
2e941fa
Begin day 8 with some grid cells called trees
GPKyte Dec 18, 2022
83d41e6
Implement forest traversals for output and inspection
GPKyte Dec 20, 2022
8fb21c8
Add string method to tree
GPKyte Dec 20, 2022
58d1099
Part two of day 8 calculates scenic scores
GPKyte Dec 21, 2022
7563213
Add main call to treehouse pkg
GPKyte Dec 21, 2022
a289df1
complete day 8
GPKyte Dec 21, 2022
c0c2098
Complete part one of day nine
GPKyte Dec 21, 2022
4adb25e
Begin testing day ten
GPKyte Dec 22, 2022
5baff70
Complete part 1 of day ten
GPKyte Dec 22, 2022
2a39d74
Complete day 10 part two
GPKyte Dec 22, 2022
88b2ff8
Day 11: Test operations and item transfers
GPKyte Dec 22, 2022
397e028
Implement choices
GPKyte Dec 22, 2022
63c9259
Parsing puzzle input
GPKyte Dec 23, 2022
b1bd601
Add round implementation
GPKyte Dec 23, 2022
283792a
Day 11: Alter item processing method
GPKyte Dec 30, 2022
f282f24
Pass tests and tidy up for main method
GPKyte Dec 30, 2022
4e59973
Display round activity
GPKyte Dec 30, 2022
811d0ff
Change calculation for corrected solution
GPKyte Dec 30, 2022
f76a332
Day 12: Load and print grid
GPKyte Dec 30, 2022
332ab19
Draft ideas for solving day 12 puzzle. WIP
GPKyte Dec 30, 2022
e9a906c
Testing for overall, queue, and label conversion
GPKyte Dec 30, 2022
7e0897f
Testing for path tree link and trace
GPKyte Dec 30, 2022
3f8d8b7
Merge branch 'feature.permute' into release
GPKyte Sep 25, 2023
ba66bae
Merge branch 'flow.collections' into release
GPKyte Sep 25, 2023
502e357
Merge branch 'range.sort' into release
GPKyte Sep 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.DS_Store
78 changes: 78 additions & 0 deletions challenge/advent/assignment/assignment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package assignment

import (
"io"
"fmt"
"strings"
"strconv"
"bufio"

"github.com/GPKyte/banter/challenge/advent/section"
"github.com/GPKyte/banter/challenge/advent/elf"
)

type Assignment struct {
s *section.SectionRange
e *elf.Elf
}

type AssignmentPair struct {
a, z *Assignment
}

func (ap *AssignmentPair) String() string {
return fmt.Sprintf("%d-%d,%d-%d",
ap.a.s.First(), ap.a.s.Last(), ap.z.s.First(), ap.z.s.Last())
}

func LoadFromPuzzleInput(from io.Reader) *[]*AssignmentPair {
aps := make([]*AssignmentPair, 0)

s := bufio.NewScanner(from)
s.Split(bufio.ScanLines) // Set token scan behavior to read line by line
for dataRemaining := s.Scan(); dataRemaining; dataRemaining = s.Scan() {
line := s.Text()
aps = append(aps, newPair(line))
}

return &aps
}
func newPair(s string) *AssignmentPair {
first, second := splitAtThe(",", s)

return &AssignmentPair{
a: New(first),
z: New(second),
}
}
func splitAtThe(sep, s string) (string, string) {
ss := strings.Split(s, sep)

if len(ss) != 2 {
panic("Could not properly split the input string: "+s)
}

return ss[0], ss[1]
}
func New(s string) *Assignment {
one, two := splitAtThe("-", s)
start, err := strconv.Atoi(one)
if err != nil {
panic("Could not parse the "+s+" string for new Assignment.")
}
end, err := strconv.Atoi(two)
if err != nil {
panic("Could not parse the "+s+" string for new Assignment.")
}
return &Assignment{
s: section.Range(start, end),
e: &elf.Elf{},
}
}
func (ap *AssignmentPair) AnyOverlap() bool {
return section.DoAnyOverlap(ap.a.s, ap.z.s)
}

func (ap *AssignmentPair) HasFullyRedundantSectionOverlap() bool {
return section.EitherContainsTheOther(ap.a.s, ap.z.s)
}
42 changes: 42 additions & 0 deletions challenge/advent/assignment/assignment_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package assignment

import (
"testing"
"strings"
)

func TestImportFromString(t *testing.T) {
input := "2-4,8-9"
p := newPair(input)

if p.a.s.Len() != 3 || p.z.s.Len() != 2 {t.Fail()}

severalInputs := `0-9,5-9
1-3,3-8
4-5,9-20
3-6,1-10`
severalAps := LoadFromPuzzleInput(strings.NewReader(severalInputs))
if len(*severalAps) != 4 {t.Fail()}
}

func TestRedundancyCheck(t *testing.T) {
with := newPair("20-30,10-50")
without := newPair("1-5,4-9")
equal := newPair("1-8,1-8")

if !with.HasFullyRedundantSectionOverlap() {t.Fail()}
if without.HasFullyRedundantSectionOverlap() {t.Fail()}
if !equal.HasFullyRedundantSectionOverlap() {t.Fail()}
}

func TestOverlap(t *testing.T) {
with := newPair("20-30,10-50")
without := newPair("1-5,4-9")
equal := newPair("1-8,1-8")
other := newPair("10-35,49-81")

if !with.AnyOverlap() {t.Fail()}
if !without.AnyOverlap() {t.Fail()}
if !equal.AnyOverlap() {t.Fail()}
if other.AnyOverlap() {t.Fail()}
}
21 changes: 21 additions & 0 deletions challenge/advent/common/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package common

import (
"os"
)

func OpenFirstArgAsFileReader() *os.File {
if len(os.Args) < 2 {
panic("Specify which file to read from as first argument.")
}
fileAtRelativePath := os.Args[1]

file, err := os.Open(fileAtRelativePath)
if err != nil && os.IsNotExist(err) {
panic("File does not exist at "+fileAtRelativePath)
} else if err != nil {
panic("Could not open file "+fileAtRelativePath)
}

return file
}
14 changes: 14 additions & 0 deletions challenge/advent/crate/crate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package crate

type Crate string
const CrateSize int = len("[C]") // characters needed to label a crate in the puzzle's input e.g. '[C]'

func New(crate string) Crate {
return Crate(crate)
}

var NoCrate = Crate("")

func (c Crate) DifferentThan(this Crate) bool {return c != this}
func (c Crate) SameAs(this Crate) bool {return !c.DifferentThan(this)}
func (c Crate) ShortString() string {return string(c[1:2])}
50 changes: 50 additions & 0 deletions challenge/advent/crate/crate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package crate

import (
"testing"
"os"
)

func exampleHelper(t *testing.T, fn string) func(t *testing.T) {
return func(t *testing.T) {
ex, err := os.Open(fn)
if err != nil {
panic(err)
}
defer ex.Close()

stacks, usingTransfers := LoadPuzzle(ex)
stacks.rearrange(usingTransfers, true)
ex.Seek(int64(0), 0) // Reset reader
expectedStacks := loadPuzzleAnswer(ex)

if have, want := stacks.TopSummary(), expectedStacks.TopSummary(); have != want {
t.Fail()
t.Log(have, want)
t.Log(stacks)
t.Log(expectedStacks)
}
}
}

func TestPuzzleExample(t *testing.T) {

MultiCrateTransfer.Disable()

for _, fn := range []string{
"testdata/example-00.txt",
"testdata/example-01.txt",
} {
t.Run(fn, exampleHelper(t, fn))
}

MultiCrateTransfer.Enable()

for _, fn := range []string{
"testdata/example-10.txt",
"testdata/example-11.txt",
} {
t.Run(fn, exampleHelper(t, fn))
}
}

170 changes: 170 additions & 0 deletions challenge/advent/crate/input.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package crate

import(
"io"
"bufio"
"strings"
"strconv"
"fmt"
)

func parseInstructions(s string) []Transfer {
instructions := make([]Transfer, 0)

i := bufio.NewScanner(strings.NewReader(s))
i.Split(bufio.ScanLines)
for ok := i.Scan(); ok; ok = i.Scan() {
var src, dst, qty int
_, err := fmt.Sscanf(i.Text(), "move %d from %d to %d", &qty, &src, &dst)
if err != nil {
panic(fmt.Errorf("Got the error (%w) and thus could not scan instructions from this input: %s\n", err, i.Text()))
}
instructions = append(instructions, Transfer{
Source: src,
Destination: dst,
Quantity: qty,
})
}
return instructions
}


func LoadCrates(from io.Reader) map[int][]Crate {
// Track where each crate was found
properPlace := map[int][]Crate{}
transferCratesToProperPlace := func(m map[int]Crate) {
for key, crate := range m {
if _, ok := properPlace[key]; !ok {
properPlace[key] = make([]Crate, 0)
}
properPlace[key] = append(properPlace[key], crate)
}
}

s := bufio.NewScanner(from)
s.Split(bufio.ScanLines)
for dataRemaining := s.Scan(); dataRemaining; dataRemaining = s.Scan() {
if !strings.Contains(s.Text(), "[") {
break // Because the input no longer serves this function
}
transferCratesToProperPlace(
extractCratesFromLine(s.Text()))
}

return properPlace
}

func extractCratesFromLine(s string) map[int]Crate {
// cratesInSparseSlice := make([]Crate, len(s))
cratesByInputLocation := map[int]Crate{}

foundCrateLabel := false
for i, r := range s {
if foundCrateLabel {
cratesByInputLocation[i] = Crate("["+string(r)+"]")
}
foundCrateLabel = r == '['
}
return cratesByInputLocation
}

func LoadPuzzle(input io.Reader) (*Stacks, []Transfer) {
puz := bufio.NewReader(input) // Once read in part, can no longer read said part without resetting
var stackDrawing, stackLabels, transferInstructions string

stackDrawing, _ = puz.ReadString('1')
puz.UnreadByte() // Give back the '1' so that it can be found in the stack labels
stackLabels, _ = puz.ReadString('\n')
puz.ReadLine() // Empty line before transferInstructions
transferInstructions, _ = puz.ReadString('-') // Read until EOF or puzzle answer separator
transferInstructions = string(transferInstructions[:len(transferInstructions) - 1])

howMany := parseNumberOfStacks(strings.NewReader(stackLabels))
stacks := createStacks(strings.NewReader(stackDrawing), howMany)
transfers := parseInstructions(transferInstructions)

return stacks, transfers
}

func brokenLoadPuzzle(input io.Reader) (*Stacks, []Transfer) {
// Worried that sharing io.Reader and varying implementation options of subfunctions could result in odd behavior, as though io.Reader may need to be reset.
copy := make([]byte, 0)
io.ReadFull(input, copy)

howMany := parseNumberOfStacks(strings.NewReader(string(copy)))
stacks := createStacks(strings.NewReader(string(copy)), howMany)

r := bufio.NewReader(strings.NewReader(string(copy)))
aid := []byte("1.")
r.ReadString(aid[0]) // Stack labels are written above the tranfer instructions
r.ReadLine() // Clear this line
i, _ := r.ReadString(aid[1]) // Won't find a period, will go to EOF
transfers := parseInstructions(i)

return stacks, transfers
}

func parseNumberOfStacks(input io.Reader) int {
r := bufio.NewReader(input)
discarded, err := r.ReadString('1')
if err != nil {
panic(
fmt.Errorf(
`Could not find start of stack labels because %w
Discarded this input: %s`,
err, discarded))
}
stackLabelsLineRaw, err := r.ReadString('\n')
if err != nil {
panic(fmt.Errorf("Could not read line of Stack Labels: %w", err))
}
stackLabelsLine := strings.Trim(stackLabelsLineRaw, " \n")
stackLabels := strings.Split(stackLabelsLine, " ")
lastLabel, err := strconv.Atoi(last(stackLabels))
if err != nil {
panic(fmt.Errorf("Could not parse last stack label due to: %w", err))
}

return lastLabel
}

func last(ss []string) string {
return ss[len(ss)-1]
}

func brokenParseNumberOfStacks(input io.Reader) int {
bs := bufio.NewScanner(input)
ok := bs.Scan()
asLongAsItTakesToFindTheLineWithStackLabels := func () bool {
continueWhileNotFound := ok
moveOnWhenReady := !strings.Contains(bs.Text(), "1") // Finding the number one breaks the for loop
return continueWhileNotFound && moveOnWhenReady
}

for asLongAsItTakesToFindTheLineWithStackLabels() {
ok = bs.Scan()
}
if !ok && !strings.Contains(bs.Text(), "1") {
panic("Could not find number of stacks. Most recent line scanned is: "+bs.Text())
}
stackLabels := strings.Split(bs.Text(), " ")
stackCount, err := strconv.Atoi(stackLabels[len(stackLabels)-2])
if err != nil {
panic(fmt.Errorf("Could not read last stack label from %v and find number of stacks. Encountered this error as a result: %w", stackLabels, err))
}
return stackCount
}

func loadPuzzleAnswer(input io.Reader) *Stacks {
s := bufio.NewReader(input)
s.ReadString('-') // "---" marks end of input and start of puzzle
s.ReadString('\n') // "--\n" is leftover after previous Read, clear the line
// Load remaining content as stacks

stackDrawing, _ := s.ReadString('1')
s.UnreadByte()
stackLabels, _ := s.ReadString('\n')

howMany := parseNumberOfStacks(strings.NewReader(stackLabels))
return createStacks(strings.NewReader(stackDrawing), howMany)
}
Loading