Solving interview problems in F#

Last night after presenting at F#unctional Londoners, I got the chance to talk to Ross McKinlay (@pezi_pink) and the topic of job interview questions came up. Ross claimed that for most jobs the simple Fibonacci test doesn’t really do enough to filter out applicants and he instead proposed 2 other questions which he’s seen used to great effect, so I decided to try and implement them in F#.

1. Parse a number without using the built in integer parsing functions

This one was pretty interesting, given a string like “3423587083758”, turn it into an integer assuming we know the ASCII values. Here’s how I solved it. Convert the number into a char array, map those chars into numbers, fold the number sequence multiplying the accumulator by 10 and add the new element. As it stands this won’t handle negative numbers. Let’s see the F# equivalent code for this.

let asciiIntStart = 48
let parse (numStr:string) =
    numStr.ToCharArray()
    |> Seq.map (fun c -> (int c) - asciiIntStart)
    |> Seq.fold (fun acc t -> (acc * 10) + t) 0
parse "357289457320"

2. Convert all tabs to spaces in a file

At first this one sounds easy until you think about things like how tabs work. We need to consider things like carriage returns, spaces and other whitespace. Here’s how I solved it. Read in all lines in a file. For every line, fold with a string and the current character index. In the case that the current character isn’t a tab then append it to the string and add 1 to the index. However, if it is a tab then calculate how many spaces until the next tab by calculating the current index modulus the tab length. Add that many spaces to the accumulator string and increase the index by that number. And once again the F# code for answering that question.

let ConvertToSpaces tabLength fileName =
  let lines = File.ReadAllLines(fileName)
  lines
  |> Seq.map 
    (fun line -> line
                 |> Seq.fold 
                   (fun acc elem -> 
                     let acc,index = acc
                     if elem <> '\t' then
                       (acc + elem.ToString(), index+1)
                     else
                       let spacesToAdd = tabLength - (index % tabLength)
                       (acc + (String.replicate spacesToAdd " "), index+spacesToAdd))
                   ("", 0))
  |> Seq.map (fun q -> fst q)
                   
let ConvertFile file outFile =
  let lines = ConvertToSpaces 4 file
  File.WriteAllLines(outFile, lines)  

3 comments

Leave a reply to MBR Cancel reply