day19, struggling part2, not quite yet

This commit is contained in:
efim 2023-12-19 11:00:59 +00:00
parent 5f62ea45f7
commit 52beb4196f
3 changed files with 205 additions and 20 deletions

57
day19/intervals.go Normal file
View File

@ -0,0 +1,57 @@
package day19
import (
"sort"
)
func merge(intervals [][]int) [][]int {
const start, end = 0, 1
var merged [][]int
if len(intervals) > 1 {
sort.Slice(intervals, func(i, j int) bool {
return intervals[i][start] < intervals[j][start]
})
}
for _, interval := range intervals {
last := len(merged) - 1
if last < 0 || interval[start] > merged[last][end] {
merged = append(merged,
[]int{start: interval[start], end: interval[end]},
)
} else if interval[end] > merged[last][end] {
merged[last][end] = interval[end]
}
}
return merged[:len(merged):len(merged)]
}
func applyLessThan(intervals [][]int, n int) [][]int {
var lessers [][]int
for _, interval := range intervals {
from := interval[0]
if from >= n {
continue
}
lessers = append(lessers, []int{from, n-1})
}
return lessers
}
func applyMoreThan(intervals [][]int, n int) [][]int {
var greaters [][]int
for _, interval := range intervals {
to := interval[1]
if to <= n {
continue
}
greaters = append(greaters, []int{n+1, to})
}
// log.Printf(">>>> in applyMoreThan %d to %+v ; result %+v", n, intervals, greaters)
return greaters
}

View File

@ -25,3 +25,19 @@ with special cases for "R" and "A"
so. have funciton from OpeartionData & Detail -> true/false
if true take the destination, if false, check next
* well. only way to do this is with intervals
so, sorter check takes in interval.
then for each of the rule,
call first rule with full interval,
deduct first rule (for those that don't match) and pass to second.
deduct second and pass to next
A will return full
R will return empty
and results from each rule application should be joined
so. i need interval deduction
and i need interval join

View File

@ -28,9 +28,20 @@ func Run() int {
log.Printf("yay, got sorters\n%+v\nand details\n%+v", sorters, details)
countApproved := CountApprovedDetails(details, sorters)
// countApproved := CountApprovedDetails(details, sorters)
result := 0
return countApproved
fullIntervals := AttrIntervals{
"x": [][]int{[]int{1, 4000}},
"m": [][]int{[]int{1, 4000}},
"a": [][]int{[]int{1, 4000}},
"s": [][]int{[]int{1, 4000}},
}
andChecked := processInterval(fullIntervals, "qqz", sorters)
log.Print("got and checked ", andChecked)
return result
}
func CountApprovedDetails(details []DetailData, sorters map[string]SorterData) int {
@ -80,7 +91,9 @@ func CountApprovedDetails(details []DetailData, sorters map[string]SorterData) i
}
type Operation rune
const (LessThan Operation = '<'
const (
LessThan Operation = '<'
MoreThan Operation = '>'
)
@ -104,7 +117,7 @@ func ReadSorters(sortersText string) map[string]SorterData {
lines := strings.Split(sortersText, "\n")
for _, line := range lines {
sorter := ReadSorterLine(line)
sorter := SimplifyOperation( ReadSorterLine(line) )
result[sorter.Name] = sorter
}
@ -200,7 +213,7 @@ func ReadDetailLine(line string) (result DetailData) {
func ProcessDetail(d DetailData, sorters map[string]SorterData) (isAccepted bool) {
curSorterName := "in"
for (curSorterName != "A" && curSorterName != "R") {
for curSorterName != "A" && curSorterName != "R" {
sorter, found := sorters[curSorterName]
if !found {
panic(fmt.Sprint("error finding soter ", curSorterName))
@ -231,3 +244,102 @@ func (o OperationData)IsDetailPassing(d DetailData) bool {
panic(fmt.Sprint("unknown operation. ", o, d))
}
type AttrIntervals map[string][][]int
func (o OperationData) getPassingIntervals(i AttrIntervals) AttrIntervals {
result := make(AttrIntervals, 0)
for key, value := range i {
result[key] = value
}
operationKey := o.AttrName
operatedIntervals := result[operationKey]
switch o.Operation {
case LessThan:
result[operationKey] = applyLessThan(operatedIntervals, o.Num)
case MoreThan:
result[operationKey] = applyMoreThan(operatedIntervals, o.Num)
}
return result
}
func (o OperationData) getFailingIntervals(i AttrIntervals) AttrIntervals {
result := make(AttrIntervals, 0)
for key, value := range i {
result[key] = value
}
operationKey := o.AttrName
operatedIntervals := result[operationKey]
switch o.Operation {
case LessThan:
result[operationKey] = applyMoreThan(operatedIntervals, o.Num-1)
case MoreThan:
result[operationKey] = applyLessThan(operatedIntervals, o.Num+1)
}
return result
}
func processInterval(i AttrIntervals, sorterName string, sorters map[string]SorterData) AttrIntervals {
result := AttrIntervals{
"x": [][]int{},
"m": [][]int{},
"a": [][]int{},
"s": [][]int{},
}
if sorterName == "A" {
return i
}
if sorterName == "R" {
return result
}
s := sorters[sorterName]
log.Printf("> starting interval check for %s (%+v) on %+v", sorterName, s, i)
intervalsPassingOnThisStep := i
for _, operation := range s.Operations {
intervalsPassing := operation.getPassingIntervals(intervalsPassingOnThisStep)
log.Printf(">> %s; in operation %+v. passing are %+v", sorterName, operation, intervalsPassing)
ofThoseAreAccepted := processInterval(intervalsPassing, operation.SentToName, sorters)
result = MergeAuthIntervals(result, ofThoseAreAccepted)
log.Printf(">> %s; results so far are %+v", sorterName, result)
intervalsFailingAndPassedToNextCheck := operation.getFailingIntervals(i)
log.Printf(">> %s; failing for the next step %+v", sorterName, intervalsFailingAndPassedToNextCheck)
intervalsPassingOnThisStep = intervalsFailingAndPassedToNextCheck
}
log.Printf(">> %s; about to go into DEFAULT", sorterName)
intervalsAfterDefault := processInterval(intervalsPassingOnThisStep, s.DefaultState, sorters)
log.Printf(">> %s; after defaul. passing are %+v", sorterName, intervalsAfterDefault)
result = MergeAuthIntervals(result, intervalsAfterDefault)
log.Printf(">> %s; results after default %+v", sorterName, result)
return result
}
func MergeAuthIntervals(a AttrIntervals, b AttrIntervals) AttrIntervals {
result := AttrIntervals{
"x": [][]int{},
"m": [][]int{},
"a": [][]int{},
"s": [][]int{},
}
for key := range result {
aAttrIntervals := a[key]
bAttrIntervals := b[key]
allIntervals := append(aAttrIntervals, bAttrIntervals...)
result[key] = merge(allIntervals)
}
return result
}