daily pastebin goal
20%
SHARE
TWEET

Untitled

a guest May 17th, 2018 74 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # Rick's Winning Ticket!
  2. # Your favorite grandpa, Rick, is crazy about the lottery and even crazier about
  3. # how he picks his “lucky” numbers. And even though his “never fail” strategy has
  4. # yet to succeed, Grandpa Rick doesn't let that get him down.
  5. #
  6. # Every week he searches through the Sunday newspaper to find a string of digits
  7. # that might be potential lottery picks. But this week the newspaper has moved to
  8. # a new electronic format, and instead of a comfortable pile of papers, Grandpa
  9. # Rick receives a text file with the stories.
  10. #
  11. # Help your grandpa find his lotto picks. Given a large series of number strings,
  12. # return each that might be suitable for a lottery ticket pick. Note that a valid
  13. # lottery ticket must have 7 unique numbers between 1 and 59, digits must be used
  14. # in order, and every digit must be used.
  15. #
  16. # Example strings:
  17. # ["569815571556", "4938532894754", "01234567", "472844278465445"]
  18. #
  19. # Example output:
  20. # 01234567 -> 1 2 3 4 5 6 7
  21. #
  22. # Additionally:
  23. # 1) 6 and 06 both represent the number 6, however 006 would not be valid
  24. # 2) Return all valid picks per input sorted without duplicates for that input
  25. # 3) Please return both the original string, and the valid ticket created from it
  26. # 4) No output for invalid tickets.
  27.  
  28. # Testing command:
  29. # RicksNumberFinder.initialize(["abc", "1234567","569815571556","4938532894754","472844278465445","123045610","123451618","1234101112","12310111213","121415161718","1131415161718","59585756565453"])
  30.  
  31. class RicksNumberFinder
  32.  
  33.   # Receives an array of strings to find numbers from
  34.   def self.initialize(newspaper_arr)
  35.     hits_arr = [] # container array for positive hits
  36.     newspaper_arr.uniq.each do |word|
  37.       result = review_word(word)  # review string for suitability
  38.       hits_arr << result unless result.blank? # add to hits if not blank
  39.     end
  40.     print_output(hits_arr)
  41.   end
  42.  
  43.   # Checks to see if the number set is valid. First illegal numbers, then duplicate numbers
  44.   def self.check_validity(number_set)
  45.     return false unless number_set.select{|num| num.to_i > 59 || num.to_i == 0 }.count == 0
  46.     return false unless number_set.length == number_set.uniq.length
  47.   end
  48.  
  49.   # Choose calculation to find number of permutations possible for a string
  50.   def self.choose(n, k)
  51.     return 1 if k == 0
  52.     (n * choose(n - 1, k - 1)) / k
  53.   end
  54.  
  55.   # Creates a helper array that keeps tracks of the placement of double digit
  56.   # numbers. Example for three double digits: [0,1,2]
  57.   def self.initialize_dd_placements(doubles_allowed)
  58.     dd_placements = []
  59.     doubles_allowed.times do |counter|
  60.       dd_placements << counter
  61.     end
  62.     dd_placements
  63.   end
  64.  
  65.   # Populates the permutations array with all of the possible permutations
  66.   def self.populate_permutations_arr(test_string)
  67.     double_digits_count = test_string.length - 7 # count of how many double digits in this set of numbers
  68.     dd_placements = initialize_dd_placements(double_digits_count) # create the helper to keep track of double digit number placement
  69.  
  70.     permutations_arr = [] # create an array to hold all the permutations possible from the test_string
  71.     # choose method provides count of possible variations possible with this many double digits
  72.     choose(7, double_digits_count).times do
  73.       permutations_arr << [] # add array for every permutation possible
  74.     end
  75.     # Populate the permutations array with all possible permutations from this number string this uses the dd_placements array to
  76.     # simplify the logic. If the current counter location is present in the helper, then a double digit goes here.
  77.     permutations_arr.each do |permutation|
  78.       string_copy = test_string.dup
  79.       7.times do |counter|
  80.         if dd_placements.include? counter # this position is occupied by a double digit number
  81.           permutation[counter] = string_copy.slice!(0, 2).to_i
  82.         else # this position is occupied by a single digit number
  83.           permutation[counter] = string_copy.slice!(0, 1).to_i
  84.         end
  85.       end
  86.       helper = increment_dd_placements(dd_placements) # increment helper for the next possible permutation of double digit placements
  87.     end
  88.     permutations_arr # return permutations array
  89.   end
  90.  
  91.   # Print method
  92.   def self.print_output(hits)
  93.     hits.each do |hit_set|
  94.       hit_set[:results].each do |hit|
  95.         puts "#{hit_set[:test_string]} -> #{hit*" "}"
  96.       end
  97.     end
  98.   end
  99.  
  100.   # Reviews each string to see if it meets our criteria and gets results for those that do
  101.   def self.review_word(test_string)
  102.     return nil if test_string.length < 7 || test_string.length > 14 || !(test_string !~ /\D/) # Quick rejections
  103.     permutations_arr = populate_permutations_arr(test_string) # populates all possible permutations of double digit placements
  104.     permutations_arr.delete_if { |permutation| check_validity(permutation) == false } # remove invalid entries
  105.     return nil if permutations_arr.empty? # reject if no valid permutations found
  106.     permutations_arr.each do |permutation|
  107.       permutation.sort! # sort all of the permutations
  108.     end
  109.     {test_string: test_string, results: permutations_arr.uniq.sort}  # return hash with sorted unique entries
  110.   end
  111.  
  112.   # Increment the double digit helper to create the pattern for the next placement
  113.   # of double digit numbers.
  114.   # Ex: [0,1,2] => [0,1,3] | [0,1,6] => [0,2,6] | [0,5,6] => [1,5,6]
  115.   def self.increment_dd_placements(dd_placements)
  116.     pointer = dd_placements.count - 1
  117.     while pointer >= 0
  118.       if dd_placements[pointer] < (6 - (dd_placements.count - pointer - 1))
  119.         dd_placements[pointer] = dd_placements[pointer] + 1
  120.         break
  121.       elsif dd_placements[pointer] == 6
  122.         secondary_pointer = pointer - 1
  123.         new_max = 5
  124.         while dd_placements[secondary_pointer] == new_max
  125.           secondary_pointer = secondary_pointer - 1
  126.           new_max = new_max - 1
  127.         end
  128.         dd_placements[secondary_pointer] = dd_placements[secondary_pointer] + 1
  129.         (pointer - secondary_pointer).times do
  130.           secondary_pointer = secondary_pointer + 1
  131.           dd_placements[secondary_pointer] = dd_placements[secondary_pointer - 1] + 1
  132.         end
  133.         break
  134.       else
  135.         pointer = pointer - 1
  136.       end
  137.     end
  138.     dd_placements
  139.   end
  140.  
  141.  
  142. end
RAW Paste Data
Top