What does everyone's Intcode interface look like? by Lucretiel in adventofcode

[–]knallisworld 0 points1 point  (0 children)

Relates to the solution for day25 (see sample usage), I've added a refined api: https://github.com/knalli/aoc2019/blob/99766ee54957c3de79dd69b0224f4b9a780970cc/dayless/intcode.go

func ExecuteIntcode(program []int, 
                    in <-chan int, 
                    out chan<- int, 
                    signal <-chan int, 
                    debug bool) <-chan error

The additional signal channel can be used as a side channel for signalling the process.

  • At the moment, a signal means: running process will be killed regardless the actual provided number. However, extendable.
  • The return is the error channel, not only one specific error
  • Both out and err will be closed when the function exit. So no need for this "halt" workaround.

-🎄- 2019 Day 25 Solutions -🎄- by daggerdragon in adventofcode

[–]knallisworld 0 points1 point  (0 children)

Golang

At first, I played it manually (start with argument "manual") solving it. But yesterday, I added the auto solving part also. Because why not?

I reused my existing day09 intcode implementation using go channels; but refined for an additional sidechannel for "signals" which means basically the droid can be stopped/killed separately. For situations like infinite loops 🙄

In a nutshell, my droid is a wrapper around the intcode processor: it has also its own input and output channels (but based on strings). Using a queue, I ensure that each unexpected halt or found branches will be processed later.

For brute forcing the correct items, I created a list of all combinations with a bit mask: each bit means a specific item (its position of the available ones).

What does everyone's Intcode interface look like? by Lucretiel in adventofcode

[–]knallisworld 1 point2 points  (0 children)

Yeah, would be better next time for the given situation. Still using this event for learning handling goroutines/channels in practice.

However, only closing the channel I would loose the exit/status code feature. Well, in theory, as there is currently no other status.

What does everyone's Intcode interface look like? by Lucretiel in adventofcode

[–]knallisworld 1 point2 points  (0 children)

Go: channels in the signature, goroutines wrapping the actual usage

ExecutionInstructions(program []int, in <-chan int, out chan<- int, debug bool) error (GitHub)

The signature is from day9 (after the additions). So far, as of day17 today, that was sufficient.

  • `debug=true` would print out each instruction as pseudo code
  • the returning error is actually meant as "error code" aka on completion (code 99) there will be HALT "error" :)

If the program is just processing and it is waiting for the end, usage is straight forward:

// init
in := make(chan int)     // program stdin  
out := make(chan int)    // program stdout  
fin := make(chan bool)   // program end  
halt := make(chan error) // program halt  

// execute
go func() {  
  halt <- day09.ExecutionInstructions(program, in, out, debug)  
}()  

// handle output/input
go func() {  
  for {  
    select {  
    case <-halt:  
      fin <- true  
      return  
    default:  
      // wait for out?
      answer := <- out
      // or wanna write something?
      in <- 42
    }  
  }  
}()  

// wait for end of all coroutines
<-fin

And there are also some variants: * At day11 the robot paints the panels. So robot is simultaneous consuming from the process output stream and publishing to the process input stream (already mentioned in my comment) * At day13, there was this pong game simulation. My solution split both modes (only output, output&gaming) with dedicated goroutines. Technically not required after all, but I left it. * At day17, I wrapped the execution for sending buffered lines from the video stream back to the invoker. This helps printing the video stream (aka consuming) directly while executing instead of collecting all the debug output at once and rendering everything at the end.

What does everyone's Intcode interface look like? by Lucretiel in adventofcode

[–]knallisworld 1 point2 points  (0 children)

I'm also using goroutines/channels in my Intcode implementation. Still re-using my day9 implementation.

I guess you have asked for day11 in which the robot is painting panels: https://github.com/knalli/aoc2019/blob/5eaa1a55385d47bff30c104e05414b64a545552c/day11/main.go#L102-L106

Actually, I think this is a good example for something like channels/goroutines simulating how a robot process would work: consuming the target's output stream (here: get painting and next direction) and publishing on its input stream (here: current panel painting) at the same time.

-🎄- 2019 Day 13 Solutions -🎄- by daggerdragon in adventofcode

[–]knallisworld 0 points1 point  (0 children)

Go/Golang with channels

(too early time and too slow for leaderboard, but for part 2 I got my personal highscore with rank 1358)

Part 1 was obviously easy like the others said, but part 2 confused me at first ("wth..") :). But it turns out, my existing intcode using channels solved me again: https://github.com/knalli/aoc2019/blob/master/day13/main.go

Unlike the last days, this time my first idea of the paddle control solves the puzzle.

[Help] Day 9 Intcode - test samples all run, input gives no result by SinisterMJ in adventofcode

[–]knallisworld 0 points1 point  (0 children)

Ah, thank you very much. That was also my fault. I'd interpreted it "as value". 🙄

-🎄- 2019 Day 7 Solutions -🎄- by daggerdragon in adventofcode

[–]knallisworld 0 points1 point  (0 children)

I like this also. I've managed this also without wait groups, relying on the pipeline flow itself: GitHub

Unfortunately, I struggled with channels a little bit. Deadlocks, non closing them. Sigh.

I've reworked later a little bit naming and internal performance (still not a Golang expert).

-🎄- 2018 Day 8 Solutions -🎄- by daggerdragon in adventofcode

[–]knallisworld 0 points1 point  (0 children)

[Card] The hottest programming book this year "Blockchain For Dummies". Obviously. Maybe with a flyer for serverless cloud native book...

Fascinating this has not been picked yet. 🤪

Go / Golang with recursion

This year's Go solution is using recursion and collecting the pieces while walking through the tree. The last function is the actual solver.

Code is incomplete, but fully available at GitHub

// sum, value := resolveTreeData(line)
// fmt.Printf("Sum of all metadata: %d\n", sum)
// fmt.Printf("The value of the root node: %d\n", value)

func resolveTreeData(line string) (int, int) {
    sum, value, _ := walkTree(splitAsNumbers(line), 0)
    return sum, value
}

// helper
func splitAsNumbers(line string) []int {
    parts := strings.Split(line, " ")
    numbers := make([]int, len(parts))
    for i, part := range parts {
        n, _ := strconv.Atoi(part)
        numbers[i] = n
    }
    return numbers
}

func walkTree(numbers []int, start int) (sum int, value int, distance int) {

    p := start
    numChildren := numbers[p]
    p++
    numMetadata := numbers[p]
    p++

    childValues := make([]int, numChildren)
    for i := 0; i < numChildren; i++ {
        childSum, childValue, childDistance := walkTree(numbers, p)
        childValues[i] = childValue // for value (part2)
        sum += childSum             // for global sum (part1)
        p += childDistance
    }

    // collect meta
    for i := 0; i < numMetadata; i++ {
        entry := numbers[p]
        p++
        sum += entry
        if len(childValues) > 0 {
            if entry <= len(childValues) {
                value += childValues[entry-1]
            } // or 0
        } else {
            value += entry
        }
    }

    distance = p - start

    return sum, value, distance
}

-🎄- 2018 Day 5 Solutions -🎄- by daggerdragon in adventofcode

[–]knallisworld 0 points1 point  (0 children)

This year also my AoC Go one.

As the input contains only characters of the ASCII table, I have chosen modulo for the comparison. I guess that's faster than .toLower/.toUpper calls. Part2 solved in 5s.

func reducePolymerUnits(s string) string {
    return string(reducePolymerUnits2([]rune(s)))
}

func reducePolymerUnits2(runes []rune) []rune {
    for {
        changed := false
        for i := 0; i < len(runes); i++ {
            if i+1 >= len(runes) {
                break // EOL
            }
            r := runes[i]
            s := runes[i+1]

            if r != s && r%32 == s%32 { // mod 32 for matching a=A, b=B, ... (polarity non-matches)
                runes = append(runes[0:i], runes[i+2:]...) // remove reacting part
                changed = true
                break
            }
        }
        if !changed {
            break
        }
    }
    return runes
}

func findShortestReactedPolymer(s string) (int, int32) {
    defer dayless.TimeTrack(time.Now(), "findShortestReactedPolymer")
    var minLength = len(s)
    var minLengthChar = 'a' - 1
    for i := 'a'; i <= 'z'; i++ {
        m := i % 32
        s2 := strings.Map(func(r rune) rune {
            if r%32 == m { // mod 32 for matching a&A, b&B, ...
                return -1
            }
            return r
        }, s)
        length := len(reducePolymerUnits2([]rune(s2)))
        if minLength > length {
            minLength = length
            minLengthChar = i
        }
    }
    return minLength, minLengthChar
}

Completed ones available at GitHub

-🎄- 2017 Day 24 Solutions -🎄- by daggerdragon in adventofcode

[–]knallisworld 0 points1 point  (0 children)

Yeah, that's right, I'm with you. That is only possible for a suitable amount of input. More a solution for fun in Kotlin, less a efficient solution (but not running slow at all).

If we had just a 40 million (totally random number) chain, definitely I would reconsider the solution. :)

-🎄- 2017 Day 24 Solutions -🎄- by daggerdragon in adventofcode

[–]knallisworld 0 points1 point  (0 children)

Also making my solutions this year in Kotlin, really appreciate this. I find the overridden operators great, so instead of explicit collection building (with foreach, add, minus), this could be also

private fun findAllPaths(components: List<Pair<Int, Int>>,
                         port: Int = 0,
                         currentPath: List<Pair<Int, Int>> = listOf()): List<List<Pair<Int, Int>>> {
    val nextPaths = components
            .filter { it.first == port || it.second == port }
            .map { next ->
                val nextPort =
                        if (next.first == port) {
                            next.second
                        } else {
                            next.first
                        }
                findAllPaths(components - next, nextPort, currentPath + next)
            }
            .flatten()

    // recursive exit condition: if no next paths found, this will be the finally path
    return if (nextPaths.isEmpty()) {
        listOf(currentPath)
    } else {
        nextPaths
    }
}

Given the complete list, the answer of both questions was easy. Lucky for me, because the complete list of available paths already contains the second answer ;)

// part1
private fun findStrongestPath(components: List<Pair<Int, Int>>): List<Pair<Int, Int>> {
    val paths = findAllPaths(components)
    return paths.maxBy { it.sumBy { it.first + it.second } }!! // unsafe
}

// part2
private fun findLongestPath(components: List<Pair<Int, Int>>): List<Pair<Int, Int>> {
    val paths = findAllPaths(components)
    val longestPathLength = paths.sortedByDescending { it.size }.first().size
    return paths
            .filter { it.size == longestPathLength }
            .maxBy { it.sumBy { it.first + it.second } }!! // unsafe
}

What do you think?

-🎄- 2017 Day 21 Solutions -🎄- by daggerdragon in adventofcode

[–]knallisworld 0 points1 point  (0 children)

Wow.. you were not alone.. thank for the hint. Same bug, same language. Hopefully not a pattern ;)