Belated - Advent of Code 2018 Day 1

I know it's late, but I really love the advent of code theme each year to find some project ideas to go out and code something and push myself.

I had the intentions of completing the AOC 2018 before the new year, but I've got 2 young kids (1yo and 4yo), so most nights I just want to sleep.

I've been looking at this on my half hourly commute each day before and after work.

So whilst doing this, I found not many people had posted what they had done and in previous years.

I'd found this helpful when I've got stuck for ideas, so I thought I would post what I've done (that works) and see how others might of implemented a solution.

A full explanation of Day1 part 1 can be found at: https://adventofcode.com/2018/day/1 and the input can be found

at: https://adventofcode.com/2018/day/1/input

A brief description of this exercise is that you recieve a sequence of frequency changes.

Starting with a frequency of 0 you need to loop through the sequence/list adding the value to the frequency and return the last frequency.

Here is the code I tried below:

ClassMethod FreqPart1(Input As %String, ListPlace As %String)
{
// ***** CLEAR existing global *****

// Delete Globals. No update GP list but upload all from file.
KILL ^AOC2018.Day1D,^AOC2018.Day1I 
// Add info to the log.
write "Deleted TEMP globals '^AOC2018.Day1D' & '^AOC2018.Day1I'."
set Input = "+13,-16,+18,+11,+15,+10,-4,-19,+14,-19,-17,-19,-2,+6,+2,+21,+5,+12,-10,-10,+18,-11,+2,+17,-5,+14,+14,-3,-12,+10,+7,-3,+6,-2,+8,-17,-18,-19,-14,+9,-16,-1,-1,+11,-3,+8,-12,+10,+14,+12,-18,+19,-5,+13,+1,+4,+2,+11,-3,-2,+18,+8,-4,+15,-7,-3,+18,+16,+2,-4,-12,-19,-4,+12,+15,-17,+1,-16,-5,+15,+26,+9,+9,-3,-5,+3,+3,-11,-8,-11,-16,+14,+14,+14,+17,+14,+11,-9,+18,-10,-4,-11,-10,-9,+8,+12,-6,-1,-2,+12,-17,-1,+17,-10,+9,+11,+6,+3,+18,+19,+11,-3,+15,-3,-2,+18,+17,+13,+13,-6,+16,+10,+7,-6,-15,-15,-1,+15,+6,-2,-12,+19,-1,+17,+18,-8,-11,-18,+12,-3,-14,+6,-12,+1,-11,-9,+13,-3,-15,-19,-16,-3,+7,+7,-17,-18,+3,-2,-12,-1,+16,+15,+10,+7,-13,+7,+13,+14,+5,+18,-14,-8,-4,+15,-20,-17,-17,+11,-15,-14,-10,-1,+5,-11,+18,-4,-19,+15,-8,+14,-20,-12,+10,-11,-12,+16,-7,-7,+4,-18,-8,+11,+13,-6,+24,+8,+4,-19,+11,+15,+3,-17,+30,+9,+10,+6,-2,+3,+14,+8,-3,-12,+1,+5,-8,+11,+10,+16,+6,+16,+1,+21,+19,+18,+18,+15,+15,+8,+2,-6,-16,+5,-10,+18,-12,+16,+6,+18,-6,-2,+5,-14,-17,-14,-13,-7,+16,-8,-11,-3,+8,-13,+6,+3,-5,+6,+5,+1,+12,+14,+10,+12,-20,+12,-15,+8,+4,-7,-9,-1,+11,-22,-4,-14,-4,-18,+6,+2,+8,-4,-1,+16,-17,-1,-2,-10,-10,-10,+16,+3,-12,+2,-1,+4,-15,+18,-2,-9,-6,-22,+7,+16,-5,+17,+13,+2,-1,+3,-11,+10,-25,-14,+17,-15,+3,+43,+19,+12,+1,-8,+4,+8,-11,-40,-29,-30,-12,+18,-15,-5,-14,+10,-16,+1,-34,-13,-20,-7,+12,+9,+16,-2,-2,+9,+23,+15,-8,-38,-37,-8,-20,+11,-24,-2,+14,-24,-18,+2,-7,+14,+1,+19,-5,-23,-11,-15,+23,+8,-14,+16,-25,-19,+8,-3,-20,+11,-15,-11,-14,+16,-31,+18,+25,+20,-6,+11,+48,-7,-18,-2,-31,+21,-49,+50,-20,-44,+8,-81,+24,-16,-18,+26,-60,+19,-36,-14,-41,+25,-72,-46,+1,-46,-61361,+12,-18,-7,-9,+6,+14,-13,-8,+19,+19,+11,+9,+2,+9,-18,-3,+20,-4,-11,+4,+14,+3,-11,+2,+2,-13,-17,+3,+19,-13,-16,+11,+14,-5,+12,+16,+17,+15,+6,+6,+2,-1,+15,+6,-3,-5,-6,+20,+16,+7,+1,-5,+9,+12,-2,+11,-16,+6,-14,-3,-11,-8,-18,-9,+2,+12,-15,+20,+1,+1,+10,+5,+17,+7,-2,-14,+1,+10,-1,+12,+12,-37,-13,-3,+5,+3,+18,-14,-26,+11,-14,-3,-14,-6,-21,+2,-8,-3,+18,-3,+18,-10,-15,-6,+10,+5,+17,+14,-16,-10,+6,-2,-1,-6,-12,+14,-5,-11,-11,+7,-6,+9,+20,-11,-21,+14,-7,-8,-29,-12,-2,-3,-17,+9,-7,+13,+18,-9,-11,+12,+11,-1,-24,-7,-14,-13,-18,+9,-16,+19,+18,+16,+2,-13,-19,+7,-19,-1,-8,-16,+2,+15,-16,+18,+13,-19,-3,-2,-4,-14,+9,+10,-14,-15,+6,+8,-12,-11,-3,-12,-4,-18,+14,-13,-10,-14,+15,+3,-15,+2,+1,-9,-11,-1,-17,+16,-5,-2,+19,-8,-19,-3,-19,+12,-17,+6,+16,+19,+4,-5,-4,-11,+13,+15,+7,-11,+16,+4,-1,+18,-15,+20,-11,+8,-13,+19,+7,+11,+19,-1,-7,-17,-2,-19,-11,+15,-11,-16,+15,-10,+25,-5,+9,+17,-16,+12,+10,+5,-2,-17,+11,+16,-4,-3,-4,-4,-3,-7,+4,-9,-19,+1,-5,+29,+2,+28,+15,+20,-15,-13,+20,+20,+3,-10,-11,+20,+5,+14,+6,-18,-13,+1,+15,+30,-23,+28,-7,-10,-19,-21,+20,-5,+12,-9,-10,-9,-15,-23,-1,+17,-2,-10,-1,-13,+28,+22,-6,-8,+43,+42,-8,+27,+4,-18,+49,+19,-8,+9,-2,-1,+37,-12,-11,+17,+15,-6,+24,+19,+6,-74,+6,+26,-317,+4,-23,-9,-17,-17,+13,-19,+8,+14,-6,-6,+1,+10,+10,-1,+9,-7,+18,-9,-8,-4,+7,+18,-3,-16,+18,-5,+11,+12,-1,+9,+11,-14,-9,+19,+24,+30,-27,+76,-35,-34,-82,+14,-25,-10,-3,-7,-14,+16,-4,-2,-5,-18,+9,-7,-1,+6,-15,+11,+18,-4,+16,-9,+11,-16,-25,-11,+21,+6,+5,-10,+7,+20,+22,-10,+4,-10,-16,-6,-18,-31,-69,-12,-18,-25,-8,+49,+50,-19,+60,-16,-96,+200,+34,-148,-153,-45,-1,-45,-61788,-16,-5,-8,-6,+3,-6,+16,+18,+10,-14,+9,-20,+6,+18,+9,+13,+7,+11,-5,-11,+17,+13,-4,-4,-3,-11,-17,-2,+4,+9,-15,-3,+19,-9,-12,-17,+5,-14,+17,-7,-23,-11,+3,-13,+4,+19,-14,-17,+10,+1,+4,-11,+9,-17,+7,-16,+12,-8,+1,-9,-9,-7,-7,+1,+1,+4,+2,-16,+7,+4,-18,-7,+12,+7,-1,-14,+9,-17,-8,+13,+19,-18,-17,-14,-10,-9,-12,-19,-17,+14,-16,+18,-15,-14,-17,-9,-14,-15,-19,-19,+10,-17,-2,+11,+15,+9,+1,+17,+17,-10,-16,+15,+4,-7,+10,+5,-16,-5,-5,-3,-8,+17,-5,+124726"
set list  = $LISTFROMSTRING(Input,",")
set status = $LISTVALID(list)
IF status '= 1 {
do $system.Status.DisplayError(status)
write $system.Status.GetErrorText(status)
QUIT}
// found out how many items are in list
    set end = $LISTLENGTH(list)
    //write list length
    write !, "There are "_end_" entries in the input list to process."
    // set previous record counter to 0 
    set prevrecord = 0
    set FreqCount = 0
    // Loop through list
    FOR i=1:1:end{
    //set current value in list
    set insertitem = $LIST(list,i)
    //create new object to save to Global
    set newrecord = ##class(AOC2018.Day1).%New()
    //set Frequency change value = to insertitem variable
    set newrecord.FrequencyChange = insertitem
    //If not at beginning of list calculate current frequency
    IF prevrecord '= 0 {
         //set prevrecord = currentrecord-1
    set newrecord.CurrentFrequency = prevfreq + newrecord.FrequencyChange
    set prevfreq = newrecord.CurrentFrequency
    set prevrecord = prevrecord+1
    set status = newrecord.%Save()
    write status
    }
// IF at beginning of list set CurrentFrequency to 0
ELSE {
set FreqCount = 1
set newrecord.FreqCount = FreqCount
set newrecord.CurrentFrequency = insertitem
set prevfreq = newrecord.CurrentFrequency
set prevrecord = prevrecord+1
set status = newrecord.%Save()
write status
}
    set status = newrecord.%Save()
    &sql(SELECT COUNT (CurrentFrequency) INTO :FreqCount FROM AOC2018.Day1 WHERE CurrentFrequency = :prevfreq)
    set newrecord.FreqCount = FreqCount
    set status = newrecord.%Save()
    write status
  
    }
    return status
}

I passed the input into a string, however I could of picked this up as a file.

The code above ran quite quickly.  The kill global came out of part 2 from this task, which I will post in the comments.

Let me know how you might approach this differently

 

Comments

AOC 2018 Day1 Part 2

As promised in the post above, I have posted part 2 in the comments.

The summary of part 2 is to find the first frequency that repeats twice.

In this published method rather than looping through a string, I looped through the first set of sequence changes (990) via a sql query.

This version was much quicker than parsing the string of frequency changes through each loop.  I added a kill global to the first method, so I could use this to generate the first loop of values before testing/debugging this script.

In hindsight I didn't need to do this and could do something inside this method.

Let me know what you think:

ClassMethod FreqPart2(Input As %String)
{
//This needs to be run after ImportFreqPI method as expects Global to be populated
// set previous record counter to 0 
    set prevrecord = 0 
    //Find the last record to append to in AOC2018.Day1 global
    &sql(SELECT TOP 1 ID INTO :prevrecord FROM AOC2018.Day1 ORDER BY ID DESC)
    //Set Prev frequency to 0 then get value via SQL query
    set prevfreq = 0
    &sql(SELECT CurrentFrequency INTO :prevfreq FROM AOC2018.Day1 WHERE ID = :prevrecord)
    write prevfreq
    set end = 990
   
PILOOP
    // Loop through list
    FOR i=1:1:end{
    //create new object to save to Global
    set newrecord = ##class(AOC2018.Day1).%New()
    // Set Freqency counter to 0, so when used later is only value from current loop
    set FreqCount = 0
    //set freqcount variable to newrecord.Freqcount so can be saved correctly .
    set FreqCount = newrecord.FreqCount
    //set current value in list
    &sql(SELECT FrequencyChange INTO :insertitem FROM AOC2018.Day1 WHERE ID = :i )
    //write list value
    //write insertitem
    //set Frequency change value = to insertitem variable
    set newrecord.FrequencyChange = insertitem
    //set current frequency by adding prevfreq to newrecord.FrequencyChange
    set newrecord.CurrentFrequency = prevfreq + newrecord.FrequencyChange
    //set prev freq variable to newrecord.CurrentFrequency
    // so can be used to calculate newrecord.CurrentFrequency in next loop
    set prevfreq = newrecord.CurrentFrequency
    //save record
    set status = newrecord.%Save()
    // Check if there is any entry in the global already for the frequency and input into FreqCount variable
    &sql(SELECT COUNT (CurrentFrequency) INTO :FreqCount FROM AOC2018.Day1 WHERE CurrentFrequency = :newrecord.CurrentFrequency)
    //write FreqCount
    set newrecord.FreqCount = FreqCount 
    set status = newrecord.%Save()
    //write !,"Frequency Change Is:"_insertitem_" Current Frequency is:"_newrecord.FrequencyChange
    //write !,"Frequency counter IS: "_FreqCount
    //write status
    IF FreqCount > 1 {
        write "First repeat = "_newrecord.CurrentFrequency
        QUIT}
        set prevrecord = prevrecord+1
        }
    IF FreqCount < 2 {
    write !, "Relooping" 
    GOTO PILOOP
            }

    return status
    }

Great to see more AoC participants!

Also please note, that $ListValid returns 1/0 (%Boolean) and not a %Status. So $system.Status methods won't work.

set status = $LISTVALID(list)

you can write something like this:

set isValid = $listValid(list)
if isValid {
  // main code
} else {
  write "List is invalid:",!
  zwrite list
}