Adding white-space to the output of a variable - Ruby - ruby

I've justed started learning to code in Ruby and have hit a snag in my first script. The idea is to translate the English alphabet into morse code.
I have set up a hash for my letters and their corresponding values:
morse_code = {
'a' => '.-',
'b' => '-...',
etc etc
I use the following to iterate through the hash and pull the corresponding values based on input then output it:
print "What would you like to translate: "
code = gets.strip.downcase
morse_code.each do |morse, alpha|
code.gsub!( morse, alpha )
end
puts code
The problem is that my output does not contain spacing so looks like this:
......-...-..----
instead of what I want:
.... . .-.. .-.. --- -
All I've found thus far are relating to adding a whitespace when calling variables inside a string. Below is an example:
Putting space between the output of defined variables in Ruby
Any help on how I can achieve this with my current code or rewrite it accordingly would be appreciated.

What you need is to take the input and map its characters to corresponding values from the morse_code hash, and then join it with spaces:
code = 'abb'
code.each_char.map { |letter| morse_code[letter] }.join(' ')
#=> ".- -... -..."
Reference:
String#each_char
Enumerable#map
Array#join
EDIT:
To make your initial code to work the only thing you lacked is a space, which is easy to add using interpolation:
code = 'abab'
morse_code.each do |morse, alpha|
code.gsub!(morse, "#{alpha} ") # <=============
end
code
#=> ".- -... .- -... "
code.rstrip
#=> ".- -... .- -..."
If you did not know about interpolation - here is how it works:
foo = 'bar'
"#{foo}" #=> "bar"
"hello I am #{foo}" #=> "hello I am bar"
So going back to your case, all the following does
"#{alpha} "
is adding a space after, which you needed. Problem with it, that the resulting string will have an extra space at the end, which we solved with
code.rstrip

Related

How to reverse a string using each method?

So here is the string I want to convert to an array, where then I want to reverse each word without reversing the entire sentence, and then join them back and provide the output.
For instance, I want to change "Hello there, and how are you?" to "olleH ,ereht dna woh era ?uoy"
This is the string:
sentence1="Hello there, and how are you?"
and, this is my code in which I have to incorporate .each(which i know is wrong, but don't know how)
def reverse_each_word(sentence1)
split_array = sentence1.split
reversed_array = split_array.reverse
reversed_array.each do |joined_array|
joined_array.join(' ')
end
end
and as mentioned, the desired result has to be:
"olleH ,ereht dna woh era ?uoy"
You're calling join in a string, since you're iterating over each element in reversed_array, and all those ones are string objects:
p sentence1.split.first.join(' ')
# undefined method `join' for "Hello":String (NoMethodError)
It might work if you use something to store the value in each iteration within the block, it can be a variable declared outside the iteration, or better map, after that, you can just reverse each string and then join everything:
def reverse_each_word(sentence1)
sentence1.split.map do |joined_array|
joined_array.reverse
end.join(' ')
end
p reverse_each_word(sentence1) # "olleH ,ereht dna woh era ?uoy"
Notice this can be written as sentence1.split.map(&:reverse).join(' ') too.
In case you're looking for each to solve this problem, you'll need a variable where to store each "modified" string as long as you're iterating over each of those elements:
memo = ''
sentence1.split.each { |joined_array| memo << "#{joined_array.reverse} " }
p memo.rstrip # "olleH ,ereht dna woh era ?uoy"
There you have a memo variable which is an empty string, just for the reason to be filled with each reversed string, you reverse the string and add a white space to the right. The last string is going to have an additional whitespace, so rstrip helps you to "remove" it.
For collect you can use the map approach, because they're aliases.
I would be inclined to use String#gsub with a regular expression.
str = "Hello there, and how are you?"
str.gsub(/\S+/) { |s| s.reverse }
#=> "olleH ,ereht dna woh era ?uoy"
The regular expression reads, "match one or more characters other than whitespace characters".

How to replace a specific character in a string along with the immediate next character

I have a string of text:
string = "%hello %world ho%w is i%t goin%g"
I want to return the following:
"Hello World hoW is iT goinG
The % sign is a key that tells me the next character should be capitalized. The closest I have gotten so far is:
#thing = "%this is a %test this is %only a %test"
if #thing.include?('%')
indicator_position = #thing.index("%")
lowercase_letter_position = indicator_position + 1
lowercase_letter = #thing[lowercase_letter_position]
#thing.gsub!("%#{lowercase_letter}","#{lowercase_letter.upcase}")
end
This returns:
"This is a Test this is %only a Test"
It looks like I need to iterate through the string to make it work as it is only replacing the lowercase 't' but I can't get it to work.
You can do this with gsub and a block:
string.gsub(/%(.)/) do |m|
m[1].upcase
end
Using a block allows you to run arbitrary code on each match.
Inferior to #tadman, but you could write:
string.gsub(/%./, &:upcase).delete('%')
#=> "Hello World hoW is iT goinG

Print Unicode escape codes from variable

I have a list of Unicode character codes that I would like to output with rumoji. Here's the code I'm using to iterate over my data.
require "rumoji"
# this works
puts Rumoji.decode("\u{1F600}")
# feed some data
data = [
"1F600",
"1F476",
"1F474"
]
data.each do |line|
# this doesn't work
puts Rumoji.decode("\u{#{line}}")
puts Rumoji.decode("\u{" + line + "}")
end
I'm not sure how I can use variable names inside the escaped string.
One can not use \u along with string interpolation, since \u takes precedence. What one might do, is to Array#pack an array of integers:
β–Ά data.map { |e| e.to_i(16) }.pack 'U*'
#β‡’ "πŸ˜€πŸ‘ΆπŸ‘΄"

What's different about this ruby regex?

I was trying to substitute either a comma or a percent sign, and it continually failed, so I opened up IRB and tried some things out. Can anyone explain to me why the first regex (IRB line 13) doesn't work but the flipped version does (IRB line 15)? I've looked it up and down and I don't see any typos, so it must be something to do with the rule but I can't see what.
b.gsub(/[%]*|[,]*/,"")
# => "245,324"
b.gsub(/[,]*/,"")
# => "245324"
b.gsub(/[,]*|[%]*/,"")
# => "245324"
b
# => "245,324"
Because ruby happily finds [%]* zero times throughout your string and does the substitution. Check out this result:
b = '232,000'
puts b.gsub(/[%]*/,"-")
--output:--
-2-3-2-,-0-0-0-
If you put all the characters that you want to erase into the same character class, then you will get the result you want:
b = "%245,324,000%"
puts b.gsub(/[%,]*/, '')
--output:--
245324000
Even then, there are a lot of needless substitutions going on:
b = "%245,324,000%"
puts b.gsub(/[%,]*/, '-')
--output:--
--2-4-5--3-2-4--0-0-0--
It's the zero or more that gets you into trouble because ruby can find lots of places where there are 0 percent signs or 0 commas. You actually don't want to do substitutions where ruby finds zero of your characters, instead you want to do substitutions where at least one of your characters occurs:
b = '%232,000,000%'
puts b.gsub(/%+|,+/,"")
--output:--
232000000
Or, equivalently:
puts b.gsub(/[%,]+/, '')
Also, note that regexes are like double quoted strings, so you can interpolate into them--it's as if the delimiters // are double quotes:
one_or_more_percents = '%+'
one_or_more_commas = ',+'
b = '%232,000,000%'
puts b.gsub(/#{one_or_more_percents}|#{one_or_more_commas}/,"")
--output:--
232000000
But when your regexes consist of single characters, just use a character class: [%,]+

How to find out if a key exists in a hash, then use that information ruby

I have read the lines of a text file into a hash of chars. Now I need to make it so only the alphabetical chars appear, not the special chars and punctuation. I have tried this:
File.open(WORKING_DIR + '/code.txt','r') do |f|
char_count = Hash.new(0) # create a hash where 0 is the default value
f.each_char do |c| # iterate on each character
char_count.has_key?(c)
char_count[c] +=1
end
end
puts char_count.inspect
But when I inspect my hash, all punctuation is still present. How am I using has_key incorrectly?
You definitely seem to be missing some things here. Since you've tagged this as homework, I'm not going to give you an outright solution, but here's some things to look into:
First, each_char iterates through every single character -- not just alphanumerics:
irb(main):001:0> "xyz.abc".each_char { |c| print c, ' ' }
x y z . a b c => "xyz.abc"
So, you will need some sort of test for that.
Second, inside your iterator, you're not actually applying your has_key? test -- you will need to use some logic here to decide when to increment your hash.

Resources