day19, struggling part2, not quite yet
This commit is contained in:
parent
5f62ea45f7
commit
52beb4196f
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue