Why does this:
elements = Hash.new()
elements[100] = "a"
elements[200] = "b"
elements[300] = "c"
elements[400] = "d"
print "Count: ", elements.count(),
elements.delete(100)
print "Count: ", elements.count(),
return this:
Count: 4
Count: 3
I wonder why that wouldn't return anything except the value 100.
This is working as expected.
You are printing the count for your elements hash which is 4 at the beginning, then you are deleing one element using: elements.delete(100) then printing the count again, which is 3 now.
See this way to understand what's going on with your elements hash:
elements = Hash.new()
elements[100] = "a"
elements[200] = "b"
elements[300] = "c"
elements[400] = "d"
puts "elements: #{elements.inspect}"
puts "Count: #{elements.count()}"
elements.delete(100)
puts "elements: #{elements.inspect}"
puts "Count: #{elements.count()}"
# > elements: {100=>"a", 200=>"b", 300=>"c", 400=>"d"}
# > Count: 4
# > elements: {200=>"b", 300=>"c", 400=>"d"}
# > Count: 3
Related
I'm writing a program which takes input, stores it as a hash and sorts the values.
I'm having trouble comparing a current hash value with a variable.
Sample Input:
3
A 1
B 3
C 5
A 2
B 7
C 2
Sample Output:
A 1 2
B 3 7
C 2 5
Everything works apart from this part, and I'm unsure why.
if values.key?(:keys)
if values[keys] >= val
values.store(keys,val.prepend(val + " "))
else
values.store(keys,val.concat(" " + val))
end
else
values.store(keys,val)
end
i = i + 1
end
Rest of code:
#get amount of records
size = gets.chomp
puts size
size = size.to_i
values = Hash.new(0)
i = 0
while i < (size * 2)
text = gets.chomp
#split string and remove space
keys = text.split[0]
val = text.split[1]
#check if key already exists,
# if current value is greater than new value append new value to end
# else put at beginning of current value
if values.key?(:keys)
if values[keys] >= val
values.store(keys,val.prepend(val + " "))
else
values.store(keys,val.concat(" " + val))
end
else
values.store(keys,val)
end
i = i + 1
end
#sort hash by key
values = values.sort_by { |key, value| key}
#output hash values
values.each{|key, value|
puts "#{key}:#{value}"
}
Could anyone help me out? It would be most appreciated.
The short answer is that there are two mistakes in your code. Here is the fixed version:
if values.key?(keys)
if values[keys] >= val
values.store(keys,values[keys].prepend(val + " "))
else
values.store(keys,values[keys].concat(" " + val))
end
else
values.store(keys,val)
end
The if statement was always evaluating as false, because you were looking for hash key named :keys (which is a Symbol), not the variable you've declared named keys.
Even with that fixed, there was a second hidden bug: You were storing a incorrect new hash value. val.concat(" " + val) would give you results like A 2 2, not A 1 2, since it's using the new value twice, not the original value.
With that said, you code is still very confusing to read... Your variables are size, i, text, val, values, key and keys. It would have been a lot easier to understand with clearer variable names, if nothing else :)
Here is a slightly improved version, without changing the overall structure of your code:
puts "How may variables to loop through?"
result_length = gets.chomp.to_i
result = {}
puts "Enter #{result_length * 2} key-value pairs:"
(result_length * 2).times do
input = gets.chomp
input_key = input.split[0]
input_value = input.split[1]
#check if key already exists,
# if current value is greater than new value append new value to end
# else put at beginning of current value
if result.key?(input_key)
if result[input_key] >= input_value
result[input_key] = "#{input_value} #{result[input_key]}"
else
result[input_key] = "#{result[input_key]} #{input_value}"
end
else
result[input_key] = input_value
end
end
#sort hash by key
result.sort.to_h
#output hash result
result.each{|key, value|
puts "#{key}:#{value}"
}
h = Hash.new { |h,k| h[k] = [] }
input = ['A 1', 'B 3', 'C 5', 'A 2', 'B 7', 'C 2'].join("\n")
input.each_line { |x| h[$1] << $2 if x =~ /^(.*?)\s+(.*?)$/ }
h.keys.sort.each do |k|
puts ([k] + h[k].sort).join(' ')
end
# A 1 2
# B 3 7
# C 2 5
This would be a more Ruby-ish way to write your code :
input = "A 1
B 3
C 5
A 2
B 7
C 2"
input.scan(/[A-Z]+ \d+/)
.map{ |str| str.split(' ') }
.group_by{ |letter, _| letter }
.each do |letter, pairs|
print letter
print ' '
puts pairs.map{ |_, number| number }.sort.join(' ')
end
#=>
# A 1 2
# B 3 7
# C 2 5
I am grabbing some data from a list and I want to rank the items. There are 100 items from the list. When I run my code I get the data I am looking for but before every data I get "100" when it should be "1. ... 2. ..." Here is my code
lineList = mdoc.read.split("\n")
songList = []
count = 0
lineList.each do |line|
matchObj = line.match(/<td>(\S+.+)<\/td>/)
if matchObj then
songList.push(matchObj.captures[0])
count = count + 1
end
end
songList.each do |title|
puts count.to_s + ". " + title
end
The typical way to display a list is this:
song_list.each_with_index do |song, i|
puts '%d. %s' % [ i + 1, song ]
end
This uses the string formatting function % and each_with_index.
I need to count the number of vowels,words,pronouns("he,she,them") in each line of a string entered by user. if input is "they are playing. he is studying" the output expected is Sentence 1 has 3 words,has 4 vowels , 1 pronoun. \nSentence 2 has 3 words,4 vowels , 1 pronoun. I have written the following code but getting an error unexpected-end-of-input.
string = gets
string =string.chomp
sentencecount = 0
wordcount = 0
pronouns={"He"=>0,"She"=>0,"They"=>0,"Them"=>0}
procount=0;
string.split(".").each do |sentence|
wordcount = 0
sentencecount += 1 #tracking number of sentences
vowels=sentence.scan(/[aeoui]/).count
procount=0
sentence.split(/\w+/).each do |word|
pronouns.each do|key,value|
if (key.eq word)
procount++
wordcount += 1 # tracking number of words
end
puts "Sentence #{sentencecount} has #{wordcount} words, has #{vowels} vowels"
end
you don't need semicolon at the end of the lines
if requires an end (unless it's the inline form)
++ operator doesn't exist in Ruby
you compare two strings with the == operator (it's a method actually)
string = gets.chomp
sentencecount = 0
wordcount = 0
pronouns = {"He"=>0, "She"=>0, "They"=>0, "Them"=>0}
procount = 0
string.split(".").each do |sentence|
wordcount = 0
sentencecount += 1 #tracking number of sentences
vowels = sentence.scan(/[aeoui]/).count
procount = 0
sentence.split(/\w+/).each do |word|
pronouns.each do|key, value|
if key == word
procount += 1
end
wordcount += 1 # tracking number of words
end
end
puts "Sentence #{sentencecount} has #{wordcount} words, has #{vowels} vowels"
end
Based off of your initial attempt, I've optimized it slightly and make it more readable in terms of code.
string = gets.chomp
pronouns = ['he', 'she', 'they', 'them']
total_word_count = 0
total_procount = 0
total_vowel_count = 0
sentences = string.split(".")
total_sentence_count = sentences.size
sentences.each_with_index do |sentence, idx|
# VOWELS
vowel_count = sentence.scan(/[aeoui]/).count
total_vowel_count += vowel_count
# WORDS
words = sentence.split
sentence_word_count = words.size
total_word_count += sentence_word_count
# PRONOUNS
sentence_procount = 0
words.each do |word|
sentence_procount += 1 if pronouns.include?(word.downcase)
end
total_procount += sentence_procount
puts "Sentence #{idx + 1} has #{sentence_word_count} words, has #{vowel_count} vowels"
end
puts "Input has #{total_sentence_count} sentences, #{total_word_count} words, #{total_vowel_count} vowels, and #{total_procount} pronouns"
I suggest you return an array of hashes, one for each line, each hash containing statistics for the associated line. You can then do what you want with the information in that array.
VOWELS = 'aeiou'
PRONOUNS = %w| he she they them |
#=> ["he", "she", "they", "them"]
PRONOUN_REGEX = /\b#{Regexp.union(PRONOUNS)}\b/
#=> /\b(?-mix:he|she|they|them)\b/
def count_em(str)
str.downcase.split(/\n/).map { |line|
{ vowels: line.count(VOWELS),
words: line.scan(/[[:lower:]]+/).count,
pronouns: line.scan(PRONOUN_REGEX).size } }
end
a = count_em "He thought that she thought that he did not know the truth\n" +
"René knew she would torment them until they went bananas\n"
#=> [{:vowels=>14, :words=>12, :pronouns=>3},
# {:vowels=>15, :words=>10, :pronouns=>3}]
a.each.with_index(1) { |h,i|
puts "In line #{i} there are %d vowels, %d words and %d pronouns" %
h.values_at(:vowels, :words, :pronouns) }
# In line 1 there are 14 vowels, 12 words and 3 pronouns
# In line 2 there are 15 vowels, 10 words and 3 pronouns
puts "The total number of vowels in all lines is %d" %
a.map { |h| h[:vowels] }.reduce(:+)
# The total number of vowels in all lines is 29
This solution is incomplete in that it doesn't deal with contractions ("don't"), possessives ("Mary's"), abbreviations ("1st"), initials and numeric parts of names ("J. Philip ('Phil') Sousa III") and other twists of the English language.
I am trying to create a program where two strings are entered. If they match it returns the number of positions where they contain the same length 2 substring.
for example:string_match('xxcaazz', 'xxbaaz') → 3 "xx" "aa" "az"
My question is what metacharacters should i use to validate
here is what i have come up with
puts "enter word"
a = STDIN.gets
a.chomp!
puts"enter word"
b = STDIN.gets
b.chomp!
if a == /word/ or b == /word/ then
puts str.match(/{a} {b}/) + "equal"
end
UPDATED ANSWER:
( Still spiked, but better )
first_word = 'xxcaazz'.split('')
second_word ='xxbaaz'.split('')
first_word_length = first_word.length
second_word_length = second_word.length
if [first_word_length, second_word_length].min == first_word_length
inner_word = second_word
outter_word = first_word
else
inner_word = first_word
outter_word = second_word
end
outter_word_length = outter_word.length - 2
word_matches = 0
(0..outter_word_length).each do |character|
if "#{outter_word[character]}#{outter_word[character + 1]}" == "#{inner_word[character]}#{inner_word[character + 1]}"
puts "#{outter_word[character]}#{outter_word[character + 1]}"
word_matches += 1
end
end
puts "Found #{word_matches} matches"
ORIGINAL SPIKE:
This may get you off to a good start ( though it's by no means bullet proof, just a quick spike ):
first_word = 'xxcaazz'.split('')
second_word ='xxbaaz'.split('')
first_word_length = first_word.length
(0..first_word_length).each do |character|
if "#{second_word[character]}#{second_word[character + 1]}" == "#{first_word[character]}#{first_word[character + 1]}"
puts "#{second_word[character]}#{second_word[character + 1]}"
end
end
Unpack 'a2X' means extract the 2 bytes, then rewind 1 byte:
first_word = 'xxcaazz'
second_word ='xxbaaz'
tokens = first_word.unpack 'a2X' * (first_word.length - 1)
# => ["xx", "xc", "ca", "aa", "az", "zz"]
tokens.flat_map{|m| second_word.scan m}
# => ["xx", "aa", "az"]
This is probably easy to do! I'm not able envision the loop yet, I was thinking about a nested for loop but not quite sure how to alternate between the two hashes.
Lets say I have a class with a def that containts two hash tables:
class Teststuff
def test_stuff
letters = { "0" => " A ", "1" => " B ", "2" => " C " }
position = {"1" => "one ", "2"=> " two ", "3"=> " three ", "4"=>" four " }
my_array=[0,1,2,2] #this represents user input stored in an array valid to 4 elements
array_size = my_array.size #this represents the size of the user inputed array
element_indexer = my_array.size # parellel assignment so I can use same array for array in dex
array_start_index = element_indexer-1 #give me the ability later to get start at index zero for my array
#for loop?? downto upto??
# trying to get loop to grab the first number "0" in element position "0", grab the hash values then
# the loop repeats and grabs the second number "1" in element position "1" grab the hash values
# the loop repeats and grabs the third number "2" in elements position "2" grab the hash values
# the final iteration grabs the fourth number "2" in elements position "3" grab the hash values
# all this gets returned when called. Out put from puts statement after grabing hash values
# is: **A one B two C three C four**
return a_string
end
end
How do I go about returning string output to the screen like this:
**A one B two C three C four**
or simply letter position letter position...
Thanks for the help, put code up so I can try on my editor!
I think I figured out what it is you want, although I still have no idea what array_size, element_indexer, array_start_index and TestStuff are for.
def test_stuff
letters = { "0" => " A ", "1" => " B ", "2" => " C " }
position = {"1" => "one ", "2"=> " two ", "3"=> " three ", "4"=>" four " }
my_array = [0, 1, 2, 2]
"**#{my_array.map.with_index {|e, i|
"#{letters[e.to_s].strip} #{position[(i+1).to_s].strip}"
}.join(' ')}**"
end
[I took the liberty of reformatting your code to standard Ruby coding style.]
However, everything would be much simpler, if there weren't all those type conversions, and all those superfluous spaces. Also, the method would be much more useful, if it actually had a way to return different results, instead of always returning the same thing, because at the moment, it is actually exactly equivalent to
def test_stuff
'**A one B two C three C four**'
end
Something along these lines would make much more sense:
def test_stuff(*args)
letters = %w[A B C]
position = %w[one two three four]
"**#{args.map.with_index {|e, i| "#{letters[e]} #{position[i]}" }.join(' ')}**"
end
test_stuff(0, 1, 2, 2)
# => '**A one B two C three C four**'
If you don't want to pollute the Object namespace with your method, you could do something like this:
def (TestStuff = Object.new).test_stuff(*args)
letters = %w[A B C]
position = %w[one two three four]
"**#{args.map.with_index {|e, i| "#{letters[e]} #{position[i]}" }.join(' ')}**"
end
TestStuff.test_stuff(0, 1, 2, 2)
# => '**A one B two C three C four**'
You can use enumerators, like this:
l = letters.to_enum
p = position.to_enum
a_string = ''
loop do
a_string << l.next[1] << p.next[1]
end
How about :
a_string = ""
my_array.each_with_index { |x, index|
a_string += letters[my_array[index].to_s] + " " + (position.include?((index+1).to_s) ? position[(index+1).to_s] : "nil")
}