#!/usr/bin/env ruby # # Performs a smart copy based on the files you pass in # require 'ftools' # Abstract class that generates more words class Generator # String -> List[String] # Generates a new flat list of Strings from the input word def generate(word) res = word.scan(/([A-Z][a-z]*|[^A-Za-z0-9]|[a-z0-9]+)/).flatten.collect do |part| generate_parts(part) || part end cartesian_product res end # String -> List[String] | String | nil # Generate new word possibilities def generate_parts(word) throw 'implement generate_parts(String)' end private # List[List[X]]-> List[List[X]] # Computes cartesian product, doesn't destruct the input list def cartesian_product(input) return nil if input == nil return [] if input.empty? return find_cartesian_product Array.new(input),[[]] end # This puts the result in 'result' # We desctruct the input 'lists' def find_cartesian_product(lists,result) # Base case: just return return result if lists.empty? # Recurrance case: # - remove the first list # - iterate over all the items, creating new sets from every set # in result adding that item # - recur with the cdr of the input list and the new result fst = lists.shift if fst && !fst.empty? new_result = [] fst.each do |item| result.each do |set| new_set = Array.new set new_set << item new_result << new_set end end else new_result = result end return find_cartesian_product lists,new_result end end # A Generator based on a set of strings class SetBasedGenerator < Generator def initialize(set) @set = set @set_caps = @set.collect {|s| s.capitalize} end def generate_parts(word) return @set if @set.index word return @set_caps if @set_caps.index word end end # A Generator based on a single number that asks the user how many # occurrences class NumberBasedGenerator < Generator def initialize @lst = nil end def generate_parts(word) if word =~ /[0-9]/ n = word.to_i if !@lst print 'How many occurrences would you like> ' num = STDIN.gets.chomp.to_i @lst = Array.new(num) {|x| (n+x).to_s} end return @lst end end end def main(argv) gens = [ SetBasedGenerator.new(['north','south','east','west']), SetBasedGenerator.new(['up','down']), SetBasedGenerator.new(['left','right']), NumberBasedGenerator.new ] argv.each do |file| # Collect all the results into 'res' res = [file] gens.each do |gen| new_words = [] res.each do |w| gen.generate(w).each do |lst| new_words << lst.join end end res = new_words.uniq end # Either print or copy the file if res.length == 1 puts 'Nothing to copy' else res.each do |f| if File.exist? file File.copy file,f else puts f end end end end end main ARGV