0

I am trying to figure out the following:

When I run this in the terminal using Ruby, the string in the array is removed until it is done when I continue typing in a string that is in the saxophone_section array. But I still want to be able to remove the string from the array when I type in "alto saxophone 1" and because "alto 1" is found in the input string.

How can I do this when a string in an array matches, regardless of the size of an input string?

saxophone_section = ["alto 1", "alto 2", "tenor 1", "tenor 2", "bari sax"]

until saxophone_section == []

puts "Think of sax parts in a jazz big band."
print ">>"

sax_part = gets.chomp.downcase


# this is the part that is confusing me.  Trying to figure out the method in which 
# a string in the above array matches an input, whether "alto 1" or "alto saxophone 1" 
# or "Eb alto saxophone 1" is typed in ("alto 1" is found in all).  
# How can I make it true in all three (or more) cases?

saxophone_section.any?(sax_part)

# I am thinking that this bottom parts one could be used? or not?
parts = saxophone_section.map {|sax| sax.gsub(/\s+/m, ' ').strip.split(" ")}


#this is the loop to delete the item in the array:

if saxophone_section.include?(sax_part) == true

p saxophone_section.delete_if{ |s| s == sax_part}
puts "Damn, you're lucky"
else
  puts "Woops! Try again."
end
end
puts "You got all parts."

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • 1
    Is this ruby? If it is, add the [tag:ruby] – aloisdg Feb 24 '20 at 12:57
  • Take a look at https://stackoverflow.com/a/5395777/128421. When trying to look through multiple words it's helpful to match on patterns, but creating the patterns by hand can be a pain. Using code to create the unions of the patterns results in much more concise code. – the Tin Man Feb 24 '20 at 23:20

3 Answers3

0

Converting strings into array and making an intersection operation should be an option. I know, this is not the best solution, but might save your day.

[17] pry(main)> x = "alto saxophone 1"
=> "alto saxophone 1"
[18] pry(main)> y = "i am not an anglophone"
=> "i am not an anglophone"
[19] pry(main)> z = "alto 1"
=> "alto 1"
[20] pry(main)> x.split & z.split == z.split # & is array intersection
=> true
[21] pry(main)> x.split & y.split == y.split
=> false
marmeladze
  • 6,468
  • 3
  • 24
  • 45
0

You should use regex to match the input. So instead of creating an array of strings, try the array of regular expressions like so;

saxophone_section = [/alto\s(?:.*\s)?1/, /alto\s(?:.*\s)?2/, /tenor\s(?:.*\s)?1/, /tenor\s(?:.*\s)?2/, /bari\s(?:.*\s)?sax/]

Then use match with all the elements in the array against the input to find if there is a match with the input string;

sax_part = gets.chomp.downcase

index = saxophone_section.find_index { |regex| sax_part.match(regex) }

Later you can use this index to remove the element from array if it's not nil;

saxophone_section.delete(index)

Or you can just use Array#delete_if method to delete the element from array directly like so;

saxophone_section.delete_if { |regex| sax_part.match(regex) }

Note: You can use https://www.rubular.com to test your regular expressions.

Foo Bar Zoo
  • 206
  • 3
  • 10
0

Here's where I'd start with this sort of task; These are great building blocks for human-interfaces on the web or in applications:

require 'regexp_trie'

saxophone_section = ["alto 1", "alto 2", "tenor 1", "tenor 2", "bari sax"]
RegexpTrie.union saxophone_section   # => /(?:alto\ [12]|tenor\ [12]|bari\ sax)/

The output of RegexpTrie.union is a pattern that will match all of the strings in saxophone_section. The pattern is concise and efficient, and best of all, doesn't have to be generated by hand.

Applying that pattern to the string being created will show if you have a hit when there's a match, but only when there's enough of the string to match.

That's where a regular Trie is very useful. When you're trying to find what possible hits you could have, prior to having a full match, a Trie can find all the possibilities:

require 'trie'

trie = Trie.new
saxophone_section = ["alto 1", "alto 2", "tenor 1", "tenor 2", "bari sax"]

saxophone_section.each { |w| trie.add(w) }
trie.children('a') # => ["alto 1", "alto 2"]
trie.children('alto') # => ["alto 1", "alto 2"]
trie.children('alto 2') # => ["alto 2"]
trie.children('bari') # => ["bari sax"]

Blend those together and see what you come up with.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303