Formatting issue with Ruby and puts - ruby

When we were younger, my friend and I had our own secret language. Recently he challenged me to make a translator so that I could input a word and it would convert it to the right word. It's silly, but it was just for fun.
The problem I have is that the converted word output is on separate lines.
What it should do:
Word to translate: Banana
Translated word: ananabang
What it does:
Word to translate: Banana
Translated word:
anana
bang
This is the code I've written.
puts "Enter word to translate \n \n"
input = gets
firstCharacter = input[0].chr
ang = "ang"
if firstCharacter =~ /\A(a|b|c|d|A|B|C|D)\Z/
input.slice!(0)
puts firstCharacter + input + "ang"
end
I wonder if anyone can help me with the outputting issue..?
Thanks
EDIT: Fixed it with gets.chomp.

gets returns the entered string with a newline at the end. If you change your second line to input = gets.chomp, it will work as expected because chomp removes the trailing newline.

You can also refactor your code into something more concise and clear:
print "Enter word to translate: "
word = gets.chomp.downcase
puts word.sub(/^(.)/, '') << "#{$1}ang"
Or slightly more verbosely:
print "Enter word to translate: "
word = gets.chomp.downcase
translation = word[1,1000] << word[0,1]
translation << 'ang'
puts translation
There are a lot of ways to do anything in Ruby, and it often pays to step back and consider whether you're overengineering when you could be creating something simpler and more maintainable.

Related

Codecademy Ruby course: Control Flow know-how

When coding in Ruby, I came up with an error about needing to state all words the user inputed. I tried to change my code to get it to output that, but the problem remained. Here is my code and the Ruby instructions.
Instructions
Add an if/else statement inside your .each.
if the current word equals the word to be redacted, then print "REDACTED " with that extra space.
Otherwise (else), print word + " ".
The extra space in both cases prevents the words from running together.
puts text = gets.chomp
puts redact = gets.chomp
words = text.split(" ")
words = ['hi', 'hello', 'what', 'why']
words.each do |word|
if gets = words
print "Redact "
else
print word + "Incorrect"
end
end
The problem it says I have with my code is... Oops, try again. Make sure to print each word from the user's text to the console unless that word is the word to be redacted; if it is, print REDACTED (all caps!).
I would appreciate all help, please and thank you.
Ben sorry these guys aren't being too helpful. :D It's been awhile but I hope this helps. In the first section titled "What you'll be building" Codecademy gives you the exact example (the answer) to the final problem in the section. This is always true and may help in the future. What you're looking for:
puts "Text to search through: "
text = gets.chomp
puts "Word to redact: "
redact = gets.chomp
words = text.split(" ")
words.each do |word|
if word != redact
print word + " "
else
print "REDACTED "
end
end
Have pass several years I know, but I wanted pass and let my solution for this excercise.
puts "Text to search through: "
text = gets.chomp
puts "Word to redact: "
redact = gets.chomp
words = text.split(',') # "," is necessary to identify each of the words
words.each do |x|
if x == redact # if words repeat, print REDACTED
print "REDACTED"
else # else, only write de word and space
print x + " "
end
end

Ruby bang strange behaviour

I wrote the following code:
print "Please enter a string"
user_input = gets.chomp
user_input.downcase!
if user_input.include? "s"
print "Changing #{user_input} to #{user_input.gsub!(/s/,'th')}"
else
print "No s in the string"
end
and I found that user_input and user_input.gsub!(/s/,'th') contain the same value. This happens because of the bang operation on gsub and because they are part of the same string.
Splitting the print in two lines changes the behavior:
print "Changing #{user_input} to "
print "#{user_input.gsub!(/s/,'th')}"
I wonder if this is a bug.
It's a feature, not a bug.
String interpolation (the "#{}" operator) works by finding all the dynamic parts, evaluating them and then glueing static and dynamic parts together into one string. Since all dynamic parts are evaluated prior to concatenation, gsub! mutates the object which user_input points to. So the first appearance of inner_page in that string will see the updated value.
Solution: don't use dangerous gsub!, use safe gsub.
You can observe here, how it really happens (VM instructions). This will probably be Chinese to you at the moment, but in a few years you'll understand. :)
code = <<-RUBY
user_input = 'blah'
print "Changing \#{user_input} to \#{user_input.gsub!(/s/,'th')}"
RUBY
puts RubyVM::InstructionSequence.new(code).disasm

Error in .each execution (Ruby)

I'm making an auditor with ruby which started off fine this morning (using single word, user inputted content to omit) but now that I've tried to implement a wordlist, it puts the string to search through as many times as there are words in the wordlist, only censoring it once or twice. My code is as follows.
#by Nightc||ed, ©2015
puts "Enter string: "
text = gets.chomp
redact = File.read("wordlist.txt").split(" ")
words = text.split(" ")
redact.each do |beep|
words.each do |word|
if word != beep
print word + " "
else
print "[snip] "
end
end
end
sleep
I kind of understand why it doesn't work but I'm not sure how to fix it.
Any help would be appreciated.
There's an easier way than iterating through each array. The Array#include method can be easily used to see if the word is contained in your redacted list.
Here's some code that should behave how you wanted the original code to behave:
puts "Enter string: "
text = gets.chomp
redact = File.read("wordlist.txt").split(" ")
words = text.split(" ")
words.each do |word|
if redact.include? word
print "[snip] "
else
print word + " "
end
end
Scrubbing text gets very tricky. One thing you want to watch out for is word boundaries. Splitting on spaces will let a lot of beep words get through because of puctuation. Compare the first two results of the sample code below.
Next, assembling the split text back into its intended form with punction, spacing, etc., gets to be quite challenging. You may want to consider using regex for something presuambly as small as user comments. See the third result.
If you're doing this as a learning exercise, great, but if the application is sensitive where you're likely to take heat over failures to bleep words, you may want to look for an existing well-tested library.
#!/usr/bin/env ruby
# Bleeper
scifi_curses = ['friggin', 'gorram', 'fracking', 'dork']
text = "Why splitting spaces won't catch all the friggin bleeps ya gorram, fracking dork."
words = text.split(" ")
words.each do |this_word|
puts "bleep #{this_word}" if scifi_curses.include?(this_word)
end
puts
better_words = text.split(/\b/)
better_words.each do |this_word|
puts "bleep #{this_word}" if scifi_curses.include?(this_word)
end
puts
bleeped_text = text # keep copy of original if needed
scifi_curses.each do |this_curse|
bleeped_text.gsub!(this_curse, '[bleep]')
end
puts bleeped_text
You should get these results:
bleep friggin
bleep fracking
bleep friggin
bleep gorram
bleep fracking
bleep dork
Why splitting spaces won't catch all the [bleep] bleeps ya [bleep], [bleep] [bleep].

gets.chomp without moving to a new line

I understand about the \n that's automatically at the end of puts and gets, and how to deal with those, but is there a way to keep the display point (the 'cursor position', if you will) from moving to a new line after hitting enter for input with gets ?
e.g.
print 'Hello, my name is '
a = gets.chomp
print ', what's your name?'
would end up looking like
Hello, my name is Jeremiah, what's your name?
You can do this by using the (very poorly documented) getch:
require 'io/console'
require 'io/wait'
loop do
chars = STDIN.getch
chars << STDIN.getch while STDIN.ready? # Process multi-char paste
break if ["\r", "\n", "\r\n"].include?(chars)
STDOUT.print chars
end
References:
http://ruby-doc.org/stdlib-2.1.0/libdoc/io/console/rdoc/IO.html#method-i-getch
http://ruby-doc.org/stdlib-2.1.0/libdoc/io/wait/rdoc/IO.html#method-i-ready-3F
Related follow-up question:
enter & IOError: byte oriented read for character buffered IO
Perhaps I'm missing something, but 'gets.chomp' works just fine does it not? To do what you want, you have to escape the apostrophe or use double-quotes, and you need to include what the user enters in the string that gets printed:
print 'Hello, my name is '
a = gets.chomp
print "#{a}, what's your name?"
# => Hello, my name is Jeremiah, what's your name?
Works for me. (Edit: Works in TextMate, not Terminal)
Otherwise, you could just do something like this, but I realise it's not quite what you were asking for:
puts "Enter name"
a = gets.chomp
puts "Hello, my name is #{a}, what's your name?"

Format output to 40 characters long per line

I'm fairly new to Ruby and I've been searching Google for a few hours now.
Does anyone know how to format the output of a print to be no more than 40 characters long?
For example:
What I want to print:
This is a simple sentence.
This simple
sentence appears
on four lines.
But I want it formatted as:
This is a simple sentence. This simple
sentence appears on four lines.
I have each line of the original put into an array.
so x = ["This is a simple sentence.", "This simple", "sentence appears", "on three lines."]
I tried x.each { |n| print n[0..40], " " } but it didn't seem to do anything.
Any help would be fantastic!
The method word_wrap expects a Strind and makes a kind of pretty print.
Your array is converted to a string with join("\n")
The code:
def word_wrap(text, line_width = 40 )
return text if line_width <= 0
text.gsub(/\n/, ' ').gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
end
x = ["This is a simple sentence.", "This simple", "sentence appears", "on three lines."]
puts word_wrap(x.join("\n"))
x << 'a' * 50 #To show what happens with long words
x << 'end'
puts word_wrap(x.join("\n"))
Code explanation:
x.join("\n")) build a string, then build one long line with text.gsub(/\n/, ' ').
In this special case this two steps could be merged: x.join(" "))
And now the magic happens with
gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n")
(.{1,#{line_width}})): Take any character up to line_width characters.
(\s+|$): The next character must be a space or line end (in other words: the previous match may be shorter the line_width if the last character is no space.
"\\1\n": Take the up to 40 character long string and finish it with a newline.
gsub repeat the wrapping until it is finished.
And in the end, I delete leading and trailing spaces with strip
I added also a long word (50 a's). What happens? The gsub does not match, the word keeps as it is.
puts x.join(" ").scan(/(.{1,40})(?:\s|$)/m)
This is a simple sentence. This simple
sentence appears on three lines.
Ruby 1.9 (and not overly efficient):
>> x.join(" ").each_char.each_slice(40).to_a.map(&:join)
=> ["This is a simple sentence. This simple s", "entence appears on three lines."]
The reason your solution doesn't work is that all the individual strings are shorter than 40 characters, so n[0..40] always is the entire string.

Resources