Init commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.vscode
|
||||||
|
debug*.txt
|
||||||
|
input*.txt
|
||||||
10
cmd/day1/example.txt
Normal file
10
cmd/day1/example.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
L68
|
||||||
|
L30
|
||||||
|
R48
|
||||||
|
L5
|
||||||
|
R60
|
||||||
|
L55
|
||||||
|
L1
|
||||||
|
L99
|
||||||
|
R14
|
||||||
|
L82
|
||||||
147
cmd/day1/main.go
Normal file
147
cmd/day1/main.go
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
debug := flag.Bool("debug", false, "Debug flag.")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
d1 := dial{n: 50}
|
||||||
|
d2 := dial{n: 50}
|
||||||
|
if *debug {
|
||||||
|
fmt.Println("LINE d1 d2")
|
||||||
|
fmt.Println(" 50 50")
|
||||||
|
}
|
||||||
|
|
||||||
|
sc := bufio.NewScanner(os.Stdin)
|
||||||
|
for sc.Scan() {
|
||||||
|
if sc.Text() == "" {
|
||||||
|
log.Fatal("empty line")
|
||||||
|
}
|
||||||
|
n, err := strconv.ParseUint(sc.Text()[1:], 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
i := int(n)
|
||||||
|
if sc.Text()[0] == 'L' {
|
||||||
|
i = -int(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if err := handleLine(d1.Add1, sc.Text()); err != nil {
|
||||||
|
// log.Fatal(err)
|
||||||
|
// }
|
||||||
|
if err := handleLine(d1.Add1, sc.Text()); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := handleLine(d2.Add2, sc.Text()); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if *debug {
|
||||||
|
fmt.Printf("%+4d %2d %2d (%+3d %+3d)\n", i, d1.n, d2.n, d1.lastClicks, d2.lastClicks)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := sc.Err(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("zeros:", d1.zeros, d2.zeros)
|
||||||
|
fmt.Println("zero passes:", d1.zeroClicks, d2.zeroClicks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleLine(add func(int), line string) error {
|
||||||
|
if line == "" {
|
||||||
|
return errors.New("empty line")
|
||||||
|
}
|
||||||
|
n, err := strconv.ParseUint(line[1:], 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch line[0] {
|
||||||
|
case 'L':
|
||||||
|
add(-int(n))
|
||||||
|
return nil
|
||||||
|
case 'R':
|
||||||
|
add(int(n))
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unexpected line: %q", line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type dial struct {
|
||||||
|
n int
|
||||||
|
lastClicks int
|
||||||
|
zeros int
|
||||||
|
zeroClicks int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *dial) Add1(n int) {
|
||||||
|
wasAtZero := d.n == 0
|
||||||
|
d.n += n
|
||||||
|
step := +100
|
||||||
|
if d.n < 0 {
|
||||||
|
step = -100
|
||||||
|
}
|
||||||
|
d.lastClicks = 0
|
||||||
|
for d.n < 0 || d.n > 99 {
|
||||||
|
d.lastClicks++
|
||||||
|
d.n -= step
|
||||||
|
}
|
||||||
|
if d.lastClicks > 0 && wasAtZero {
|
||||||
|
d.lastClicks--
|
||||||
|
}
|
||||||
|
if d.n == 0 {
|
||||||
|
d.zeros++
|
||||||
|
if d.lastClicks == 0 {
|
||||||
|
d.lastClicks++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.zeroClicks += d.lastClicks
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *dial) Add2(diff int) {
|
||||||
|
n := d.n + diff
|
||||||
|
|
||||||
|
var clicks int
|
||||||
|
switch {
|
||||||
|
case n < 0:
|
||||||
|
wasAtZero := d.n == 0
|
||||||
|
for n < 0 {
|
||||||
|
if wasAtZero {
|
||||||
|
wasAtZero = false
|
||||||
|
} else {
|
||||||
|
clicks++
|
||||||
|
}
|
||||||
|
n += 100
|
||||||
|
}
|
||||||
|
if n == 0 && !wasAtZero {
|
||||||
|
clicks++
|
||||||
|
}
|
||||||
|
|
||||||
|
case n > 99:
|
||||||
|
for n > 99 {
|
||||||
|
clicks++
|
||||||
|
n -= 100
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if n == 0 && d.n != 0 {
|
||||||
|
clicks++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
d.zeros++
|
||||||
|
}
|
||||||
|
d.n = n
|
||||||
|
d.lastClicks = clicks
|
||||||
|
d.zeroClicks += clicks
|
||||||
|
}
|
||||||
80
cmd/day1/main_test.go
Normal file
80
cmd/day1/main_test.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_dial_Add2(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
start int
|
||||||
|
turn int
|
||||||
|
want int
|
||||||
|
wantClicks int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
start: 50,
|
||||||
|
turn: 300,
|
||||||
|
want: 50,
|
||||||
|
wantClicks: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: 50,
|
||||||
|
turn: -300,
|
||||||
|
want: 50,
|
||||||
|
wantClicks: 3,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
start: 0,
|
||||||
|
turn: -100,
|
||||||
|
want: 0,
|
||||||
|
wantClicks: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: 1,
|
||||||
|
turn: -101,
|
||||||
|
want: 0,
|
||||||
|
wantClicks: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: 99,
|
||||||
|
turn: -199,
|
||||||
|
want: 0,
|
||||||
|
wantClicks: 2,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
start: 0,
|
||||||
|
turn: 100,
|
||||||
|
want: 0,
|
||||||
|
wantClicks: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: 99,
|
||||||
|
turn: 101,
|
||||||
|
want: 0,
|
||||||
|
wantClicks: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: 1,
|
||||||
|
turn: 199,
|
||||||
|
want: 0,
|
||||||
|
wantClicks: 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
name := fmt.Sprintf("R%d", tt.turn)
|
||||||
|
if tt.turn < 0 {
|
||||||
|
name = fmt.Sprintf("L%d", -tt.turn)
|
||||||
|
}
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
d := dial{n: tt.start}
|
||||||
|
d.Add2(tt.turn)
|
||||||
|
assert.Equal(t, tt.want, d.n, "dial")
|
||||||
|
assert.Equal(t, tt.wantClicks, d.zeroClicks, "clicks")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
22
cmd/day2/digits.go
Normal file
22
cmd/day2/digits.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func digits(n uint) []uint8 {
|
||||||
|
if n == 0 {
|
||||||
|
return []uint8{0}
|
||||||
|
}
|
||||||
|
var digits []uint8
|
||||||
|
for ; n != 0; n /= 10 {
|
||||||
|
digits = append(digits, uint8(n%10))
|
||||||
|
}
|
||||||
|
return digits
|
||||||
|
}
|
||||||
|
|
||||||
|
func number(digits []uint8) uint {
|
||||||
|
var n uint
|
||||||
|
base := uint(1)
|
||||||
|
for _, d := range digits {
|
||||||
|
n += uint(d) * base
|
||||||
|
base *= 10
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
30
cmd/day2/digits_test.go
Normal file
30
cmd/day2/digits_test.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_digits_number(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
n uint
|
||||||
|
d []uint8
|
||||||
|
}{
|
||||||
|
{n: 0, d: []uint8{0}},
|
||||||
|
{n: 1234, d: []uint8{4, 3, 2, 1}},
|
||||||
|
{n: 12345, d: []uint8{5, 4, 3, 2, 1}},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
name := strconv.FormatUint(uint64(tt.n), 10)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Run("digits", func(t *testing.T) {
|
||||||
|
assert.Equal(t, tt.d, digits(tt.n))
|
||||||
|
})
|
||||||
|
t.Run("number", func(t *testing.T) {
|
||||||
|
assert.Equal(t, tt.n, number(tt.d))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
1
cmd/day2/example.txt
Normal file
1
cmd/day2/example.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124
|
||||||
97
cmd/day2/main.go
Normal file
97
cmd/day2/main.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"slices"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
debug := flag.Bool("debug", false, "Debug.")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
ranges, err := readRanges(os.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sum1, sum2 uint
|
||||||
|
for _, r := range ranges {
|
||||||
|
invalid1 := handleRange(r, scanPart1)
|
||||||
|
invalid2 := handleRange(r, scanPart2)
|
||||||
|
|
||||||
|
if *debug {
|
||||||
|
fmt.Printf("range: %d-%d\n", r.from, r.to)
|
||||||
|
}
|
||||||
|
if *debug && len(invalid1) > 0 {
|
||||||
|
fmt.Println("invalid (part 1):")
|
||||||
|
for _, id := range invalid1 {
|
||||||
|
fmt.Printf(" %d\n", id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if *debug && len(invalid2) > 0 {
|
||||||
|
fmt.Println("invalid (part 2):")
|
||||||
|
for _, id := range invalid2 {
|
||||||
|
fmt.Printf(" %d\n", id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, id := range invalid1 {
|
||||||
|
sum1 += id
|
||||||
|
}
|
||||||
|
for _, id := range invalid2 {
|
||||||
|
sum2 += id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("sum (part 1):", sum1)
|
||||||
|
fmt.Println("sum (part 2):", sum2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleRange(r idRange, scan func(id uint) (advance uint, ok bool)) []uint {
|
||||||
|
var invalid []uint
|
||||||
|
for id := r.from; id <= r.to; {
|
||||||
|
advance, ok := scan(id)
|
||||||
|
if !ok {
|
||||||
|
invalid = append(invalid, id)
|
||||||
|
}
|
||||||
|
id += advance
|
||||||
|
}
|
||||||
|
return invalid
|
||||||
|
}
|
||||||
|
|
||||||
|
func scanPart1(id uint) (advance uint, ok bool) {
|
||||||
|
digits := digits(id)
|
||||||
|
if len(digits)%2 == 1 { // odd is always valid
|
||||||
|
nextSmallestEven := uint(math.Pow10(len(digits)))
|
||||||
|
return nextSmallestEven - id, true
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
x = uint(math.Pow10(len(digits) / 2))
|
||||||
|
left = id / x
|
||||||
|
right = id % x
|
||||||
|
)
|
||||||
|
return 1, left != right
|
||||||
|
}
|
||||||
|
|
||||||
|
func scanPart2(id uint) (advance uint, ok bool) {
|
||||||
|
digits := digits(id)
|
||||||
|
if len(digits) <= 1 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
|
||||||
|
loop:
|
||||||
|
for i := 1; i <= len(digits)/2; i++ {
|
||||||
|
ref := digits[:i]
|
||||||
|
for chunk := range slices.Chunk(digits, i) {
|
||||||
|
if !slices.Equal(chunk, ref) {
|
||||||
|
continue loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1, false
|
||||||
|
}
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
77
cmd/day2/main_test.go
Normal file
77
cmd/day2/main_test.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_scanPart1(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
id uint
|
||||||
|
advance uint
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
// {
|
||||||
|
// id: 9,
|
||||||
|
// advance: 1,
|
||||||
|
// ok: true,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// id: 10,
|
||||||
|
// advance: 1,
|
||||||
|
// ok: true,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// id: 11,
|
||||||
|
// advance: 1,
|
||||||
|
// ok: false,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// id: 99,
|
||||||
|
// advance: 1,
|
||||||
|
// ok: false,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// id: 100,
|
||||||
|
// advance: 900,
|
||||||
|
// ok: true,
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
id: 1234,
|
||||||
|
advance: 1,
|
||||||
|
ok: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
name := strconv.FormatUint(uint64(tt.id), 10)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
advance, ok := scanPart1(tt.id)
|
||||||
|
assert.Equal(t, tt.advance, advance, "advance")
|
||||||
|
assert.Equal(t, tt.ok, ok, "ok")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_scanPart2(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
id uint
|
||||||
|
advance uint
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
id: 111,
|
||||||
|
advance: 1,
|
||||||
|
ok: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
name := strconv.FormatUint(uint64(tt.id), 10)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
advance, ok := scanPart2(tt.id)
|
||||||
|
assert.Equal(t, tt.advance, advance, "advance")
|
||||||
|
assert.Equal(t, tt.ok, ok, "ok")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
62
cmd/day2/range.go
Normal file
62
cmd/day2/range.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type idRange struct {
|
||||||
|
from, to uint
|
||||||
|
}
|
||||||
|
|
||||||
|
func readRanges(r io.Reader) ([]idRange, error) {
|
||||||
|
sc := bufio.NewScanner(r)
|
||||||
|
sc.Split(scanSimpleCSV)
|
||||||
|
|
||||||
|
var ranges []idRange
|
||||||
|
for sc.Scan() {
|
||||||
|
before, after, ok := strings.Cut(sc.Text(), "-")
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("range %q: missing dash", sc.Text())
|
||||||
|
}
|
||||||
|
from, err := strconv.ParseUint(before, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("range %q: %w", sc.Text(), err)
|
||||||
|
}
|
||||||
|
to, err := strconv.ParseUint(after, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("range %q: %w", sc.Text(), err)
|
||||||
|
}
|
||||||
|
if from > to {
|
||||||
|
return nil, fmt.Errorf("range %q: refers from higher to lower", sc.Text())
|
||||||
|
}
|
||||||
|
ranges = append(ranges, idRange{
|
||||||
|
from: uint(from),
|
||||||
|
to: uint(to),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return ranges, sc.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func scanSimpleCSV(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||||
|
if atEOF && len(data) == 0 {
|
||||||
|
return 0, nil, nil
|
||||||
|
}
|
||||||
|
if i := bytes.IndexByte(data, ','); i >= 0 {
|
||||||
|
return i + 1, data[:i], nil
|
||||||
|
}
|
||||||
|
if atEOF {
|
||||||
|
if trimmed, ok := bytes.CutSuffix(data, []byte("\r\n")); ok {
|
||||||
|
return len(data), trimmed, nil
|
||||||
|
}
|
||||||
|
if trimmed, ok := bytes.CutSuffix(data, []byte{'\n'}); ok {
|
||||||
|
return len(data), trimmed, nil
|
||||||
|
}
|
||||||
|
return len(data), data, nil
|
||||||
|
}
|
||||||
|
return 0, nil, nil
|
||||||
|
}
|
||||||
22
cmd/day3/battery.go
Normal file
22
cmd/day3/battery.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func readBatteries(r io.Reader) (banks [][]uint8, err error) {
|
||||||
|
sc := bufio.NewScanner(r)
|
||||||
|
for sc.Scan() {
|
||||||
|
var bank []uint8
|
||||||
|
for _, b := range sc.Bytes() {
|
||||||
|
if b < '0' || b > '9' {
|
||||||
|
return nil, fmt.Errorf("bank %q: invalid joltage %q", sc.Text(), b)
|
||||||
|
}
|
||||||
|
bank = append(bank, b-'0')
|
||||||
|
}
|
||||||
|
banks = append(banks, bank)
|
||||||
|
}
|
||||||
|
return banks, sc.Err()
|
||||||
|
}
|
||||||
4
cmd/day3/example.txt
Normal file
4
cmd/day3/example.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
987654321111111
|
||||||
|
811111111111119
|
||||||
|
234234234234278
|
||||||
|
818181911112111
|
||||||
86
cmd/day3/main.go
Normal file
86
cmd/day3/main.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmp"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
debug := flag.Bool("debug", false, "Debug.")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
f := os.Stdin
|
||||||
|
if flag.NArg() > 0 {
|
||||||
|
var err error
|
||||||
|
f, err = os.Open(flag.Arg(0))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
banks, err := readBatteries(f)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sum1, sum2 uint
|
||||||
|
for _, bank := range banks {
|
||||||
|
power1 := bestPowerPart1(bank)
|
||||||
|
power2 := bestPowerPart2(bank)
|
||||||
|
if *debug {
|
||||||
|
for _, b := range bank {
|
||||||
|
fmt.Print(b)
|
||||||
|
}
|
||||||
|
fmt.Println(":", power1, power2)
|
||||||
|
}
|
||||||
|
sum1 += power1
|
||||||
|
sum2 += power2
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("sum (part 1):", sum1)
|
||||||
|
fmt.Println("sum (part 2):", sum2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bestPowerPart1(bank []uint8) uint {
|
||||||
|
// i := maxIndex(bank[:len(bank)-1])
|
||||||
|
// j := maxIndex(bank[i+1:]) + i + 1
|
||||||
|
// return uint(bank[i])*10 + uint(bank[j])
|
||||||
|
return bestPower(bank, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bestPowerPart2(bank []uint8) uint {
|
||||||
|
return bestPower(bank, 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bestPower(bank []uint8, batteries int) uint {
|
||||||
|
if len(bank) < batteries {
|
||||||
|
panic(fmt.Sprintf("bank (%d) is smaller than requested batteries (%d)", len(bank), batteries))
|
||||||
|
}
|
||||||
|
var joltage uint
|
||||||
|
var i int
|
||||||
|
for j := batteries - 1; j >= 0; j-- {
|
||||||
|
k := maxIndex(bank[i : len(bank)-j])
|
||||||
|
k += i
|
||||||
|
i = k + 1
|
||||||
|
joltage += uint(bank[k]) * uint(math.Pow10(j))
|
||||||
|
}
|
||||||
|
return joltage
|
||||||
|
}
|
||||||
|
|
||||||
|
func maxIndex[S ~[]E, E cmp.Ordered](x S) int {
|
||||||
|
if len(x) < 1 {
|
||||||
|
panic("maxIndex: empty list")
|
||||||
|
}
|
||||||
|
i := 0
|
||||||
|
for j := 1; j < len(x); j++ {
|
||||||
|
if x[j] > x[i] {
|
||||||
|
i = j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
11
go.mod
Normal file
11
go.mod
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
module git.bernotas.lt/sewiti/advent-of-code-2025
|
||||||
|
|
||||||
|
go 1.25.5
|
||||||
|
|
||||||
|
require github.com/stretchr/testify v1.11.1
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
10
go.sum
Normal file
10
go.sum
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
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/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
Reference in New Issue
Block a user