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 {
@ -39,7 +50,7 @@ func CountApprovedDetails(details []DetailData, sorters map[string]SorterData) i
approvedDetails := make(chan DetailData)
go func(){
go func() {
wg.Wait()
close(approvedDetails)
}()
@ -49,7 +60,7 @@ func CountApprovedDetails(details []DetailData, sorters map[string]SorterData) i
done := make(chan any)
go func(){
go func() {
for detail := range approvedDetails {
log.Println("got approved ", detail)
count += 1
@ -74,28 +85,30 @@ func CountApprovedDetails(details []DetailData, sorters map[string]SorterData) i
}(d)
}
<- done
<-done
return acceptedScore
}
type Operation rune
const (LessThan Operation = '<'
const (
LessThan Operation = '<'
MoreThan Operation = '>'
)
type OperationData struct {
AttrName string
Operation Operation
Num int
AttrName string
Operation Operation
Num int
SentToName string
String string
String string
}
type SorterData struct {
Name string
Name string
DefaultState string
Operations []OperationData
Operations []OperationData
}
func ReadSorters(sortersText string) map[string]SorterData {
@ -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
}
@ -120,12 +133,12 @@ func ReadSorterLine(line string) (result SorterData) {
result.Name = firstSplit[1]
operationLines := strings.Split(firstSplit[2], ",")
operations := make([]OperationData, len(operationLines) - 1)
operations := make([]OperationData, len(operationLines)-1)
result.Operations = operations
result.DefaultState = operationLines[len(operationLines) - 1]
result.DefaultState = operationLines[len(operationLines)-1]
for i, line := range operationLines[:len(operationLines) - 1] {
for i, line := range operationLines[:len(operationLines)-1] {
operations[i] = ReadOperationLine(line)
}
@ -182,7 +195,7 @@ func ReadDetailsPart(text string) (result []DetailData) {
func ReadDetailLine(line string) (result DetailData) {
attrs := make(map[string]int)
result.Attrs = attrs
line = line[1:len(line)-1]
line = line[1 : len(line)-1]
attrsLine := strings.Split(line, ",")
re := regexp.MustCompile(`(?P<ATTR>\D)=(?P<NUM>\d+)`)
for _, attrLine := range attrsLine {
@ -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))
@ -210,7 +223,7 @@ func ProcessDetail(d DetailData, sorters map[string]SorterData) (isAccepted bool
return curSorterName == "A"
}
func (s SorterData)NextSorterNameFor(d DetailData) string {
func (s SorterData) NextSorterNameFor(d DetailData) string {
for _, operation := range s.Operations {
if operation.IsDetailPassing(d) {
return operation.SentToName
@ -220,7 +233,7 @@ func (s SorterData)NextSorterNameFor(d DetailData) string {
return s.DefaultState
}
func (o OperationData)IsDetailPassing(d DetailData) bool {
func (o OperationData) IsDetailPassing(d DetailData) bool {
detailValue := d.Attrs[o.AttrName]
switch o.Operation {
case LessThan:
@ -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
}