Saturday, May 16, 2009

Chemistry Library

This week's code is probably the biggest single release I've ever made. I considered splitting it up into two or three weeks, but that would be too much work. Before we get started, you'll need my proper case function.


In this function library, we have three major things going on: look up chemical element symbols by atomic number, look up chemical element names by atomic number, and figure out the electron configuration of an atom given the atomic number.


For the chemical element names and symbols, I made an array of all the named elements; currently the highest named element is atomic number 111. There are elements with higher atomic numbers that have been discovered, but not yet named. There is also the possibility that more elements may be discovered in the future. To handle both these situations, I wrote code to generate standardized names if the array lookup fails.


The function(s) for figuring out electron configuration are my favorite. I started with an array of all the subshells in the order they get filled. Then I wrote a function that knows how many electrons can fit in each type of subshell. Finally, I wrote the main function which fills the subshells, taking into account known exceptions to the rules. (e.g. palladium)


Saturday, May 9, 2009

Fuel consumption

Last November I was at a Service Canada office and picked up a pamphlet called Fuel Consumption Guide 2007. Although too old to be relevant (unless you're buying a used car), it contained some formulae for calculating fuel consumption which inspired me to write some code.


This library of functions is among the longest yet, so I won't be posting the code directly on the blog, but here's a list of the functions included:


  • lph() - Calculate fuel consumption rating in litres per 100 kilometres.
  • mpg() - Calculate fuel consumption rating in miles per gallon.
  • lph2mpg() - Convert miles per (imperial) gallon to litres per 100 kilometres.
  • mpg2lph() - Convert litres per 100 kilometres to miles per (imperial) gallon.
  • fuelConsumption() - Calculate fuel consumption in litres.
  • CO2emissions() - Calculate carbon dioxide emissions in kilograms.

Saturday, May 2, 2009

Regular Expressions

Over the past year, I've posted a lot of code that made use of regular expressions. When used appropriately, they can be very powerful. But regular expressions in ASP are a little more cumbersome than PHP. Wouldn't it be great if ASP had the simplicity of regular expression functions?


Once again, the source code is too long to post here, so it will only be available on Snipplr. This library of functions includes the following:

  • ereg() - case-sensitive regular expression match
  • eregi() - case-insensitive regular expression match
  • ereg_replace() - case-sensitive regular expression replacement
  • eregi_replace() - case-insensitive regular expression replacement
  • sql_regcase() - make regular expression for case insensitive match

View ASP implementation on Snipplr

Saturday, April 25, 2009

Social Insurance Numbers

Here in Canada, our equivalent of the Social Security Number is called Social Insurance Number. It serves the same purpose and has the same demands for privacy surrounding it.


Once again, I won't be posting the full source code on the blog, only on Snipplr, but I will discuss briefly how it works. It consists of three groups of three digits, and is validated using the Luhn algorithm. I also do a quick regular expression validation to check for numbers which invalidly begin with an eight: ^([1-79]{3})[\-\s]?(\d{3})[\-\s]?(\d{3})$.


Saturday, April 18, 2009

Social Security Numbers

Assuming that you have a legitimate need to capture social security numbers (human resources app?), you may want to validate and format them consistently. The actual code for both languages combined is a little bit too long to post, so I'll just talk about the algorithm.


A social security number is a nine-digit number and can be matched with the following regular expression: ^\d{3}\-?\d{2}\-?\d{4}$. If it can't pass this test, it's not a valid social security number. However, passing this simple test doesn't guarantee validity, so we need to keep checking.



  • No digit group can consist of only zeros, and the first group cannot be 666. We check for these errors with the following regular expression: ((000|666)\-?\d{2}\-?\d{4}|\d{3}\-?00\-?\d{4}|\d{3}\-?\d{2}\-?0000.

  • Numbers from 987-65-4320 to 987-65-4329 are reserved for use in advertisements, and other previously legitimate numbers have been invalidated because of use in advertisments. We check for these errors with the following regular expression: 987\-?65\-?432\d{1}|042\-?10\-?3580|062\-?36\-?0749|078\-?05\-?1120|095\-?07\-?3645|128\-?03\-?6045|135\-?01\-?6629|141\-?18\-?6941|165\-?(16|18|20|22|24)\-?7999|189\-?09\-?2294|212\-?09\-?(7694|9999|219\-?09\-?9999|306\-?30\-?2348|308\-?12\-?5070|468\-?28\-?8779|549\-?24\-?1889)

  • Last but not least, the first three numbers are never higher than 772 (well, not yet; this could change in the future). For this I used a simple string conversion and numeric comparison.


The complete, commented source code is available on Snipplr:


Next week we'll head north of the border to my country and see what the Canadian equivalent of the Social Security Number is, and how we can validate them.

Saturday, April 11, 2009

Homeland Security Advisory System

Back in 2002, a bunch of bureaucrats decided that the United States needed an advisory system so that all federal departments and agencies could communicate what the current threat condition was using the same definitions. Sounds like a good idea to me.


The average citizen can see what the current threat condition is by visiting certain government web sites. The web site for the Department of Homeland Security is a good example.


The Department of Homeland Security also provides a little-known web service which returns the threat condition in XML format so that you can do what you want with it. Let's write a function to retrieve and parse this information down to just the threat condition itself.


ASP



  1. function getThreatLevel()

  2.     dim regEx

  3.     set regEx = new RegExp


  4.     with regEx

  5.         .Pattern = ".*\n.*CONDITION=""(.*)"" />"

  6.         .IgnoreCase = true

  7.         .Global = true

  8.     end with


  9.     dim xmlhttp

  10.     set xmlhttp = Server.CreateObject("Msxml2.ServerXMLHTTP")

  11.     xmlhttp.open "GET", "http://www.dhs.gov/dhspublic/getAdvisoryCondition", "False"

  12.     xmlhttp.send


  13.     getThreatLevel = regEx.replace(xmlhttp.responseText, "$1")


  14.     set xmlhttp = nothing

  15.     set regEx = nothing

  16. end function


As is often the case, the PHP version requires a significantly less amount of code.


PHP



  1. function getThreatLevel()

  2. {

  3.     return eregi_replace('.*CONDITION="(.*)" />', '\1', file_get_contents("http://www.dhs.gov/dhspublic/getAdvisoryCondition"));

  4. }


So now we have a string that contains just the word "ELEVATED" (or whatever the current threat level is at the moment; it's been at elevated for several years at the time of this writing). What can you do with it? Feed it into a switch statement and display an image is one possibility.


Saturday, April 4, 2009

Min/Max

SQL contains a number of aggregate functions that can do things like select the largest or smallest number from a set of values. This could be handy in the programming language itself.


ASP

  1. function max(arrNumbers)
  2.     dim result
  3.     result = arrNumbers(0)
  4.     for each i in arrNumbers
  5.         if i > result then
  6.             result = i
  7.         end if
  8.     next
  9.     max = result
  10. end function
  11. function min(arrNumbers)
  12.     dim result
  13.     result = arrNumbers(0)
  14.     for each i in arrNumbers
  15.         if i < result then
  16.             result = i
  17.         end if
  18.     next
  19.     min = result
  20. end function

View ASP implementation on Snipplr