I'm completely new to ruby and wanted to ask for some help with this ruby script.
it's supposed to take in a string and find out which character occurs the most frequently. It does this using a hash, it stores all the characters in a hash and then iterates through it to find the one with greatest value. As of right now it doesn't seem to be working properly and i'm not sure why. It reads the characters in properly as far as i can tell with print statements. Any help is appreciated.
Thanks!
puts "Enter the string you want to search "
input = gets.chomp
charHash = Hash.new
input.split("").each do |i|
if charHash.has_key?(i)
puts "incrementing"
charHash[i]+=1
else
puts"storing"
charHash.store(i, 1)
end
end
goc = ""
max = 0
charHash.each { |key,value| goc = key if value > max }
puts "The character #{goc} occurs the most frequently"
There are two major issues with you code:
As commented by Holger Just, you have to use += 1 instead of ++
charHash.store(:i, 1) stores the symbol :i, you want to store i
Fixing these results in a working code (I'm using snake_case here):
char_hash = Hash.new
input.split("").each do |i|
if char_hash.has_key?(i)
char_hash[i] += 1
else
char_hash.store(i, 1)
end
end
You can omit the condition by using 0 as your default hash value and you can replace split("").each with each_char:
char_hash = Hash.new(0)
input.each_char do |i|
char_hash[i] += 1
end
Finally, you can pass the hash into the loop using Enumerator#with_object:
char_hash = input.each_char.with_object(Hash.new(0)) { |i, h| h[i] += 1 }
I might be missing something but it seems that instead of
charHash.each { |key,value| goc = key if value > max }
you need something like
charHash.each do |key,value|
if value > max then
max = value
goc = key
end
end
Notice the max = value statement. In your current implementation (i.e. without updating the max variable), every character that appears in the text at least once satisfies the condition and you end up getting the last one.
Related
I am working on this coding challenge, and I have found that I am stuck. I thought it was possible to call the .string method on an argument that was passed in, but now I'm not sure. Everything I've found in the Ruby documentation suggests otherwise. I'd really like to figure this out without looking at the solution. Can someone help give me a push in the right direction?
# Write a method that will take a string as input, and return a new
# string with the same letters in reverse order.
# Don't use String's reverse method; that would be too simple.
# Difficulty: easy.
def reverse(string)
string_array = []
string.split()
string_array.push(string)
string_array.sort! { |x,y| y <=> x}
end
# These are tests to check that your code is working. After writing
# your solution, they should all print true.
puts(
'reverse("abc") == "cba": ' + (reverse("abc") == "cba").to_s
)
puts(
'reverse("a") == "a": ' + (reverse("a") == "a").to_s
)
puts(
'reverse("") == "": ' + (reverse("") == "").to_s
)
This is the simplest one line solution, for reversing a string without using #reverse, that I have come across -
"string".chars.reduce { |x, y| y + x } # => "gnirts"
Additionally, I have never heard of the #string method, I think you might try #to_s.
Easiest way to reverse a string
s = "chetan barawkar"
b = s.length - 1
while b >= 0
print s[b]
b=b-1
end
You need to stop the search for alternative or clever methods, such as altering things so you can .sort them. It is over-thinking the problem, or in some ways avoiding thinking about the core problem you have been asked to solve.
What this test is trying to get you you to do, is understand the internals of a String, and maybe get an appreciation of how String#reverse might be implemented using the most basic string operations.
One of the most basic String operations is to get a specific character from the string. You can get the first character by calling string[0], and in general you can get the nth character (zero-indexed) by calling string[n].
In addition you can combine or build longer strings by adding them together, e.g. if you had a="hell" and b="o", then c = a + b would store "hello" in the variable c.
Using this knowledge, find a way to loop through the original string and use that to build the reverse string, one character at a time. You may also need to look up how to get the length of a string (another basic string method, which you will find in any language's string library), and how to loop through numbers in sequence.
You're on the right track converting it to an array.
def reverse(str)
str.chars.sort_by.with_index { |_, i| -i }.join
end
Here is a solution I used to reverse a string without using .reverse method :
#string = "abcde"
#l = #string.length
#string_reversed = ""
i = #l-1
while i >=0 do
#string_reversed << #string[i]
i = i-1
end
return #string_reversed
Lol, I am going through the same challenge. It may not be the elegant solution, but it works and easy to understand:
puts("Write is a string that you want to print in reverse")
#taking a string from the user
string = gets.to_s #getting input and converting into string
def reverse(string)
i = 0
abc = [] # creating empty array
while i < string.length
abc.unshift(string[i]) #populating empty array in reverse
i = i + 1
end
return abc.join
end
puts ("In reverse: " + reverse(string))
Thought i'd contribute my rookie version.
def string_reverse(string)
new_array = []
formatted_string = string.chars
new_array << formatted_string.pop until formatted_string.empty?
new_array.join
end
def reverse_str(string)
# split a string to create an array
string_arr = string.split('')
result_arr = []
i = string_arr.length - 1
# run the loop in reverse
while i >=0
result_arr.push(string_arr[i])
i -= 1
end
# join the reverse array and return as a string
result_arr.join
end
I have this file.rb and when I run it from terminal, I want to delete a certain input value. However, the array remains the same. Any help, please?
def delete
print "Introduce the parameter for the delete action"
delete_value = gets.chomp
p #array.select { |e| e!= "#{delete_value}"}
##second_array = #array.reject! {|x| x == "#{delete_value}" }
#puts #second_array
end
You have an array of numbers:
#array = [-3,6,5,3,10,6,2,3,9,-3,-2,-5]
But your delete_value is a string:
delete_value = gets.chomp
a == b is false for every Fixnum a and String b (and similarly a != b is always true) so you'll need to convert b to a number with something like:
delete_value = gets.to_i
#array.reject! { |x| x == delete_value }
Ruby doesn't automatically convert between strings and numbers the way some languages will, you have to make the types match and perform the type conversions by hand.
This method return a new array with all matches. Your original array will indeed not change at all.
For further reference: http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-select
I was wondering if it is possible to return to an Each iterator in Ruby from within a for-loop placed within the block passed to Each.
def find member = ""
productHash = {}
##entries is a hash, with both the keys and values being strings
#the member parameter is a string
#entries.each do |key, value|
for i in 0...member.size
if(key[i] != member[i])
next #the next keyword doesn't work...all it does is return to the for iterator. I'm looking for a keyword that would return to the each iterator, and allow each to pass back in the next key-value pair.
end
end
productHash[key] = value
end
productHash
end
What I'm trying to accomplish is this: the moment I see that a character in the member parameter doesn't match the corresponding character in a given key, I move on to the next key-value pair.
It looks like you're trying to do some kind of comparison where if the key matches a particular prefix specified by member then you would make an assignment.
This code should be functionally similar:
def find(member = "")
hash = { }
#entries.each do |key, value|
# Unless key begins with prefix, skip it.
next unless (key[0, prefix.length] == prefix)
hash[key] = value
end
hash
end
There's no official goto statement in Ruby, and many would argue this is a good thing, but it means that busting out of nested blocks can be a bit tricky.
Still, if you approach the problem in the right way, there's almost always a solution that's elegant enough.
Update:
To break out of nested loops, an approach might be:
list.each do |i|
broken = false
inner_list.each do |j|
if (j > 10)
broken = true
break
end
end
break if (broken)
end
So, here's the preface:
I'm quite a beginner in Ruby. I'm working on a anagram finding script (find all anagrams in a text file). The essence is: I create a dictionary where key is word code and value is an array with words that refer to this code. It is like that: {"abdeis"=>["abides", "biased"] ,"achr"=>["char"], ... }. In the end I just print out the values with length of >1. So good so far.
Here's the deal: I want to modify the output, so that such cases are omitted: ["Wood", "wood", "WooD"] - all are different in case only. But such cases should stay: ["Doom", "DooM", "mood"].
My current piece of code:
def print_anagram(anagram_dict)
anagram_list = anagram_dict.values
anagram_list.each { |i|
if i.length > 1
print i.join("\t")
print "\n"
else
next
end
}
end
anagram_dict is a dictionary mentioned above.
What checks should I make to throw these cases away? The things I think of seem way to bulky to me. Thanks in advance!
def print_anagram(anagram_dict)
anagram_list = anagram_dict.values
anagram_list.each do |i|
next if i.map(&:downcase).uniq.length == 1
if i.length > 1
print i.join("\t")
print "\n"
else
next
end
end
end
What this does:
make all Strings lowercase
get only unique elements from the array
if you only have one unique element, all elements are the same
map(&:downcase) is a shorter way of doing: map { |element| element.downcase }
Does this do what you want?
def print_anagram(anagram_dict)
anagram_list = anagram_dict.values.uniq{|word| word.downcase}
# rest of your code
I want to count all the words in a line of text. I'm using a map to do this, with the words for keys and integers for values. I don't know how to tell Ruby that all the values will be integers. It forces me to put an ugly branching inside my iterator's block:
# in the constructor
#individual_words = {}
def count_words_from( text_line )
text_line.each do |line|
line.scan(/\p{Word}+/)
.reject{ |string| string =~ /\d/ }
.each do |word|
if #individual_words[ word ] == nil then # This is ugly
#individual_words[ word ] = 1 # This is ugly as well
else
#individual_words[ word ] += 1
end
end
end
end
In simple, I'd like to do something like this Java line:
Map<String, Integer> individualWords;
to avoid having to change the type of the first occurence of a word from Nil to Integer.
You can set a default value in your hash like this:
individual_words = Hash.new(0)
Then when you come across a word, whether its key is in the hash or not, all you have to do is:
individual_words[word] += 1
You can also do something like this
#individual_words[word] ||= 0
#individual_words[word] += 1
||= ensures that the value gets set if it's not truthy (ie. nil)