I solved this problem in Ruby:
Write an utility that takes 3 command-line parameters P1, P2 and P3. P3 is OPTIONAL (see below) P1 is always a file path/name. P2 can take the values:
- “lines”
- “words”
- “find”
Only P2 is “find”, then P3 is relevant/needed, otherwise it is not.
So, the utility does the following:
- If P2 is “rows” it says how many lines it has
- If P2 is “words” it says how many words it has (the complete file)
- If P2 is “find” it prints out the lines where P3 is present
My solution looks like this:
#!/usr/bin/env ruby
def print_usage
puts "Usage: #{$0} <file> words|lines"
puts " #{$0} <file> find <what-to-find>"
end
class LineCounter
# Initialize instance variables
def initialize
@line_count = 0
end
def process(line)
@line_count += 1
end
def print_result
puts "#{@line_count} lines"
end
end
class WordCounter
# Initialize instance variables
def initialize
@word_count = 0
end
def process(line)
@word_count += line.scan(/\w+/).size
end
def print_result
puts "#{@word_count} words"
end
end
class WordMatcher
# Initialize instance variables, using constructor parameter
def initialize(word_to_find)
@matches = []
@word_to_find = word_to_find
end
def process(line)
if line.scan(/#{@word_to_find}/).size > 0
@matches << line
end
end
def print_result
@matches.each { |line|
puts line
}
end
end
# Main program
if __FILE__ == $PROGRAM_NAME
processor = nil
# Try to find a line-processor
if ARGV.length == 2
if ARGV[1] == "lines"
processor = LineCounter.new
elsif ARGV[1] == "words"
processor = WordCounter.new
end
elsif ARGV.length == 3 && ARGV[1] == "find"
word_to_find = ARGV[2]
processor = WordMatcher.new(word_to_find)
end
if not processor
# Print usage and exit if no processor found
print_usage
exit 1
else
# Process the lines and print result
File.readlines(ARGV[0]).each { |line|
processor.process(line)
}
processor.print_result
end
end
My questions are:
- Is there a more Ruby-esque way of solving it?
- More compact, but still readable / elegant?
It seems checking for correct command-line parameter combinations takes up a lot of space...
Contrast it to the Scala version found here:
https://gist.github.com/anonymous/93a975cb7aba6dae5a91#file-counting-scala