2013-01-05

National identification number: Finland part 3

Last part of our short series about the Finnish social security number (Fssn). You can check part 1 here, and part 2 here.

This last post we are interested in generating random Fssn's. This has no real world applications. It is just a coding excercise for the willing. If you are up for the challenge try doing it yourself.

I'm not going to go indepth about this algorithm, I'll just present it straight away.
#n the amount of random generated FSSn
#pos.centuries are the possible centuries you want to generate
#pos.century.char are the characters which match the possible centuries
#pos.centuries and pos.century.char have to be in the same order.

finID.random = function(n, pos.centuries = c(18, 19, 20), pos.century.char=c("+", "-", "A")){
 
# this function is for genereting one random Finnish ID. It's later used in an apply function.
#A function inside a function! Smart...

 finID.randomizer = function(x, centuries, century.char){ 
        # x is just a dummy variable so that apply works.
  
   cent.char = sample(century.char, 1)
   cent = centuries[century.char %in% cent.char]
   year = sample(1:99, 1)
  
   if(nchar(year) ==1) year = paste("0", year, sep="")

   bol.year = as.integer(paste(cent, year, sep=""))
   month = sample(1:12, 1)
  
   #Leap year handling... Straight from wikipedia
   if(bol.year %% 400 == 0){
   days = c(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month]
   }else if(bol.year %% 100 == 0){
    days = c(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month]
   }else if(bol.year %% 4 == 0){
    days = c(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month]
   }else{
    days = c(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month]
   }
  
   days = sample(1:days, 1)

   if(nchar(month) == 1) month = paste("0", month, sep="")  
   if(nchar(days) == 1) days = paste("0", days, sep="")
  
   birth = paste(days, month, year, sep="")
  
   check.value = sample(0:999, 1)
  
   if(nchar(check.value) == 3) {
   }else if(nchar(check.value) == 2){ 
       check.value = paste("0", check.value, sep="") 
   }else{ 
       check.value = paste("00", check.value, sep="") 
       }   
   check.char = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, LETTERS)
   check.char = check.char[-c(17, 19, 25, 27, 36)]
   bol.value = as.integer(paste(birth, check.value, sep=""))
   check.char = check.char[(bol.value %% 31) + 1]
   x = paste(birth, cent.char, check.value, check.char, sep="")
 }

 #formals "reformats" a given function
 formals(finID.randomizer) = alist(x=, 
                                     centuries = pos.centuries, 
                                     century.char = pos.century.char) 
 n = matrix(NA, nrow = n)
 n = apply(n, 1, finID.randomizer)
 return(n)
}

No comments:

Post a Comment