FAQ: Create a Histogram - You Did It!

This community-built FAQ covers the “You Did It!” exercise from the lesson “Create a Histogram”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Learn Ruby

FAQs on the exercise You Did It!

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

Question: how to increment values for each new word?

puts “Type your input here:”
text = gets.chomp
puts words = text.split

frequencies = Hash.new(0)
puts frequencies

puts: {}

puts frequencies[“test”]

puts: 0

words.each do |x|
word = x
frequencies[word]+=1
end

frequencies = frequencies.sort_by do |word, count|
count
end
frequencies.each do |word, count|
puts word + " " + count.to_s
end

We could forego the x

words.each do |word|
  frequencies[word] += 1
end

Note that the new Hash is set with default value of 0 for each new key added to the hash. The above increments each word count as the word is encountered. If it is not in the hash, then it is added to the hash, and incremented in one step.

Not sure this answers your question, though.

Why is this line (shown as solution)

words.each { |word| frequencies[word] += 1 }

Not equivalent to this one (shown as attempt without solution)

words.each do |word|
word += 1
puts “#{frequencies} #{word}”

Can someone explain the logic here and what I’ve done is creating a weird interaction? is there a way I can think about this challenge better?

As we iterate over the array of words broken out of the text with split() each one is added to the hash with a default value of 0, which is then incremented. The next time that same word is encountered it will not be added to the hash since it already exists, but it will have its value incremented.

words.each { |word| frequencies[word] += 1 }

frequencies is the hash object, word is either a key that already exists, or is a new key. In either case, we update the hash with that statement.

words.each do |word|
word += 1
puts "#{frequencies} #{word}"

Above is an attempt to add a number to a string value, which will not work. word is designated as a key in the hash, not a value.

words.each do |word|
  frequencies[word] += 1
end

is the equivalent of the earlier block form.

1 Like

Thanks so much mtf!

Summarizing Lesson: Hash is a Key; and is not treated as a string when used in the last example… thereby the Variable operator (+= ) is compatible to the array where as a string is not compatible with a Variable Operator…

Hope you don’t mind but I have a few more questions.

Q1: What data type is a keys? I only know of Numeric (any number), Boolean (which can be true or false) and String (words or phrases )…

Q2: Where can I find more information on these kinds of rules/interactions? I don’t have a traditional background in CS so is there a quick reference to learn up? Or maybe suggested google searches that will help?

Q3: I am very new to this and often times want to go through the tutorial; play around with ideas… but when I can’t debug the code my confidence goes down and I’m forced to give up in frustration… Should I just stick to the tutorials so I don’t confuse myself?? I don’t want to develop bad habits.

Actually, a hash is similar to a JS object or a Python dictionary consisting of key - value pairs.

{key => value}  => hash

Keys are always treated as string objects. They are immutable so we cannot attempt to change them. We only act upon the associated values.

Their values can be any defined data type, string, numeric, boolean, hash, and array. Would need to explore this further to see if we left any off this list.

Dig up the main Ruby docs, and look for wikis on the subject, Ruby forums, Ruby tutorials. &c.

We all learn in different ways. Some learners are more intuitive than others given they may already possess some of the skills that can be translated to programming. If one is totally green then confidence is always going to be a factor but we should never let it become our albatross. Stick with the tutorial and complete a module, then go back and review. Don’t interrupt your progress by taking too many detours.

Once you get over a few hurdles and have more rote knowledge under you hat your confidence will slowly grow. There is no hurry. This is not a race. Just don’t give up, whatever you do.

1 Like

Thanks, much appreciated!

1 Like

Hi, my code looks like this

puts “please eneter text”
text = gets.chomp
words = text.split

frequencies = Hash.new(0)
puts frequencies
words.each {|word|frequencies[word] +=1 }
frequencies = frequencies.sort_by do |word, count|
count
end
frequencies.reverse
frequencies.each do |word, frequency|
puts word + " " + frequency.to_s
end

The program runs correctly, however why do I get two {} before it counts how many words I’ve got?

please eneter text
help why do I have these
{}
help 1
why 1
do 1
I 1
have 1
these 1

Or are they supposed to be there?

Thank you :slight_smile:

frequencies at this point is an empty hash, hence it prints {}. Remove that puts statement and see what happens.

1 Like

Aaah ok, thank you :smiley:

1 Like

This is my code:

puts "Enter a phrase you’d like to analyze: "
text = gets.chomp
words = text.split
frequencies = Hash.new(0)
words.each { |word| frequencies[word] += 1 }
frequencies = frequencies.sort_by do |thing, count|
count
end
frequencies.reverse!

frequencies.each do |thing, count|
puts “#{thing} #{count}”
end

I’m confused, in the last part, are thing and count considered variables? Also, in
words.each { |word| frequencies[word] += 1 },
is words a new hash or an array automatically?

Yes, exactly. In Ruby they are called, block parameters, just as they would be parameters in a JavaScript or Python function.

words is an array and that does not change. The only new hash at this point would be a newly discovered word for which there is no key. That key will be given an initial value of 0, and then incremented to 1 to account for its unit value in the count.

1 Like

Thank you! In summary, with this line
frequencies.each do |thing, count|
I’m creating variables for the key and values of the hash called frequencies. Also, the words array gets the split string of user input and turns that into an array.
Is that right?

Yes, that is correct. String.split() returns an array.

Thanks for the help!

1 Like

It’s supposed that we can iterate over an array with colors.each { |color| puts color } and over a hash with polygons.each do |shape, sides|.
In the last .each of the program we iterate like if we have a hash, but it supposed that .sort_by returns an array.
I can use help to understand that part.
Thanks.

By histogram I thought we were going to do a graph.
So went back to the loops and iterations section and added the line

count.times { print "#"}

Which did draw me a little graph.

1 Like

Hi coders!
I have quite a few questions if I may.

  1. I’m little confused on the following code.
    When I use:
    frequencies.sort_by {|word, count|count}
    the,
    frequencies.reverse!
    flags up with
    undefined method `reverse!’ for {“la”=>2, “land”=>1}:Hash
    Did you mean? reverse_each
    in the console…
    but when I swap it with:
    frequencies = frequencies.sort_by do |word, count|
    count

    end
    it’s happy to take frequencies.reverse! and reverses without a fuss.
    How does this happen?

my full code for the error to happen was this:

puts "write me a Lyric: "
text = gets.chomp
words = text.split

frequencies = Hash.new(0)
words.each { |word| frequencies[word] += 1}

frequencies.sort_by {|word, count| count}

frequencies.reverse!

frequencies.each {|word, count| puts word + " " + count.to_s}

  1. I have read a lot about words.each { |word| frequencies[word] += 1} in the entire FAQ posts on Histogram, and… I’m afraid I’m still confused.
    I’m just coming up to 40% of my Ruby course so I am aware there are more things I have yet to learn. But could someone please explain to me:
  • frequencies[word] += 1 this part simpler?
    frequencies = Hash.new(0) - here, ‘hash’ has been made with a default of ‘0’.
    but I am confused on how did the ‘hash’ end up in the .each method?
  • What does that Hash do in .each method. And then the correlation to [word]?
    so…
    ‘[word]’ = user’s inputs (individually separated by .split). It is now an element of ‘key’ for hash as its cushioned with [ ].
    ‘1’ = is the ‘value’ of the hash (which gets used to print as ‘count’)
    Hash = is there so you can access [word] as a ‘key’?
  • And this is probably silly but, am I right to think frequencies basically means 0? if so, what is the thought process behind using frequency hash and not 0?

or am I looking at this all wrong?
I feel so confused that I’m not sure if my questions make sense to anyone. but I’d appreciate anyone’s time helping! :innocent:

I’ve figured it out!
The wording in this course is little complicating.
But I drew it out on a note pad and it makes sense!

this basically set a rule for the ‘frequencies’ hash.

puts "write me a Lyric: " #la la land
text = gets.chomp
words = text.split
#la, la, land
frequencies = Hash.new(0)
#frequencies{empty=> empty, empty => empty,empty => empty}
words.each { |word| frequencies[word] += 1}
# .each makes a new rule for 'frequencies' Hash...
#{frequencies[words] => += 1, freqencies[word] => += 1, frequencies[word] += 1}

# so with user's input, it becomes...
#{frequencies[la] => += 1, freqencies[la] => += 1, frequencies[land] => += 1}
frequencies.sort_by {|word, count|count}
# this counts them up, so it becomes...
#{reqencies[la] => 2, frequencies[land] => 1}

#frequencies.reverse! (this code doesn't work on this block of coding to use, for some reason, and I have not yet figured out why.)

frequencies.each {|word, count| puts word + " " + count.to_s}
=begin
|word, count| ----- means 
word = frequencies[ ]-------- la, land
count = number counted ------ 2, 1
so 
'{|word, count| puts word + " " + count.to_s}'------ means to 
'puts'
la(space)2
land(space)1
to string

and out come is:
la 2
land 1
=end

Though I have not yet figured why:

frequencies.reverse!

does not work when you use:
frequencies.sort_by {|word, count| count }

But works fine with:
frequencies = frequencies.sort do |word, count|
count
end