Advent of Code 2016 Day3: Squares with Three Sides

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

For an introduction : goto to article https://community.intersystems.com/post/advent-code-2016-day1-no-time-ta... or look at the http://adventofcode.com/ website.

 

In today's challenge, you have to find out how many 'valid' triangles you find on the walls of the Easter Bunny HQ.
(you can find the input on the adventofcode website : http://adventofcode.com/2016/day/3/input)

A sample of the input looks like this :

  810  679   10
  783  255  616
  545  626  626
   84  910  149
  607  425  901
  556  616  883
  938  900  621

A valid triangle is a set of three side lengths where the sum of any two sides is larger than the remaining side.

You can find the complete instructions here : http://adventofcode.com/2016/day/3

 

We can solve this challenge in only a few steps :
 - stripping the input for unnecessary whitespace : $ZStrip(var,"<=>W") will strip leading, trailing, and repetitive whitespace
 - check each input line for the three sides, and test on valid values : (S1 + S2 > S3, S1 + S3 > S2, S2 + S3 > S1)
 - and display the number of valid triangles

... thats really all there is to do.

Here is my solution as a classmethod :

ClassMethod Part1(file As %String = "j:\winfo\aoc\day3.txt")
{
#Dim possibles as %Integer = 0
#Dim line as %String
#Dim values as %Integer
#Dim t, combi as %String
#Dim possible as %Integer

  Open file:"R":1 Else  Use 0 Write "Could not open file ",file Quit
  Try {
    For {
      Use file Read line If line="" Quit
      Set line=$ZStrip(line,"<=>W")
      For values=1:1:3 Set t(values)=$Piece(line," ",values)
        Set possible = 1
        For combi=$lb(1,2,3),$lb(1,3,2),$lb(2,3,1) {
          If (t($List(combi,1))+t($List(combi,2)))'>t($List(combi,3)) set possible=0 quit
        }
        If possible set possibles = possibles + 1
      }
Catch {
    If $ZE'["ENDOFFILE" Use 0 Write "Error : ",$ZE,!
  }
  Close file
  Use 0 Write "Possibles : ",possibles,!
  Quit
}

 

The answer will unlock the second part of the puzzle, which does a twist in reading the input file : instead of each line being one triangle, for each three lines each column will be a triangle.
So after some fiddling with reading the input file, I think it's better to first read the input into an array (but that's for next time).

Here is the routine code that Bert wrote for the second part  :

Start2() PUBLIC {

count=0
  #Dim objFileStream As %Stream.FileCharacter
objFileStream = ##Class(%Stream.FileCharacter).%New()
sc=objFileStream.LinkToFile("C:\Users\15274\workspace\adventofcode\2016\input\day03\input.txt")
  while 'objFileStream.AtEnd {
line=objFileStream.ReadLine()
line2=objFileStream.ReadLine()
line3=objFileStream.ReadLine()
a=$ZSTRIP($EXTRACT(line,3,5),"*W")
b=$ZSTRIP($EXTRACT(line,8,10),"*W")
c=$ZSTRIP($EXTRACT(line,13,15),"*W")
a2=$ZSTRIP($EXTRACT(line2,3,5),"*W")
b2=$ZSTRIP($EXTRACT(line2,8,10),"*W")
c2=$ZSTRIP($EXTRACT(line2,13,15),"*W")
a3=$ZSTRIP($EXTRACT(line3,3,5),"*W")
b3=$ZSTRIP($EXTRACT(line3,8,10),"*W")
c3=$ZSTRIP($EXTRACT(line3,13,15),"*W")
    if $$IsValidTriangle(a,a2,a3) {
count = count + 1
    }
    if $$IsValidTriangle(b,b2,b3) {
count = count + 1
    }
    if $$IsValidTriangle(c,c2,c3) {
count = count + 1
    }
  }
!,count
}

IsValidTriangle(A,B,C) {
sides(A)=""
sides(B)=""
sides(C)=""
smallest = $ORDER(sides(""))
middle = $ORDER(sides(smallest))
last = $ORDER(sides(middle))
(smallest+middle)>last
}

 

I have a feeling that the next challenges will not all be so easy ...

As mentioned before, you can get all our solutions of the challenges as they pass on https://github.com/DannyWijnschenk/AdventOfCode2016 and https://bitbucket.org/bertsarens/advent2016 

 

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

Danny, 
 

Thanks, It's amazing, to see such articles. 

But how about coding style. If to be honest, your code looks like a mess of old-school code and modern.

As this articles mostly for beginners, it would be much better to have also modern style. Instead of OPEN/USE/READ use %Stream classes. I see this way as much readable.

And about how you use standalone ELSE command without brackets, not sure that beginners, can quickly get the trick here.

Open file:"R":1 Else  Use 0 Write "Could not open file ",file Quit

hi Dmitry,

i gladly take your hints, this is precisely the goal of this article series : to comment and discuss code and make it better or point out alternative code.

Using streams is to be preferred over the Open command (like showed in Bert's code), you can see the age difference in comparing our code !

I limit the use of standalone Else to checking a timeout.

For example:

Lock +^MyLock("MyBatch"):1 Else  Quit "job is already running"

which is identical to 

Lock +^MyLock("MyBatch"):1
If '$Test {
    Quit "job is already running"
}