Thursday, January 12, 2017

Some more Ruby

Trying out Ruby code again today for no specific reason other than to try out some different languages. Expanding on the previous example I decided to allow edge detection for multi-row matrix. This time we look for changes to the matrix with the left character and the row above.

Some comments on the syntax

- I found the for loop syntax a little weird “…” does not seem very intuitive.
- Reading from standard Input was really simple and felt good.
- Some of the syntax like ‘gsub’, ‘def’ (instead of 'function') would take a little getting used too, but Stack Overflow was a big help with that.
- RegEx was never my favourite technology, but Rubular website was very good; however did not work on Safari only Chrome.
- Closing ‘if' statements with ‘end’ felt like I was coding basic again.
Full code example is below.
#!/usr/bin/env ruby
# Usage:     cat <filename> | ./<edge.rb>
def CalculateEdge(arr)
  result = ""     # loop over each line of the array of text items
  for lineIndex in 0 ... arr.size
     topChar = "0" # start empty
     prevChar = "0" # start empty
     for charIndex in 0 ... arr[lineIndex].chomp.size
       # consider <whitespace> as '0'
       currentChar = arr[lineIndex][charIndex].gsub(/\s/,'0')
       # validation checks
       if lineIndex == 0 then
          topChar = currentChar  # assume current char if first row
        elsif lineIndex > 0 && charIndex > arr[lineIndex-1].chomp.size
          topChar = "0"  # assume "0" if missing on row above
        else
          topChar = arr[lineIndex-1][charIndex].nil? ? "0" : arr[lineIndex-1][charIndex].gsub(/\s/,'0')
        end
        # XOR char against the previous char to the left of current
        edgeLeft = prevChar.to_i(2) ^ currentChar.to_i(2)
        # XOR char against the char above the current
        edgeTop = currentChar.to_i(2) ^ topChar.to_i(2)
        # if the left char has not changed use the top row
        edge = edgeLeft == 1 ? edgeLeft : edgeTop
        prevChar = currentChar
        result = result+"#{edge}"
     end   result = "#{result}\n\t"
   end
   return result
end
# Place each line into an array
input = $stdin.read
if not (input =~ /[^0-1\W]/).nil? then
    puts "Error: Only 0-1 values allowed. e.g. 0100001111"
    puts "       Whitespace will be considered '0'"
    exit
end
arr = input.split(/\n/)
result = CalculateEdge(arr)
puts "Input :\t#{input}"
puts "Output:\t#{result}"

Next steps for the language

Must see if you can Unit Test this language ….. debugging on the command line was not great.