## Advent of code Day 10

Oforth examples. Feel free to post your own code.

### Advent of code Day 10

I'm doing this years advent of code in python, and I was trying the challenge for today in oforth, it was fun. I really got stuck in debugging my loops for a while though, so I've learnt how to better debug in oforth, when you get used to it it's actually very powerful.

As normally the code is full of inefficiencies and things a good programmer wouldn't do, but I was thinking I'd share this little example as well.

--- Day 10: Balance Bots ---

You come upon a factory in which many robots are zooming around handing small microchips to each other.

Upon closer examination, you notice that each bot only proceeds when it has two microchips, and once it does, it gives each one to a different bot or puts it in a marked "output" bin. Sometimes, bots take microchips from "input" bins, too.

Inspecting one of the microchips, it seems like they each contain a single number; the bots must use some logic to decide what to do with each chip. You access the local control computer and download the bots' instructions (your puzzle input).

Some of the instructions specify that a specific-valued microchip should be given to a specific bot; the rest of the instructions indicate what a given bot should do with its lower-value or higher-value chip.

For example, consider the following instructions:

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.

In the end, output bin 0 contains a value-5 microchip, output bin 1 contains a value-2 microchip, and output bin 2 contains a value-3 microchip. In this configuration, bot number 2 is responsible for comparing value-5 microchips with value-2 microchips.

Based on your instructions, what is the number of the bot that is responsible for comparing value-61 microchips with value-17 microchips?

--- Part Two ---

What do you get if you multiply together the values of one chip in each of outputs 0, 1, and 2?

Both parts of this puzzle are complete! They provide two gold stars: **

If you still want to see it, you can get your puzzle input.

Code: Select all
`#!/usr/bin/oforthimport: collect\ Hash of which bots are holding which valuestvar: botsHash new to bots\ Hash of output valuestvar: outputsHash new to outputs\ Opens file with given name for reading: openFile \ filename -- aFile  File new dup open(File.READ); \ open file with input\ Reads all lines from an open file to an ArrayBuffer: readLines \ file(open) -- ArrayBuffer  ArrayBuffer new  while ( over readLine dup notNull )    [ over add ]  drop nip ;\ gives value to a bot, if the bot doesn't exist it gets created: givebot \ value bot#  --  dup bots keyAt isNull    ifTrue: [ swap ArrayBuffer new tuck add bots insert ]    else: [ bots valueAt add ] ;\ gives value to output, creates if doesn't exist: giveout \ bot# value --  dup outputs keyAt isNull    ifTrue: [ swap ArrayBuffer new tuck add outputs insert ]    else: [ outputs valueAt add ] ;\ get second word in a sentence as an int: 2ndint \ String -- Int  words at(2) asInteger ;\ adds a bot and its value to botsbuffer: addBot \ String --   dup words at(6) asInteger swap  2ndint swap  givebot ;\ checks if string starts with the word "value": isValue \ String - ?  words first "value" == ;\ checks if string starts with the word "bot": isBot \ String - ?  words first "bot" == ;\ checks if the bot is already initialized\ and that it has 2 values that it can give out: canActivate \ String - ?  2ndint  dup bots keyAt isNull    ifTrue: [ drop false return ]  bots valueAt size 2 = ;\ activates a bot and follows the command: activate \ string --  dup 2ndint  bots valueAt sort dup second swap first  3 pick words at(6) "bot" ==    ifTrue: [ 3 pick words at(7) asInteger givebot ]    else:   [ 3 pick words at(7) asInteger giveout ]  over words at(11) "bot" ==    ifTrue: [ swap words at(12) asInteger givebot ]    else:   [ swap words at(12) asInteger giveout ] ;\ handles one line, and throws it away if it can be handled\ else puts it back at the end of the ArrayBuffer: handle \ ArrayBuffer -- ArrayBuffer   dup removeAt(1)  dup isValue    ifTrue: [ addBot return ]  dup isBot  over canActivate and    ifTrue: [ activate return ]  \ Couldn't do anything with the instruction for now, so we'll  \ just add it back in the end of the queue  over add ;\ loops through the list of lines until it has handled every line: loopThrough  \ ArrayBuffer -- Empty ArrayBuffewhile( dup size ) [ handle ] drop ;: findbot \ ArrayBuffer -- key| o | bots forEach: o [ dup o value == ifTrue: [ drop o key return ] ] ;: getoutput  outputs valueAt first ;"day10" openFile dup readLines swap close  loopThrough[61, 17] dup findbot "Bot" . . "handles" . dup first . "and" . second .cr"Output 0 * 1 * 2:" . 0 getoutput 1 getoutput 2 getoutput * * .cr`
sotolf

Posts: 55
Joined: 30 Jul 2015 15:53

### Re: Advent of code Day 10

Hi,

Thank you for sharing.
Your code in Oforth has improved a lot !

1) In Oforth, files are collections of lines.
You can use methods on collections on files.

For instance :
Code: Select all
`\ Return a list of all lines into a file"afile" File new map( #yourself)`

Code: Select all
`\ Return a list of all size of lines into a file"afile" File new map( #size )`

Code: Select all
`\ Returns lines with size greater than 20"afile" File new mapIf( #[ size 20 >= ], #yourself )`

2) If you test for null, you can you #ifNull: or ifNotNull:

Of course, you can add a #else: after if necessary

Code: Select all
`: givebot \ value bot#  --  dup bots keyAt    ifNull: [ swap ArrayBuffer new tuck add bots insert ]    else:   [ bots valueAt add ] ;`

3) #givebot and #giveout are really similar.
This needs to be factored

4) Some shotcuts :
at(2) --> second
removeAt(1) --> removeFirst
findbot --> keyAt

5) I don't like your activate word

Its obvious that you are becoming a lot more familiar with Oforth. Great !

Franck
Franck

Posts: 163
Joined: 29 Oct 2014 19:01

### Re: Advent of code Day 10

As always, thank you for all the tips, the ifNull function is very cool.

I have to say I really like the nil punning possibility with booleans, since their just numbers it's quite practical.

and Yeah, there are a lot of factoring possible, but at the time I posted it was 04:00 and I needed some sleep, I was just so happy that I got it to work

I'm not sure if it's feasable to do the problem without the tvars, it feels a bit dirty, but it would clutter the code up so much having to drag the two hashes around into all functions, and it would make the stack juggling a nightmare.

I have to say though that I was going into the thing thinking it would be very hard, and barred some stupid mistakes that was keeping me down.

I'm starting to see more possibilities for factoring every time that I write a new thing in oforth, and every time it surprises me with having some elegant ways of doing stuff. It sure has a bit of a steep learning curve some times, but man is it fun
sotolf

Posts: 55
Joined: 30 Jul 2015 15:53