When Google maps gets it wrong…

Recently we were on vacation in Bergen Norway. We wanted to visit the Old Bergen Museum, which is north of Bergen at this address: “Elsero, Nyhavnsveien 4, 5042 Bergen”. By car, it’s a 3.6 km drive, roughly 8-10 minutes. It’s also possible to walk it in 40-odd minutes. But to take public transit? Here is what Google Maps suggests:

They obviously haven’t hooked into Bergen transit, skyss, because you can take bus numbers 3, 4, 5 or 6 to get there. Although to be fair, the skyss website is hard to navigate if you want to actually find a bus. One of the reasons we didn’t end up going was the lack of clear information about getting there, and Google obviously doesn’t help. But I guess where Google Maps fails, Bing Maps doesn’t (probably should have tried it when we were there):

Advertisements

Learning to program (x) – usability

As we near the end of writing this program, there is one more thing we could do, and that is improve the usability of the program. How? By making it it more interactive. Say you wanted to expand the number of tree species in the program to 100? This would make for a horribly long menu system. A better alternative might be to allow the user to type in the species they are interested in, and then search for the appropriate growth factor – without printing out a menu. If a matching tree species is found in the “database”, then its growth factor is used, otherwise the user is informed that the program cannot find the tree species.

How is this done? The first step involves prompting the user to enter the tree species. In this case we use the readline/chomp combination (without using parse), because we want to read in a word. The user might enter something like “black walnut”, or “Silver Maple”. To make things easier, the program then converts what the user typed into lowercase – this alleviates issues with capitals being used. This is done with the function lowercase(). This means if the user enters “Silver Maple”, it will be converted to “silver maple”.

 println("What type of tree species? ")
 treeSpecies = chomp(readline())
 treeSpecies = lowercase(treeSpecies)

Next we write a piece of code to search the “database” (or array) of trees to see if the species entered by the user exists.

treeInd = 0

for i=1:length(species)
   if (treeSpecies == species[i])
      treeInd = i
      break
   end
end

If the species entered by the user exists, the value of treeInd is set to the index of the species in the storage array. Otherwise it remains at zero. Then it is a matter of using this data. This we do using an if-else statement. If the value of treeInd is 0, then the species does not exist, and no calculation is performed. Otherwise, the normal calculations are performed to find the age of the tree.

if (treeInd == 0)
   println("Sorry that tree species does not exist.")
else
   treeDiam = treeCirc / pi
   treeAge = treeDiam * growthF[treeInd]
   println("The ", species[i], " is ", round(treeAge,2), " years old")
end

Here’s what the whole program looks like:

function readNum(str)
   print(str)
   aNum = parse(chomp(readline()))
   return aNum
end

nTrees = readNum("How many trees? ")

species = ["silver maple", "white birch", "black walnut",
 "red oak", "white oak", "american elm"]
growthF = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]
treeInd = 0

for i=1:nTrees

   treeCirc = readNum("Enter the circumference of the tree (inches): ")

   println("What type of tree species? ")
   treeSpecies = chomp(readline())
   treeSpecies = lowercase(treeSpecies)
   for i=1:length(species)
      if (treeSpecies == species[i])
         treeInd = i
         break
      end
   end

   if (treeInd == 0)
      println("Sorry that tree species does not exist.")
   else
      treeDiam = treeCirc / pi
      treeAge = treeDiam * growthF[treeInd]
      println("The ", species[treeInd], " is ", round(treeAge,2), " years old")
   end

end

 

 

 

Valerian – my thoughts on the movie

I am a big Valerian fan. Ever since Cinebooks started translating the entire series, I have been reading them as soon as they are published. I like Valerian, because like many French comics, they are different. Now, I saw the movie, “Valerian and the City of a Thousand Planets” a few weeks back, and I really enjoyed it. The special affects were incredible. The one problem I have with it is the storyline. Now Valerian is pivotal because it helped inspire sci-fi as we know it today (see my previous post on similarities between Valerian and the space opera we know as Star Wars). The concept, and many of the ideas for the movie are taken from Book 6 of the series: Ambassador of the Shadows. The name for this movie seems to have been morphed from Book 2 of the series: Empire of a Thousand Planets – and it not a city, but more of an overgrown space-station of sorts (called Alpha in the movie, is actually called Point Central in the book). I guess “Valerian and the Spacestation of a Thousand Planets” doesn’t read well.

I really don’t like it when people do this to books. The actual storyline in Ambassador of the Shadows  is way better than that of the movie. We get to explore the station more, meet more of its interesting inhabitants. The basic pretext of the book is that Point Central was not started by humans, and so the entire story morphs – to the better (the book has a completely different ending). In changing both the title, and the core storyline, it essentially becomes a different being, and doesn’t play to the true ideology of the series.  The great thing about Valerian and Laureline is the diversity of species in the series – it would be refreshing to see a sci-fi movie told more from the perspective of the non-human species. Then there are small things…

The cool thing about Valerian and Laureline is that they are spatio-temporal agents, i.e. they can travel through time. Laureline is actually a peasant girl from 11th century France who rescues Valerian and discovers he is a time traveller, forcing Valerian to bring her back to the 28th century, where she is assigned as his partner. Interesting concept right? But completely ignored in the movie. There is also the “love” interest, which certainly develops in the book series, but there is never really any talk of marriage (let alone harping on about it). Like I said, I loved the movie, I just wish it could have been more true to the books, rather than being “Hollywood-ized”.

 

The material of software craftsmanship is the language

A knife makers raw material is steel, a potters is clay. With these raw materials, artisans build things.The raw material of the programmer is the programming language. A language is the medium from which programs are crafted, and each language offers a slightly differing type of medium. Python and Julia are more like a clay, because they are inherently pliant and flexible, and can be easily moulded into programs quickly. Fortran might be like a piece of wood, easily workable, capable of intricate detail, and yet still strong, easy for the novice to shape. C might be more steel-like, robust, and flexible, but slower to shape, and more aligned with experienced programmers. Cobol is a stone, uber robust for the task at hand, yet for the uninitiated, hard to shape.

Programming, like carving a spoon is not hard. It does take some practice to understand the intricacies of the techniques, and how they apply to each language. The ability to read a language, like the structure of various wood species. Each is different, and sometimes like different trees of one species, the same language may have variations depending on the operating system it lives on.

But in the end, languages are all just materials, waiting to be crafted into a functioning object.

 

Learning to program (ix) – all about style

In the previous eight posts, we have designed a program to calculate the age of a tree, given its circumference, and species. In these basic lessons, the core techniques for writing a program in Julia have been covered. Along the way we made changes to the basic program which improved both its functionality, and the the code within it. Now let’s look briefly at the codes style. Style you say… why is that important? It is important because while compilers or interpreters don’t care what a program looks like, humans do. It’s nice to look at a program that is formatted in an aesthetically pleasing manner. Here is the program as it stands:

function readNum(str)
   print(str)
   c = parse(chomp(readline()))
   return c
end

n = readNum("How many trees? ")

species = ["Silver Maple", "White Birch", "Black Walnut",
 "Red Oak", "White Oak", "American Elm"]
g = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

for i=1:n

   c = readNum("Enter the circumference of the tree (inches): ")

   println("Tree Species: ")
   for i=1:length(species)
      println("(",i,") ",species[i])
   end
   t = readNum("Choose a tree (?): ")

   d = c / pi
   age = d * g[t]
   println("The ", species[i], " is ", round(age,2), " years old")

end

It is already quite well formatted, with 3-space indenting (see previous posts on indenting), and good whitespace between sections. There are only two things not quite right: (i) poorly named variables, and (ii) a lack of comments. Variable names like c, and g and non-descriptive, so therefore require a comment, which is wasteful. If they were better named, there would be no need to comment them. Comments are important to inform the reader of a program what is going on. They are really only needed for parts of the program which are not self-explanatory (i.e. complex pieces of code). Here is the program with better style:

# This program calculates the approximate age of a tree using
# the measured circumference of a trunk (4ft from the ground),# and a growth factor specific to the species of tree.

function readNum(str)
   print(str)
   aNum = parse(chomp(readline()))
   return aNum
end

nTrees = readNum("How many trees? ")

species = ["Silver Maple", "White Birch", "Black Walnut",
 "Red Oak", "White Oak", "American Elm"]
growthF = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

for i=1:nTrees

   treeCirc = readNum("Enter the circumference of the tree (inches): ")

   println("Tree Species: ")
   for i=1:length(species)
      println("(",i,") ",species[i])
   end
   menuItem = readNum("Choose a tree (?): ")

   treeDiam = treeCirc / pi
   treeAge = treeDiam * growthF[menuItem]
   println("The ", species[i], " is ", round(treeAge,2), " years old")

end

The pink code shows variables that have been modified with better names. The orange code, an overall comment on what the program does – there is no need for specific comments in the program, as the variables are descriptive, and the code short and self–explanatory.

 

 

Learning to program (viii) – strings and functions

Now that we have briefly looked at strings, we can improve upon the function readNum(), defined previously. Remember that it only had one line of code inside it, which didn’t make it that useful. Now consider this snippet of code:

print("How many trees? ")
n = readNum()

What about if we combined these two lines of code into one? So somehow integrate the print statement into the function readNum(). This can be achieved by passing the phrase “How many trees? “, to the function readNum(). So readNum() would be activated in the following manner:

n = readNum("How many trees? ")

The function itself now looks like this:

function readNum(str)
   print(str)
   c = parse(chomp(readline()))
   return c
end

It takes str as input, and gives it to print, which prints it out. The other two lines are the same as before. This reduces the size of the overall program.

function readNum(str)
   print(str)
   c = parse(chomp(readline()))
   return c
end

n = readNum("How many trees? ")

species = ["Silver Maple", "White Birch", "Black Walnut",
 "Red Oak", "White Oak", "American Elm"]
g = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

for i=1:n
   c = readNum("Enter the circumference of the tree (inches): ")

   println("Tree Species: ")
   for i=1:length(species)
      println("(",i,") ",species[i])
   end
   t = readNum("Choose a tree (?): ")

   d = c / pi
   age = d * g[t]
   println("The ", species[i], " is ", round(age,2), " years old")

end

 

Learning to program (vii) – strings

In the same way that we put all the growth factors into an array, we can do the same with the tree species.

species = ["Silver Maple", "White Birch", "Black Walnut", 
           "Red Oak", "White Oak", "American Elm"]

Now we can use this to “shrink” the program code for the menu.

function readNum()
   c = parse(chomp(readline()))
   return c
end

print("How many trees? ")
n = readNum()

species = ["Silver Maple", "White Birch", "Black Walnut",
           "Red Oak", "White Oak", "American Elm"]
g = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

for i=1:n

   print("Enter the circumference of the tree (inches): ")
   c = readNum()

   println("Tree Species: ")
   for i=1:length(species)
      println("(",i,") ",species[i])
   end
   print("Choose a tree (?): ")
   t = readNum()

   d = c / pi
   age = d * g[t]
   println("The ", species[i], " is ", round(age,2), " years old")

end

It is also possible to modify the code in the final println in order to specify the type of tree selected by the user. Here’s what the program looks like when it runs:

How many trees? 2
Enter the circumference of the tree (inches): 97
Tree Species:
(1) Silver Maple
(2) White Birch
(3) Black Walnut
(4) Red Oak
(5) White Oak
(6) American Elm
Choose a tree (?): 1
The American Elm is 92.63 years old
Enter the circumference of the tree (inches): 40
Tree Species:
(1) Silver Maple
(2) White Birch
(3) Black Walnut
(4) Red Oak
(5) White Oak
(6) American Elm
Choose a tree (?): 6
The American Elm is 50.93 years old

 

 

Learning to program (vi) – arrays

So this is a little bit more challenging. Our program works fine, however the if statement which selects the value of the tree is somewhat large. If you had 200 trees to choose from, it would be kinda messy. Is there a better way? Yes, by storing the values of growth factor in an array. An array is just a container, which can hold more than one value. An array to hold the growth factors can be created in the following manner:

g = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

Each of those values is an element in the array g. So the value of g[1] = 3.0, g[2] = 5.0, etc. Now we can modify the program to use this new container. Basically we can remove the entire if statement, and replace the single g in the equation, with the container g.

age = d * g[t]

Here the value of t entered by the user to specify the type of tree is used to access the appropriate element of g. This is what the whole program looks like now:

function readNum()
   c = parse(chomp(readline()))
   return c
end

print("How many trees? ")
n = readNum()

g = [3.0, 5.0, 4.5, 4.0, 5.0, 4.0]

for i=1:n

   print("Enter the circumference of the tree (inches): ")
   c = readNum()

   println("Tree Species: ")
   println("(1) Silver Maple")
   println("(2) White Birch")
   println("(3) Black Walnut")
   println("(4) Red Oak")
   println("(5) White Oak")
   println("(6) American Elm")
   print("Choose a tree (?): ")
   t = readNum()

   d = c / pi
   age = d * g[t]
   println("The tree is ", round(age,2), " years old")

end

As you can see, the program has shrunk considerably in size. Now adding 20 more trees is as simple as adding more values to the array g, and modifying the menu.

 

Learning to program (v) – adding a subroutine

Our program as it stands works quite well.

print("How many trees? ")
n = parse(chomp(readline()))

for i=1:n
   
   println("Enter the circumference of the tree (inches): ")
   c = parse(chomp(readline()))

   println("Tree Species: ")
   println("(1) Silver Maple")
   println("(2) White Birch")
   println("(3) Black Walnut")
   println("(4) Red Oak")
   println("(5) White Oak")
   println("(6) American Elm")
   print("Choose a tree: ")
   t = parse(chomp(readline()))

   if (t == 1)
      g = 3.0
   elseif (t == 2)
      g = 5.0
   elseif (t == 3)
      g = 4.5
   elseif (t == 4)
      g = 4.0
   elseif (t == 5)
      g = 5.0
   elseif (t == 6)
      g = 4.0
   end

   d = c / pi
   age = d * g
   println("The tree is ", round(age,2), " years old")

end

The most unreadable part is still the three lines that read in info: parse(chomp(readline())). As this is used three times, it might be nice if we put it in its own “subroutine”, which is a way of creating a piece of a program which can be used anywhere. These are more often called functions. By doing this we are able to “hide” code. Here is what a simple function would look like in Julia:

function readNum()
   c = parse(chomp(readline()))
   return c
end

It uses the pair function-end, to define the function. It is given a name, in this case readNum, and because it doesn’t take any inputs there is nothing in between the parentheses. The line of code that reads the number from the user is placed inside the function, and passed back to the program using the function using the return statement.

function readNum()
   c = parse(chomp(readline()))
   return c
end

print("How many trees? ")
n = readNum()

for i=1:n

   print("Enter the circumference of the tree (inches): ")
   c = readNum()

   println("Tree Species: ")
   println("(1) Silver Maple")
   println("(2) White Birch")
   println("(3) Black Walnut")
   println("(4) Red Oak")
   println("(5) White Oak")
   println("(6) American Elm")
   print("Choose a tree (?): ")
   t = readNum()

   if (t == 1)
      g = 3.0
   elseif (t == 2)
      g = 5.0
   elseif (t == 3)
      g = 4.5
   elseif (t == 4)
      g = 4.0
   elseif (t == 5)
      g = 5.0
   elseif (t == 6)
      g = 4.0
   end

   d = c / pi
   age = d * g
   println("The tree is ", round(age,2), " years old")

end

This is a very simple example of a function – some will argue there was little point, as one line of code in each instance was replaced with “one line of code”. But were there more lines repeated, then it could be quite beneficial.