Ruby codes works - ruby

I have the ff array:
words = ['demo', 'none', 'tied', 'evil', 'dome', 'mode', 'live',
'fowl', 'veil', 'wolf', 'diet', 'vile', 'edit', 'tide',
'flow', 'neon']
And now I am trying to do an anagram like this:
["demo", "dome", "mode"]
["neon", "none"]
(etc)
So I got this code:
result = {}
words.each do |word|
key = word.split('').sort.join
if result.has_key?(key)
result[key].push(word)
else
result[key] = [word]
end
end
result.each do |k, v|
puts "------"
p v
end
I understand how the word got split and joined but this part here is not clear to me:
if result.has_key?(key)
result[key].push(word)
else
result[key] = [word]
end
On the code above it's pretty obvious that result is an empty hash and now we're asking if it has a key of the sorted/joined key via if result.has_key?(key) How does that work? Why ask an empty hash if it has a key of the selected key via word iteration?
result[key].push(word) also is not clear to me. So is this code putting the key inside the result as its key? or the word itself?
result[key] = [word] this one also. Is it adding the word inside the array with the key?
Sorry I am bit confused.

The results is only empty on the first iteration of the loop. The line
if result.has_key?(key)
is checking if the key created by sorting the letters in the current word exists, and in the case of the first iteration when it's empty, yes, it is obviously not there this time, but it still needs to check every other time too.
Now, when a particular key does not exist yet in results, that key is added to results and a new array containing the current word is added as the value for that key, in the line
result[key] = [word]
When a key already exists in results, that means there is already an array containing at least one word, so the current word is added into that array, in the line
result[key].push(word)
Stepping through what's happening:
words = ['demo', 'neon', 'dome', 'mode', 'none']
// first iteration of the loop
word = 'demo'
key = 'demo' // the letters in "demo" happen to already be sorted
Is 'demo' a key in results?
results is currently {}
No, 'demo' is not a key in {}
Add 'demo' as a key, and add an array with 'demo' inside
results is now { 'demo' => ['demo'] }
// second iteration
word = 'neon'
key = 'enno'
Is 'enno' a key in results?
results is currently { 'demo' => ['demo'] }
No, 'enno' is not a key in { 'demo' => ['demo'] }
Add 'enno' as a key, and add an array with 'neon' inside
results is now { 'demo' => ['demo'], 'enno' => ['neon'] }
// third iteration
word = 'dome'
key = 'demo'
Is 'demo' a key in results?
results is currently { 'demo' => ['demo'], 'enno' => ['neon'] }
Yes, 'demo' is a key in { 'demo' => ['demo'], 'enno' => ['neon'] }
Add 'dome' to the array at key = 'demo'
results is now { 'demo' => ['demo', 'dome'], 'enno' => ['neon'] }
// ... and so on

There are tools that help you figure this stuff out on your own. Here's an example using Seeing Is Believing with vim:
words = ['demo', 'mode']
result = {}
words.each do |word| # => ["demo", "mode"]
key = word # => "demo", "mode"
.split('') # => ["d", "e", "m", "o"], ["m", "o", "d", "e"]
.sort # => ["d", "e", "m", "o"], ["d", "e", "m", "o"]
.join # => "demo", "demo"
result # => {}, {"demo"=>["demo"]}
if result.has_key?(key)
result[key].push(word) # => ["demo", "mode"]
else
result[key] = [word] # => ["demo"]
end
result # => {"demo"=>["demo"]}, {"demo"=>["demo", "mode"]}
end
result.each do |k, v| # => {"demo"=>["demo", "mode"]}
puts "------"
p v
end
# >> ------
# >> ["demo", "mode"]
Other tools I'd use are Irb and Pry.

Considering that you have answers that provide good explanations of your problem, I would like to present some more Ruby-like approaches that could be used. All of these methods create a hash h whose values are arrays of words that are anagrams of each other, which can be extracted from the hash by executing h.values.
Use Enumerable#group_by and Array#sort
This is arguably the most direct approach.
words.group_by { |w| w.each_char.sort }.values
#=> [["demo", "dome", "mode"], ["none", "neon"], ["tied", "diet", "edit", "tide"],
# ["evil", "live", "veil", "vile"], ["fowl", "wolf", "flow"]]
group_by produces
words.group_by { |w| w.each_char.sort }
#=> {["d", "e", "m", "o"]=>["demo", "dome", "mode"],
# ["e", "n", "n", "o"]=>["none", "neon"],
# ["d", "e", "i", "t"]=>["tied", "diet", "edit", "tide"],
# ["e", "i", "l", "v"]=>["evil", "live", "veil", "vile"],
# ["f", "l", "o", "w"]=>["fowl", "wolf", "flow"]}
after which it is a simple matter of extracting the values of this hash.
Build a hash by appending words to arrays that are the values of the hash
words.each_with_object({}) { |w,h| (h[w.each_char.sort] ||= []) << w }.values
#=> [["demo", "dome", "mode"], ["none", "neon"], ["tied", "diet", "edit", "tide"],
# ["evil", "live", "veil", "vile"], ["fowl", "wolf", "flow"]]
When "demo" is passed to the block the hash h is empty, so the block variables are assigned values
w = "demo"
h = {}
and the block calculation is performed:
h[["d", "e", "m", "o"]] ||= []) << w
as
w.each_char.sort
#=> ["d", "e", "m", "o"]
Ruby first expands this to
h[["d", "e", "m", "o"]] = (h[["d", "e", "m", "o"]] ||= []) << "demo"
At this point h has no keys, so h[["d", "e", "m", "o"]] evaluates to nil. The expression therefore becomes
h[["d", "e", "m", "o"]] = (nil ||= []) << "demo"
= [] << "demo"
= ["demo"]
Later, when "dome" is encountered,
w = "dome"
w.each_char.sort
#=> ["d", "e", "m", "o"]
and since h already has this key, the block calculation is as follows.
h[["d", "e", "m", "o"]] = (h[["d", "e", "m", "o"]] ||= []) << "dome"
= (["demo"] ||= []) << "dome"
= ["demo"] << "dome"
= ["demo", "dome"]
We obtain
words.each_with_object({}) { |w,h| (h[w.each_char.sort] ||= []) << w }
#=> {["d", "e", "m", "o"]=>["demo", "dome", "mode"],
# ["e", "n", "n", "o"]=>["none", "neon"],
# ["d", "e", "i", "t"]=>["tied", "diet", "edit", "tide"],
# ["e", "i", "l", "v"]=>["evil", "live", "veil", "vile"],
# ["f", "l", "o", "w"]=>["fowl", "wolf", "flow"]}
after which the values are extracted.
A variant of this is the following.
words.each_with_object(Hash.new { |h,k| h[k] = []}) { |w,h|
h[w.each_char.sort] << w }.values
See the doc for Hash::new for an explanation, in particular the discussion of default values given by a block.
For each word, merge a hash having a single key into an initially-empty hash
words.each_with_object({}) { |w,h|
h.update(w.each_char.sort=>[w]) { |_,o,n| o+n } }.values
The argument w.each_char.sort=>[w] is shorthand for { w.each_char.sort=>[w] }.
This uses the form of Hash#update (aka merge!) that employs a "resolution" block (here { |_,o,n| o+n }) to determine the values of keys that are present in both hashes begin merged. See the doc for a description of that block's three keys (the first block variable, the common key, is not used in this calculation, which is why I used an underscore).

Related

How do I access the current array when using map/select

I have the following (working) code I'm trying to convert into a more concise snippet using either #map or #select.
def duplicate_string(string)
s_list = []
string.downcase.chars.each do |char|
if string.index(char) != string.rindex(char) && s_list.include?(char) == false
s_list << char if char != ' '
end
end
s_list
end
puts duplicate_string("I am a duplicate string") == ["i", "a", "t"] #true
This is what I've come up with so far, but I don't know how to access the current array that's been stored by #map or #select and using self isn't working
def duplicate_string_with_map(string)
string.downcase.chars.select { |char| string.index(char) != string.rindex(char) && self.include?(char) == false && char != ' ' }
end
The following code would solve your purpose:
def duplicate_string_with_map(string)
(string.downcase.chars.select { |char| string.index(char) != string.rindex(char) && char != ' ' }).uniq
end
Here you need not check include condition as you are already ensuring string.index(char) != string.rindex(char).
However, for a better ruby approach, I would suggest you to re-open String class and write a method there.
It would look something like this:
class String
def duplicate_characters_array
(downcase.chars.select { |char| index(char) != rindex(char) && char != ' ' }).uniq
end
end
string = "I am a duplicate string"
string.duplicate_characters_array
You don't need to access the array and you don't need to use Array#map.
There are many ways to reach the goal. One of them is to split the string in chars then group the chars (get a hash), reject the groups of space character and the groups smaller than two elements and return the keys of the remaining groups:
"I am a duplicate string"
.downcase
.chars
.group_by{|i| i}
.reject{|k, v| k == ' ' || v.length < 2}
.keys
# ["a", "i", "t"]
Here we can make use of a helper method, Array#difference. The method is explained here. Note that that link contains a link to an SO answer where I cite examples of its use. Though I proposed that the method be added to the Ruby core there appears to be little interest in doing so.
class Array
def difference(other)
h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
reject { |e| h[e] > 0 && h[e] -= 1 }
end
end
Here we can use this helper as follows.
def duplicate_string(str)
a = str.gsub(/\s/,'').downcase.reverse.chars
a.difference(a.uniq).uniq.reverse
end
duplicate_string "I am a duplicate string"
#=> ["a", "i", "t"]
The steps are as follows.
str = "I am a duplicate string"
b = str.gsub(/\s/,'')
#=> "Iamaduplicatestring"
c = b.downcase
#=> "iamaduplicatestring"
d = c.reverse
#=> "gnirtsetacilpudamai"
a = d.chars
#=> ["g", "n", "i", "r", "t", "s", "e", "t", "a", "c", "i", "l", "p",
# "u", "d", "a", "m", "a", "i"]
e = a.uniq
#=> ["g", "n", "i", "r", "t", "s", "e", "a", "c", "l", "p", "u", "d", "m"]
f = a.difference(e)
#=> ["t", "i", "a", "a", "i"]
g = f.uniq
#=> ["t", "i", "a"]
g.reverse
#=> ["a", "i", "t"]
The key step is the calculation of f. For each element c of e, f contains n-1 instances of c, where n is the number of instances of c in a. The method therefore excludes characters other than spaces that appear in the string exactly once.

My Ruby Anagram not working correctly

i was given an assignment to write an Anagram program
below is what i came up with
class Anagram
attr_accessor :anagram_value
def initialize(value)
#anagram_value = value
end
def matches(*collection)
matches = []
matches = collection.select do |word|
(word.length == #anagram_value.length) ? is_an_anagram?(word) : false
end
return matches
end
def is_an_anagram?(word)
return get_word_ord_sum(word) == get_word_ord_sum(#anagram_value)
end
def get_word_ord_sum(word)
sum = 0
word.split("").each { |c| sum += c.ord }
Areturn sum
end
end
while the Above works using the following cases, Surprisingly.
it "detects multiple Anagrams" do
subject = Anagram.new("allergy")
matches = subject.matches('gallery', 'ballerina', 'regally', 'clergy', 'largely', 'leading');
expect(matches).to eq ['gallery', 'regally', 'largely']
end
it actually fails the following
it "no matches" do
subject = Anagram.new("abc")
matches = subject.matches("bbb")
expect(matches).to eq []
end
The problem is that 97 + 98 + 99 == 98 + 98 + 98. Aka, the sum of the character numbers does not uniquely map to the histogram of a given string.
A way to fix it would be to map get_word_ord_sum to something else. For example, the "smallest" anagram will do. However, note it's O(nlgn):
word.chars.sort.join
EDIT: Expanding on the idea to use Array#group_by, replace get_word_ord_sum with:
word.downcase.chars.group_by(&:itself)
Now you will get a histogram-like hash, and since order of keys while comparing hashes doesn't matter, you will get your desired result in O(n).
This might help.
words = ['demo', 'none', 'tied', 'evil', 'dome', 'mode', 'live',
'fowl', 'veil', 'wolf', 'diet', 'vile', 'edit', 'tide',
'flow', 'neon']
groups = words.group_by { |word| word.split('').sort }
Return groups:
{["d", "e", "m", "o"]=>["demo", "dome", "mode"], ["e", "n", "n", "o"]=>["none", "neon"], ["d", "e", "i", "t"]=>["tied", "diet", "edit", "tide"], ["e", "i", "l", "v"]=>["evil", "live", "veil", "vile"], ["f", "l", "o", "w"]=>["fowl", "wolf", "flow"]}
groups.each { |x, y| p y }
Returns each value:
["demo", "dome", "mode"]
["none", "neon"]
["tied", "diet", "edit", "tide"]
["evil", "live", "veil", "vile"]
["fowl", "wolf", "flow"]

Ruby search for word in string

Given input = "helloworld"
The output should be output = ["hello", "world"]
Given I have a method called is_in_dict? which returns true if there's a word given
So far i tried:
ar = []
input.split("").each do |f|
ar << f if is_in_dict? f
// here need to check given char
end
How to achieve it in Ruby?
Instead of splitting the input into characters, you have to inspect all combinations, i.e. "h", "he", "hel", ... "helloworld", "e", "el" , "ell", ... "elloworld" and so on.
Something like this should work:
(0..input.size).to_a.combination(2).each do |a, b|
word = input[a...b]
ar << word if is_in_dict?(word)
end
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ar
#=> ["hello", "world"]
Or, using each_with_object, which returns the array:
(0..input.size).to_a.combination(2).each_with_object([]) do |(a, b), array|
word = input[a...b]
array << word if is_in_dict?(word)
end
#=> ["hello", "world"]
Another approach is to build a custom Enumerator:
class String
def each_combination
return to_enum(:each_combination) unless block_given?
(0..size).to_a.combination(2).each do |a, b|
yield self[a...b]
end
end
end
String#each_combination yields all combinations (instead of just the indices):
input.each_combination.to_a
#=> ["h", "he", "hel", "hell", "hello", "hellow", "hellowo", "hellowor", "helloworl", "helloworld", "e", "el", "ell", "ello", "ellow", "ellowo", "ellowor", "elloworl", "elloworld", "l", "ll", "llo", "llow", "llowo", "llowor", "lloworl", "lloworld", "l", "lo", "low", "lowo", "lowor", "loworl", "loworld", "o", "ow", "owo", "owor", "oworl", "oworld", "w", "wo", "wor", "worl", "world", "o", "or", "orl", "orld", "r", "rl", "rld", "l", "ld", "d"]
It can be used with select to easily filter specific words:
input.each_combination.select { |word| is_in_dict?(word) }
#=> ["hello", "world"]
This seems to be a task for recursion. In short you want to take letters one by one until you get a word which is in dictionary. This however will not guarantee that the result is correct, as the remaining letters may not form a words ('hell' + 'oworld'?). This is what I would do:
def split_words(string)
return [[]] if string == ''
chars = string.chars
word = ''
(1..string.length).map do
word += chars.shift
next unless is_in_dict?(word)
other_splits = split_words(chars.join)
next if other_splits.empty?
other_splits.map {|split| [word] + split }
end.compact.inject([], :+)
end
split_words('helloworld') #=> [['hello', 'world']] No hell!
It will also give you all possible splits, so pages with urls like penisland can be avoided
split_words('penisland') #=> [['pen', 'island'], [<the_other_solution>]]

Enumerator `Array#each` 's {block} can't always change array values?

Ok maybe this is simple but...
given this:
arr = ("a".."z").to_a
arr
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
..and that I'm trying to change all "arr" values to "bad"
why isn't this working ?
arr.each { |v| v = "bad" }
arr
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
Answers suggested that "v" is a local variable to the block (a "copy" of the array value) and I fully understand that (and never puzzled me before) but then
.. why it is working if array elements are objects ?
class Person
def initialize
#age = 0
end
attr_accessor :age
end
kid = Person.new
man = Person.new
arr = [kid, man]
arr.each { |p| p.age = 50 }
arr[0]
=> #<Person:0xf98298 #age=50>
isn't here "p" still local to the block here?
but then it really affects the objects, how come ?
I'll expand upon #pst's comment:
why isn't this working ?
arr.each { |v| v = "bad" }
Because each iterates through the array and puts each item into the block you've given as a local variable v, as v is not a reference to the array arr.
new_arr = arr.each { |v| v = "bad" }
each does not give back an array, for that you would use map (see #benjaminbenben's answer). Therefore assigning it does not "work".
arr.each { |v| arr[arr.index v] = "bad" }
Here you put each item in arr into the local variable v, but you've also referred to the array itself in the block, hence you are able to assign to the array and use the local variable v to find an index that corresponds to the contents of v (but you may find this wouldn't work as you expect when the items are not all unique).
arr.each { |p| p.age = 50 }
kid.age #-> 50
Here, again you've filled the local variable p with each item/object in arr, but then you've accessed each item via a method, so you are able to change that item - you are not changing the array. It's different because the reference is to the contents of the local variable, which you've mixed up with being a reference to the array. They are separate things.
In response to the comment below:
arr[0]
# => #<Person:0xf98298 #age=50>
It's all about who's referring to whom when.
Try this:
v = Person.new
# => #<Person:0x000001008de248 #age=0>
w = Person.new
# => #<Person:0x000001008d8050 #age=0>
x = v
# => #<Person:0x000001008de248 #age=0>
v = Person.new
# => #<Person:0x00000100877e80 #age=0>
arr = [v,w,x]
# => [#<Person:0x00000100877e80 #age=0>, #<Person:0x000001008d8050 #age=0>, #<Person:0x000001008de248 #age=0>]
v referred to 2 different objects there. v is not a fixed thing, it's a name. At first it refers to #<Person:0x000001008de248 #age=0>, then it refers to #<Person:0x00000100877e80 #age=0>.
Now try this:
arr.each { |v| v = "bad" }
# => [#<Person:0x00000100877e80 #age=0>, #<Person:0x000001008d8050 #age=0>, #<Person:0x000001008de248 #age=0>]
They are all objects but nothing was updated or "worked". Why? Because when the block is first entered, v refers to the item in the array that was yielded (given). So on first iteration v is #<Person:0x00000100877e80 #age=0>.
But, we then assign "bad" to v. We are not assigning "bad" to the first index of the array because we aren't referencing the array at all. arr is the reference to the array. Put arr inside the block and you can alter it:
arr.each { |v|
arr[0] = "bad" # yes, a bad idea!
}
Why then does arr.each { |p| p.age = 50 } update the items in the array? Because p refers to the objects that also happen to be in the array. On first iteration p refers to the object also known as kid, and kid has an age= method and you stick 50 in it. kid is also the first item in the array, but you're talking about kid not the array. You could do this:
arr.each { |p| p = "bad"; p.age }
NoMethodError: undefined method `age' for "bad":String
At first, p referred to the object that also happened to be in the array (that's where it was yielded from), but then p was made to refer to "bad".
each iterates over the array and yields a value on each iteration. You only get the value not the array. If you want to update an array you either do:
new_arr = arr.map{|v| v = "bad" }
new_arr = arr.map{|v| "bad" } # same thing
or
arr.map!{|v| v = "bad"}
arr.map!{|v| "bad"} # same thing
as map returns an array filled with the return value of the block. map! will update the reference you called it on with an array filled with the return value of the block. Generally, it's a bad idea to update an object when iterating over it anyway. I find it's always better to think of it as creating a new array, and then you can use the ! methods as a shortcut.
In example
arr.each { |v| v = "bad" }
"v" is just reference to string, when you do v = "bad", you reassign local variable. To make everything bad you can do like that:
arr.each { |v| v.replace "bad" }
Next time you can play with Object#object_id
puts arr[0].object_id #will be save as object_id in first iteration bellow
arr.each { |v| puts v.object_id }
You might be looking for .map - which returns a new array with the the return value of the block for each element.
arr.map { "bad" }
=> ["bad", "bad", "bad", "bad", …]
using .map! will alter the contents of the original array rather than return a new one.
How about this
arry = Array.new(arry.length,"bad")
This will set the a default value of "bad" to the arry.length

Determining if a prefix exists in a set

Given a set of strings, say:
"Alice"
"Bob"
"C"
"Ca"
"Car"
"Carol"
"Caroling"
"Carousel"
and given a single string, say:
"Carolers"
I would like a function that returns the smallest prefix not already inside the array.
For the above example, the function should return: "Caro". (A subsequent call would return "Carole")
I am very new to Ruby, and although I could probably hack out something ugly (using my C/C++/Objective-C brain), I would like to learn how to properly (elegantly?) code this up.
There's a little known magical module in Ruby called Abbrev.
require 'abbrev'
abbreviations = Abbrev::abbrev([
"Alice",
"Bob",
"C",
"Ca",
"Car",
"Carol",
"Caroling",
"Carousel"
])
carolers = Abbrev::abbrev(%w[Carolers])
(carolers.keys - abbreviations.keys).sort.first # => "Caro"
Above I took the first element but this shows what else would be available.
pp (carolers.keys - abbreviations.keys).sort
# >> ["Caro", "Carole", "Caroler", "Carolers"]
Wrap all the above in a function, compute the resulting missing elements, and then iterate over them yielding them to a block, or use an enumerator to return them one-by-one.
This is what is generated for a single word. For an array it is more complex.
require 'pp'
pp Abbrev::abbrev(['cat'])
# >> {"ca"=>"cat", "c"=>"cat", "cat"=>"cat"}
pp Abbrev::abbrev(['cat', 'car', 'cattle', 'carrier'])
# >> {"cattl"=>"cattle",
# >> "catt"=>"cattle",
# >> "cat"=>"cat",
# >> "carrie"=>"carrier",
# >> "carri"=>"carrier",
# >> "carr"=>"carrier",
# >> "car"=>"car",
# >> "cattle"=>"cattle",
# >> "carrier"=>"carrier"}
Your question still doesn't match what you are expecting as a result. It seems that you need prefixes, not the substrings (as "a" would be the shortest substring not already in the array). For searching the prefix, this should suffice:
array = [
"Alice",
"Bob",
"C",
"Ca",
"Car",
"Carol",
"Caroling",
"Carousel",
]
str = 'Carolers'
(0..str.length).map{|i|
str[0..i]
}.find{|s| !array.member?(s)}
I am not a Ruby expert, but I think you may want to approach this problem by converting your set into a trie. Once you have the trie constructed, your problem can be solved simply by walking down from the root of the trie, following all of the edges for the letters in the word, until you either find a node that is not marked as a word or walk off the trie. In either case, you've found a node that isn't part of any word, and you have the shortest prefix of your word in question that doesn't already exist inside of the set. Moreover, this would let you run any number of prefix checks quickly, since after you've built up the trie the algorithm takes time at most linear in the length of the string.
Hope this helps!
I'm not really sure what you're asking for other than an example of some Ruby code to find common prefixes. I'll assume you want to find the smallest string which is a prefix of the most number of strings in the given set. Here's an example implementation:
class PrefixFinder
def initialize(words)
#words = Hash[*words.map{|x|[x,x]}.flatten]
end
def next_prefix
max=0; biggest=nil
#words.keys.sort.each do |word|
0.upto(word.size-1) do |len|
substr=word[0..len]; regex=Regexp.new("^" + substr)
next if #words[substr]
count = #words.keys.find_all {|x| x=~regex}.size
max, biggest = [count, substr] if count > max
#puts "OK: s=#{substr}, biggest=#{biggest.inspect}"
end
end
#words[biggest] = biggest if biggest
biggest
end
end
pf = PrefixFinder.new(%w(C Ca Car Carol Caroled Carolers))
pf.next_prefix # => "Caro"
pf.next_prefix # => "Carole"
pf.next_prefix # => "Caroler"
pf.next_prefix # => nil
No comment on the performance (or correctness) of this code but it does show some Ruby idioms (instance variables, iteration, hashing, etc).
=> inn = ["Alice","Bob","C","Ca","Car","Carol","Caroling","Carousel"]
=> y = Array.new
=> str="Carolers"
Split the given string to an array
=> x=str.split('')
# ["C","a","r","o","l","e","r","s"]
Form all the combination
=> x.each_index {|i| y << x.take(i+1)}
# [["c"], ["c", "a"], ["c", "a", "r"], ["c", "a", "r", "o"], ["c", "a", "r", "o", "l"], ["c", "a", "r", "o", "l", "e"], ["c", "a", "r", "o", "l", "e", "r"], ["c", "a", "r", "o", "l", "e", "r", "s"]]
Using Join to concatenate the
=> y = y.map {|s| s.join }
# ["c", "ca", "car", "caro", "carol", "carole", "caroler", "carolers"]
Select the first item from the y thats not available in the input Array
=> y.select {|item| !inn.include? item}.first
You will get "caro"
Putting together all
def FindFirstMissingItem(srcArray,strtocheck)
y=Array.new
x=strtocheck.split('')
x.each_index {|i| y << x.take(i+1)}
y=y.map {|s| s.join}
y.select {|item| !srcArray.include? item}.first
end
And call
=> inn = ["Alice","Bob","C","Ca","Car","Carol","Caroling","Carousel"]
=> str="Carolers"
FindFirstMissingItem inn,str
Very simple version (but not very Rubyish):
str = 'Carolers'
ar = %w(Alice Bob C Ca Car Carol Caroling Carousel)
substr = str[0, n=1]
substr = str[0, n+=1] while ar.include? substr
puts substr

Resources