Reputation: 177
I'm working on this function:
It's supposed to take in an array and match it with a given word to see if that word can be formed with the given array of strings.
I added the two commented lines because I wanted to see how the for-loop works.
def canformword(arr,word)
arrword = word.chars
arrleft = arr
flag = true
for i in 0...arrword.size
ch = arrword[i]
# puts arrword[i]
if !arrleft.include?(ch)
flag = false
break
else
ind = arrleft.index(ch)
# puts ind
arrleft.delete_at(ind)
end
end
if flag
puts 'can form word'
else
puts 'can not form word'
end
end
canformword(['y','b','z','e','a','u','t'], 'beauty')
canformword(['r','o','u','g','h'], 'tough')
When I uncomment those two lines, the following is the output:
Why does the output print out the index 2 repeatedly? I would think that it would print out the index of each letter in my arrleft array rather than repeatedly spitting out 2!
I understand the 1 it prints out, because that's the index of b, but the rest is weird to me.
b
1
e
2
a
2
u
2
t
2
y
0
can form word
t
can not form word
Upvotes: 1
Views: 77
Reputation: 54223
If you want do delete index 2 and 3 from an array, you need to delete them in decreasing order, becausing deleting index 2 would modify index of 3:
array = %w(a b c d e)
array.delete_at(3)
array.delete_at(2)
p array
#=> ["a", "b", "e"]
or
array = %w(a b c d e)
array.delete_at(2)
array.delete_at(2)
p array
#=> ["a", "b", "e"]
For your code, you just need to replace
arrleft.delete_at(ind)
with
arrleft[ind] = nil
Since you take the numbers of characters into account, here's a modified version of a previous answer :
class Array
def count_by
each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
end
def subset_of?(superset)
superset_counts = superset.count_by
count_by.all? { |k, count| superset_counts[k] >= count }
end
end
def can_form_word?(chars, word)
word.chars.subset_of?(chars)
end
p can_form_word?(['y','b','z','e','a','u','t'], 'beauty')
#=> true
p can_form_word?(['y','b','z','e','u','t'], 'beauty')
#=> false
p can_form_word?(['a', 'c', 'e', 'p', 't', 'b', 'l'], 'acceptable')
#=> false
p ('acceptable'.chars - ['a', 'c', 'e', 'p', 't', 'b', 'l']).empty?
#=> true
Upvotes: 1
Reputation: 2359
hear a better implementation that
def can_form_word?(chars_array, word)
(word.chars - chars_array).empty?
end
that's all.
here another implementation the Ruby way. Because your code is like C
. I've been writing Ruby code for more than three years now, and I never used for
loops.
def canformword(chars,word)
word.each_char do |char|
puts char
if !chars.include?(char)
return false # or puts "Can't form word"
end
end
true # or puts "Can form word"
end
Upvotes: 3
Reputation: 30056
You obtain 2 several times because you are deleting elements from the array. In that case you delete the second element every time so the next character, in the next iteration, take the index 2 again.
Upvotes: 2
Reputation: 2052
this is because you are deleting the character at position ind(arrleft.delete_at(ind)); so each time array characters are shifting one cell left. Now as all your letters 'e','a','u','t','y' are placed ordered way so it is showing 2,2,2,2 continuously. Now look at 'y'; it is at position 0 ; so 0 is printed at end.
So the issue is because you are deleting the characters at position 'ind'.
So, to achieve this you can just do one thing ; do not delete the characters when found rather replace it by some numeric value like '0'.
Upvotes: 2