Advent of Code 2016 Day10: Balance Bots

This is a series of programming challenges for beginners and experienced Caché programmers.

For an introduction : go to article https://community.intersystems.com/post/advent-code-2016-day1-no-time-ta...

In today's challenge, you have to execute instructions that control how bots are handling microchips.

The input contain instructions that can be something like this :

 

value 5 goes to bot 2
bot 2 gives low to bot 1 and high to bot 0
value 3 goes to bot 1
bot 1 gives low to output 1 and high to bot 0
bot 0 gives low to output 2 and high to output 0
value 2 goes to bot 2

Initially, bot 1 starts with a value-3 chip, and bot 2 starts with a value-2 chip and a value-5 chip.
Because bot 2 has two microchips, it gives its lower one (2) to bot 1 and its higher one (5) to bot 0.
Then, bot 1 has two microchips; it puts the value-2 chip in output 1 and gives the value-3 chip to bot 0.
Finally, bot 0 has two microchips; it puts the 3 in output 2 and the 5 in output 0.

For the complete explanation of the challenge, go to http://adventofcode.com/2016/day/10.

You have to read the instructions found here : http://adventofcode.com/2016/day/10/input, and output the number of the bot that has the microchip 61 and microchip 17.

Apparently, the instructions can not always be executed (e.g. when a bot needs to hand over a microchip that it does not have). In that case, you have to  skip the instruction, and repeat the list of skipped instructions again until all instructions are done (or you know which bot has the two microchips).
 

Once you submit your answer, the second challenge is unlocked. Here you just have to give the content of the output 0, 1 and 2.

We can do both  using the same code, here is what i did :

 

Class AOC2016.Day10 Extends AOC2016.Utils
{

ClassMethod Part1(file As %String = "day10.txt")
{
  #Dim input, instruction, content as %String
  #Dim iInput,fromBot, value as %Integer
  Try {
    Do ..Input(file, .input)
    For {  //repeat until all instructions are executed
      If $Order(input(""))="" Quit  //no more instructions
        Set iInput = ""
        For {
          Set iInput = $Order(input(iInput)) If iInput="" Quit
          Set instruction = input(iInput)
          If $Piece(instruction," ",1)="value" {
            //give microchip to bot
            Do ..GiveToBot("bot",$Piece(instruction," ",6),$Piece(instruction," ",2),.content)
            Kill input(iInput)
else {
            //give hi and low microchip from bot to other bots or output
            Set fromBot = $Piece(instruction," ",2)
            Set value = $Order(content("bot",fromBot,"")) If value="" Continue
            Set value = $Order(content("bot",fromBot,value)) If value="" Continue  //bot has not both microchips to give
            Do ..GiveFromBot(fromBot,$P(instruction," ",6),$Piece(instruction," ",7),$Piece(instruction," ",11),$Piece(instruction," ",12),.content)
            Kill input(iInput)
          }
        }
      }
Catch {
    Write "Error : ",$ZError,!
  }
  Write "bot : ",$Get(content("found")),!
  Write "output 0,1,2 : ",$Order(content("output",0,""))*$Order(content("output",1,""))*$Order(content("output",2,"")),!
}

ClassMethod GiveToBot(type, bot, value, ByRef content)
{
  set content(type,bot,value)=""
  If type="bot",$Data(content("bot",bot,17))&$Data(content("bot",bot,61)) set content("found")=bot
}

ClassMethod GiveFromBot(fromBot, toWhatLow, toNumberLow, toWhatHi, toNumberHi, ByRef content)
{
  #dim hi, low as %Integer
  Set low=$Order(content("bot",fromBot,""))
  Set hi=$Order(content("bot",fromBot,low))
  Kill content("bot",fromBot)
  Do ..GiveToBot(toWhatLow, toNumberLow, low, .content)
  Do ..GiveToBot(toWhatHi, toNumberHi, hi, .content)
}

}

 

Look here for all our solutions so far : https://bitbucket.org/bertsarens/advent2016 and https://github.com/DannyWijnschenk/AdventOfCode2016
 

Here is the list of all Advent of Code 2016 articles  :

1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25 

Comments

  kill
  set fs = ##Class(%Stream.FileCharacter).%New()
  set sc=fs.LinkToFile("c:\advent\input\day10.txt")
  while 'fs.AtEnd {
    set line = fs.ReadLine()
    if $e(line)="v" {
      set $lb(,value,,,type,bot)=$lfs(line," ")
      set list(type, bot, value)=""
    else {
      set $lb(,bot,,,,lowTo,low,,,,highTo,high)=$lfs(line," ")
      set instructions(bot, "low") = $lb(lowTo, low)
      set instructions(bot, "high") = $lb(highTo, high)
    }
  }
  while $d(instructions) {
    set bot=""
    for {
      set bot = $o(list("bot", bot))
      quit:bot=""
      set low = $o(list("bot", bot, ""))
      set high = $o(list("bot", bot, ""), -1)
      continue:low=high
      if low=17,high=61 set result = bot
      set $lb(type, num) = instructions(bot, "low")
      set list(type, num, low) = ""
      set $lb(type, num) = instructions(bot, "high")
      set list(type, num, high) = ""
      kill list("bot", bot)
      kill instructions(bot)
    }
  }
  write !,"Result1 = ",result
  set result2 = 1
  for i=0,1,2 set result2 = result2 * $o(list("output", i, ""))
  write !,"Result2 = ",result2
  quit