day 5
This commit is contained in:
parent
ce0ccaaafa
commit
ab99f807e8
@ -1,8 +1,11 @@
|
||||
package aocutils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"iter"
|
||||
)
|
||||
|
||||
func SplitComma(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
@ -18,6 +21,22 @@ func SplitComma(data []byte, atEOF bool) (advance int, token []byte, err error)
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
func SplitString(s string) bufio.SplitFunc {
|
||||
sep := []byte(s)
|
||||
return func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
if atEOF && len(data) == 0 {
|
||||
return 0, nil, nil
|
||||
}
|
||||
if i := bytes.Index(data, sep); i >= 0 {
|
||||
return i + len(sep), data[0:i], nil
|
||||
}
|
||||
if atEOF {
|
||||
return len(data), data, nil
|
||||
}
|
||||
return 0, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func ReadString(r io.Reader) (string, error) {
|
||||
buff, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
@ -25,3 +44,95 @@ func ReadString(r io.Reader) (string, error) {
|
||||
}
|
||||
return string(buff), nil
|
||||
}
|
||||
|
||||
type Logger interface {
|
||||
Printf(string, ...interface{})
|
||||
Println(...interface{})
|
||||
}
|
||||
|
||||
type Context struct {
|
||||
Body io.Reader
|
||||
Logger Logger
|
||||
Context context.Context
|
||||
}
|
||||
|
||||
func (c *Context) Scanner(split ...bufio.SplitFunc) *bufio.Scanner {
|
||||
s := bufio.NewScanner(c.Body)
|
||||
if len(split) == 1 {
|
||||
s.Split(split[0])
|
||||
}
|
||||
if len(split) > 2 {
|
||||
panic("too many split line handlers")
|
||||
}
|
||||
return s
|
||||
}
|
||||
func (c *Context) BodyString() (string, error) {
|
||||
return ReadString(c.Body)
|
||||
}
|
||||
func (c *Context) BodyBytes() ([]byte, error) {
|
||||
return io.ReadAll(c.Body)
|
||||
}
|
||||
|
||||
func (c *Context) Printf(format string, args ...interface{}) {
|
||||
if c.Logger != nil {
|
||||
c.Logger.Printf(format, args...)
|
||||
}
|
||||
}
|
||||
func (c *Context) Println(args ...interface{}) {
|
||||
if c.Logger != nil {
|
||||
c.Logger.Println(args...)
|
||||
}
|
||||
}
|
||||
|
||||
type CustomScanner[T scannable, K any] struct {
|
||||
val K
|
||||
err error
|
||||
|
||||
inner scannable
|
||||
mapFunc func(T) (K, error)
|
||||
}
|
||||
|
||||
func (s *CustomScanner[T, K]) From(t T) {
|
||||
s.inner = t
|
||||
}
|
||||
func (s *CustomScanner[T, K]) MapFunc(f func(t T) (K, error)) {
|
||||
s.mapFunc = f
|
||||
}
|
||||
|
||||
func (s *CustomScanner[T, K]) Value() K {
|
||||
return s.val
|
||||
}
|
||||
func (s *CustomScanner[T, K]) Values() iter.Seq[K] {
|
||||
return func(yield func(K) bool) {
|
||||
for s.Scan() {
|
||||
if !yield(s.Value()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type scannable interface {
|
||||
Scan() bool
|
||||
}
|
||||
|
||||
func (s *CustomScanner[T, K]) Scan() bool {
|
||||
if s.err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !s.inner.Scan() {
|
||||
return false
|
||||
}
|
||||
|
||||
s.val, s.err = s.mapFunc(s.inner.(T))
|
||||
if s.err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *CustomScanner[T, K]) Err() error {
|
||||
return s.err
|
||||
}
|
||||
|
||||
@ -6,12 +6,14 @@ import (
|
||||
"io"
|
||||
"iter"
|
||||
"strconv"
|
||||
|
||||
"git.bizdoc.ro/gabi-public/Advent-of-Code.git/aocutils"
|
||||
)
|
||||
|
||||
func Day1Part1(r io.Reader, l Logger) (any, error) {
|
||||
func Day1Part1(ctx aocutils.Context) (any, error) {
|
||||
dial := 50
|
||||
solution := 0
|
||||
for pair := range day1GetPairs(r) {
|
||||
for pair := range day1GetPairs(ctx.Body) {
|
||||
dial += pair.MustValue()
|
||||
dial %= 100
|
||||
if dial < 0 {
|
||||
@ -20,34 +22,34 @@ func Day1Part1(r io.Reader, l Logger) (any, error) {
|
||||
if dial == 0 {
|
||||
solution += 1
|
||||
}
|
||||
l.Printf("The dial is rotated %s(%d) to point at 0 `once` \n", pair, pair.MustValue())
|
||||
ctx.Printf("The dial is rotated %s(%d) to point at 0 `once` \n", pair, pair.MustValue())
|
||||
}
|
||||
|
||||
return solution, nil
|
||||
}
|
||||
|
||||
func Day1Part2Slow(r io.Reader, l Logger) (any, error) {
|
||||
func Day1Part2Slow(ctx aocutils.Context) (any, error) {
|
||||
dial := 50
|
||||
solution := 0
|
||||
for pair := range day1GetPairs(r) {
|
||||
for pair := range day1GetPairs(ctx.Body) {
|
||||
nextDial, count := day1AdvanceSimulation(dial, pair.MustValue())
|
||||
dial = nextDial
|
||||
solution += count
|
||||
|
||||
if count > 0 {
|
||||
l.Printf("The dial is rotated %s(%d) to point at %d, during this points to 0 (%d)\n", pair, pair.MustValue(), dial, count)
|
||||
ctx.Printf("The dial is rotated %s(%d) to point at %d, during this points to 0 (%d)\n", pair, pair.MustValue(), dial, count)
|
||||
} else {
|
||||
l.Printf("The dial is rotated %s(%d) to point at %d\n", pair, pair.MustValue(), dial)
|
||||
ctx.Printf("The dial is rotated %s(%d) to point at %d\n", pair, pair.MustValue(), dial)
|
||||
}
|
||||
}
|
||||
|
||||
return solution, nil
|
||||
}
|
||||
|
||||
func Day1Part2Fast(r io.Reader, l Logger) (any, error) {
|
||||
func Day1Part2Fast(ctx aocutils.Context) (any, error) {
|
||||
dial := 50
|
||||
solution := 0
|
||||
for pair := range day1GetPairs(r) {
|
||||
for pair := range day1GetPairs(ctx.Body) {
|
||||
value := pair.MustValue()
|
||||
|
||||
nextDial, count := day1Advance(dial, value)
|
||||
@ -56,9 +58,9 @@ func Day1Part2Fast(r io.Reader, l Logger) (any, error) {
|
||||
solution += count
|
||||
|
||||
if count > 0 {
|
||||
l.Printf("The dial is rotated %s(%d) to point at %d, during this points to 0 (%d)\n", pair, pair.MustValue(), dial, count)
|
||||
ctx.Printf("The dial is rotated %s(%d) to point at %d, during this points to 0 (%d)\n", pair, pair.MustValue(), dial, count)
|
||||
} else {
|
||||
l.Printf("The dial is rotated %s(%d) to point at %d\n", pair, pair.MustValue(), dial)
|
||||
ctx.Printf("The dial is rotated %s(%d) to point at %d\n", pair, pair.MustValue(), dial)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -50,8 +49,8 @@ func (s *day2Scanner) Bounds() (int, int) {
|
||||
return s.a, s.b
|
||||
}
|
||||
|
||||
func Day2Part1Simple(r io.Reader, l Logger) (any, error) {
|
||||
input, err := aocutils.ReadString(r)
|
||||
func Day2Part1Simple(ctx aocutils.Context) (any, error) {
|
||||
input, err := ctx.BodyString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read input: %s", err)
|
||||
}
|
||||
@ -94,8 +93,8 @@ func Day2Part1Simple(r io.Reader, l Logger) (any, error) {
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
func Day2Part2Simple(r io.Reader, l Logger) (any, error) {
|
||||
input, err := aocutils.ReadString(r)
|
||||
func Day2Part2Simple(ctx aocutils.Context) (any, error) {
|
||||
input, err := ctx.BodyString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read input: %s", err)
|
||||
}
|
||||
@ -154,16 +153,14 @@ func Day2Part2Simple(r io.Reader, l Logger) (any, error) {
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
func Day2Part1(r io.Reader, logger Logger) (any, error) {
|
||||
inputScanner := bufio.NewScanner(r)
|
||||
inputScanner.Split(aocutils.SplitComma)
|
||||
scanner := &day2Scanner{scanner: inputScanner, sep: '-'}
|
||||
func Day2Part1(ctx aocutils.Context) (any, error) {
|
||||
scanner := &day2Scanner{scanner: ctx.Scanner(aocutils.SplitComma), sep: '-'}
|
||||
|
||||
var sum int
|
||||
|
||||
for scanner.Scan() {
|
||||
start, end := scanner.Bounds()
|
||||
logger.Println(start, "-", end)
|
||||
ctx.Println(start, "-", end)
|
||||
|
||||
for i := start; i <= end; i++ {
|
||||
str := []byte(strconv.Itoa(i))
|
||||
@ -171,7 +168,7 @@ func Day2Part1(r io.Reader, logger Logger) (any, error) {
|
||||
firstHalf := str[:len(str)/2]
|
||||
secondHalf := str[len(str)/2:]
|
||||
if bytes.Equal(firstHalf, secondHalf) {
|
||||
logger.Println("found ", i)
|
||||
ctx.Println("found ", i)
|
||||
sum += i
|
||||
}
|
||||
}
|
||||
@ -181,16 +178,13 @@ func Day2Part1(r io.Reader, logger Logger) (any, error) {
|
||||
return sum, scanner.Err()
|
||||
}
|
||||
|
||||
func Day2Part2(r io.Reader, logger Logger) (any, error) {
|
||||
inputScanner := bufio.NewScanner(r)
|
||||
inputScanner.Split(aocutils.SplitComma)
|
||||
|
||||
scanner := &day2Scanner{scanner: inputScanner, sep: '-'}
|
||||
func Day2Part2(ctx aocutils.Context) (any, error) {
|
||||
scanner := &day2Scanner{scanner: ctx.Scanner(aocutils.SplitComma), sep: '-'}
|
||||
|
||||
var sum int
|
||||
for scanner.Scan() {
|
||||
start, end := scanner.Bounds()
|
||||
logger.Println(start, "-", end)
|
||||
ctx.Println(start, "-", end)
|
||||
|
||||
for i := start; i <= end; i++ {
|
||||
str := []byte(strconv.Itoa(i))
|
||||
@ -210,7 +204,7 @@ func Day2Part2(r io.Reader, logger Logger) (any, error) {
|
||||
}
|
||||
|
||||
if isInvalid {
|
||||
logger.Println("found ", i)
|
||||
ctx.Println("found ", i)
|
||||
sum += i
|
||||
break
|
||||
}
|
||||
|
||||
@ -3,23 +3,24 @@ package year25
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.bizdoc.ro/gabi-public/Advent-of-Code.git/aocutils"
|
||||
)
|
||||
|
||||
func Day3Part1(r io.Reader, l Logger) (any, error) {
|
||||
return Day3(r, l, 2)
|
||||
func Day3Part1(ctx aocutils.Context) (any, error) {
|
||||
return Day3(ctx, 2)
|
||||
}
|
||||
func Day3Part2(r io.Reader, l Logger) (any, error) {
|
||||
return Day3(r, l, 12)
|
||||
func Day3Part2(ctx aocutils.Context) (any, error) {
|
||||
return Day3(ctx, 12)
|
||||
}
|
||||
func Day3(r io.Reader, logger Logger, size int) (int64, error) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
func Day3(ctx aocutils.Context, size int) (int64, error) {
|
||||
scanner := ctx.Scanner(bufio.ScanLines)
|
||||
var sum int64
|
||||
|
||||
findLargetDigit := func(digits []rune) (rune, int) {
|
||||
largestDigit := rune(0)
|
||||
var largestDigit rune
|
||||
index := 0
|
||||
|
||||
for i := len(digits) - 1; i >= 0; i-- {
|
||||
@ -28,7 +29,7 @@ func Day3(r io.Reader, logger Logger, size int) (int64, error) {
|
||||
index = i
|
||||
}
|
||||
}
|
||||
return rune(largestDigit) - '0', index
|
||||
return largestDigit, index
|
||||
}
|
||||
|
||||
for scanner.Scan() {
|
||||
@ -42,23 +43,46 @@ func Day3(r io.Reader, logger Logger, size int) (int64, error) {
|
||||
for index := range parts {
|
||||
digit, start := findLargetDigit(line[:len(line)+index-len(parts)+1])
|
||||
line = line[start+1:]
|
||||
if digit < 0 || digit > 9 {
|
||||
if digit < '0' || digit > '9' {
|
||||
return 0, fmt.Errorf("ivalid char '%c' in line %s", digit, text)
|
||||
} else {
|
||||
parts[index] = byte(digit)
|
||||
}
|
||||
}
|
||||
logger.Println("line: ", text)
|
||||
|
||||
var partSum int64
|
||||
for _, part := range parts {
|
||||
partSum *= 10
|
||||
partSum += int64(part)
|
||||
partSum, err := strconv.Atoi(string(parts))
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("invalid result %s for line %s", string(parts), text)
|
||||
}
|
||||
logger.Println("got: ", partSum)
|
||||
logger.Println()
|
||||
sum += partSum
|
||||
|
||||
ctx.Println("line: ", text)
|
||||
ctx.Println("got: ", string(parts))
|
||||
ctx.Println()
|
||||
sum += int64(partSum)
|
||||
}
|
||||
|
||||
return sum, scanner.Err()
|
||||
}
|
||||
|
||||
func Day3Compact(input string, size int) (total int64, _ error) {
|
||||
findLargetDigit := func(digits string, skip int) (digit byte, idx int, next string) {
|
||||
for i := len(digits) - 1 - skip; i >= 0; i-- {
|
||||
if digits[i] >= digit {
|
||||
digit, idx = digits[i], i
|
||||
}
|
||||
}
|
||||
return digit, idx, digits[idx+1:]
|
||||
}
|
||||
for _, line := range strings.Split(input, "\n") {
|
||||
var parts = make([]byte, size)
|
||||
for index := range size {
|
||||
parts[index], _, line = findLargetDigit(line, size-1-index)
|
||||
}
|
||||
if partSum, err := strconv.ParseInt(string(parts), 10, 64); err != nil {
|
||||
return 0, fmt.Errorf("invalid result %s", string(parts))
|
||||
} else {
|
||||
total += partSum
|
||||
}
|
||||
}
|
||||
return total, nil
|
||||
}
|
||||
|
||||
@ -2,21 +2,21 @@ package year25
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"git.bizdoc.ro/gabi-public/Advent-of-Code.git/aocutils"
|
||||
"git.bizdoc.ro/private/devkit.git/collections/geometry/v2"
|
||||
)
|
||||
|
||||
const Day4PaperRoll = '@'
|
||||
|
||||
func Day4Part1(r io.Reader, l Logger) (any, error) {
|
||||
func Day4Part1(ctx aocutils.Context) (any, error) {
|
||||
// 4 rolls in 8 adjacent positions
|
||||
const maxAdjacentRolls = 4
|
||||
|
||||
var accessibleRolls int
|
||||
g, err := geometry.ReaderToByteGrid(r)
|
||||
g, err := geometry.ReaderToByteGrid(ctx.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("day4: failed to read grid: %w", err)
|
||||
return nil, fmt.Errorf("day4 part1: failed to read grid: %w", err)
|
||||
}
|
||||
|
||||
for c := range g.Points() {
|
||||
@ -39,14 +39,14 @@ func Day4Part1(r io.Reader, l Logger) (any, error) {
|
||||
return accessibleRolls, nil
|
||||
}
|
||||
|
||||
func Day4Part2(r io.Reader, l Logger) (any, error) {
|
||||
func Day4Part2(ctx aocutils.Context) (any, error) {
|
||||
// 4 rolls in 8 adjacent positions
|
||||
const maxAdjacentRolls = 4
|
||||
|
||||
var totalRemovedRolls int
|
||||
g, err := geometry.ReaderToByteGrid(r)
|
||||
g, err := geometry.ReaderToByteGrid(ctx.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("day4: failed to read grid: %w", err)
|
||||
return nil, fmt.Errorf("day4 part2: failed to read grid: %w", err)
|
||||
}
|
||||
|
||||
for {
|
||||
@ -65,7 +65,7 @@ func Day4Part2(r io.Reader, l Logger) (any, error) {
|
||||
|
||||
if count <= maxAdjacentRolls {
|
||||
removedRolls += 1
|
||||
g.Set(c, '.') // remove grid
|
||||
g.Set(c, '.') // remove roll from grid
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
140
year25/day5.go
Normal file
140
year25/day5.go
Normal file
@ -0,0 +1,140 @@
|
||||
package year25
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"iter"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.bizdoc.ro/gabi-public/Advent-of-Code.git/aocutils"
|
||||
)
|
||||
|
||||
type Day5Interval struct {
|
||||
Start, End int64
|
||||
isRemoved bool
|
||||
}
|
||||
|
||||
type MergedIntervals struct {
|
||||
intervals []*Day5Interval
|
||||
}
|
||||
|
||||
func (m *MergedIntervals) Put(newInterval Day5Interval) {
|
||||
for item := range m.Items() {
|
||||
if newInterval.Start <= item.End && newInterval.End >= item.Start {
|
||||
newInterval.Start = min(newInterval.Start, item.Start)
|
||||
newInterval.End = max(newInterval.End, item.End)
|
||||
|
||||
item.isRemoved = true
|
||||
m.Put(newInterval)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// just in case there are too many intervals
|
||||
m.intervals = slices.DeleteFunc(m.intervals, func(i *Day5Interval) bool {
|
||||
return i.isRemoved
|
||||
})
|
||||
|
||||
m.intervals = append(m.intervals, &newInterval)
|
||||
}
|
||||
func (m *MergedIntervals) Put2(newInterval Day5Interval) {
|
||||
// fast search start, end
|
||||
for item := range m.Items() {
|
||||
if newInterval.Start <= item.End && newInterval.End >= item.Start {
|
||||
newInterval.Start = min(newInterval.Start, item.Start)
|
||||
newInterval.End = max(newInterval.End, item.End)
|
||||
|
||||
item.isRemoved = true
|
||||
m.Put(newInterval)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// insert in order
|
||||
m.intervals = append(m.intervals, &newInterval)
|
||||
}
|
||||
|
||||
func (m *MergedIntervals) CheckItem(itemId int64) (*Day5Interval, bool) {
|
||||
for interval := range m.Items() {
|
||||
if interval.Start <= itemId && itemId <= interval.End {
|
||||
return interval, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (m *MergedIntervals) Items() iter.Seq[*Day5Interval] {
|
||||
return func(yield func(*Day5Interval) bool) {
|
||||
for _, interval := range m.intervals {
|
||||
if !interval.isRemoved {
|
||||
if !yield(interval) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Day5ParseIntervals(s *bufio.Scanner) (intervals *MergedIntervals, err error) {
|
||||
intervals = new(MergedIntervals)
|
||||
for s.Scan() {
|
||||
line := strings.TrimSpace(s.Text())
|
||||
if line == "" {
|
||||
return
|
||||
}
|
||||
|
||||
var newInterval Day5Interval
|
||||
dashIndex := strings.Index(line, "-")
|
||||
newInterval.Start, err = strconv.ParseInt(line[:dashIndex], 10, 64)
|
||||
if err != nil {
|
||||
return intervals, fmt.Errorf("day5: failed to parse line %s. invalid start index: %w", line, err)
|
||||
}
|
||||
newInterval.End, err = strconv.ParseInt(line[dashIndex+1:], 10, 64)
|
||||
if err != nil {
|
||||
return intervals, fmt.Errorf("day5: failed to parse line %s. invalid end index: %w", line, err)
|
||||
}
|
||||
|
||||
intervals.Put(newInterval)
|
||||
}
|
||||
|
||||
return intervals, s.Err()
|
||||
}
|
||||
|
||||
func Day5Part1(ctx aocutils.Context) (int, error) {
|
||||
scanner := ctx.Scanner()
|
||||
intervals, err := Day5ParseIntervals(scanner)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("day5: failed to parse intervals %w", err)
|
||||
}
|
||||
|
||||
var freshIngredients int
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
itemId, err := strconv.ParseInt(line, 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("day5: failed to parse itemId in line %s. %w", line, err)
|
||||
}
|
||||
if interval, ok := intervals.CheckItem(itemId); ok {
|
||||
freshIngredients += 1
|
||||
ctx.Println(itemId, "is fresh because it was found in", interval)
|
||||
} else {
|
||||
ctx.Println(itemId, "is spoiled")
|
||||
}
|
||||
}
|
||||
return freshIngredients, scanner.Err()
|
||||
}
|
||||
|
||||
func Day5Part2(ctx aocutils.Context) (solution int64, _ error) {
|
||||
intervals, err := Day5ParseIntervals(ctx.Scanner())
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("day5: failed to parse intervals %w", err)
|
||||
}
|
||||
|
||||
for interval := range intervals.Items() {
|
||||
solution += interval.End - interval.Start + 1
|
||||
}
|
||||
|
||||
return solution, nil
|
||||
}
|
||||
35
year25/day5.ts
Normal file
35
year25/day5.ts
Normal file
@ -0,0 +1,35 @@
|
||||
const input = ""
|
||||
|
||||
console.log(part1(input))
|
||||
console.log(part2(input))
|
||||
|
||||
type Item = [number, number]
|
||||
const [start, end] = [0, 1]
|
||||
|
||||
function part1(input: string): number {
|
||||
const [db, ids] = parseInput(input)
|
||||
return ids.filter(currentId => {
|
||||
return db.find(id => id[start] <= currentId && id[end] >= currentId)
|
||||
}).length
|
||||
}
|
||||
|
||||
function part2(input: string): number {
|
||||
const [db, _] = parseInput(input)
|
||||
return db.reduce((sum, i) => sum + (i[end] - i[start] + 1), 0)
|
||||
}
|
||||
|
||||
function parseInput(input: string): [Item[], number[]] {
|
||||
const [dbLines, itemsLines] = input.trim().split('\n\n')
|
||||
.map(n => n.trim().split('\n'))
|
||||
|
||||
const db = dbLines.map(line => line.split('-').map(n => parseInt(n, 10)) as Item)
|
||||
.reduce((db: Item[], newItem: Item) => {
|
||||
const mergedInterval = db
|
||||
.filter(item => newItem[start] <= item[end] && newItem[end] >= item[start])
|
||||
.reduce((acc, item) => [Math.min(acc[start], item[start]), Math.max(acc[end], item[end])], newItem)
|
||||
const remaining = db.filter(item => (item[end] < newItem[start] || item[start] > newItem[end]))
|
||||
return [...remaining, mergedInterval] as Item[]
|
||||
}, [] as Item[])
|
||||
|
||||
return [db, itemsLines.map(Number)]
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
package year25
|
||||
|
||||
type Logger interface {
|
||||
Printf(string, ...interface{})
|
||||
Println(...interface{})
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user