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].
Related
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
I am writing a matching algorithm that checks a user-entered word against a huge list of english words to see how many matches it can find. Everything works, except I have two lines of code that are essentially meant to not pick the same letters twice, and they make the whole thing just return a single letter. Here is what I've done:
word_array = []
File.open("wordsEn.txt").each do |line|
word_array << line.chomp
end
puts "Please enter a string of characters with no spaces:"
user_string = gets.chomp.downcase
user_string_array = user_string.split("")
matching_words = []
word_array.each do |word|
one_array = word.split("")
tmp_user_string_array = user_string_array
letter_counter = 0
for i in 0...word.length
if tmp_user_string_array.include? one_array[i]
letter_counter += 1
string_index = tmp_user_string_array.index(one_array[i])
tmp_user_string_array.slice!(string_index)
end
end
if letter_counter == word.length
matching_words << word
end
end
puts matching_words
This part here is what breaks it:
string_index = tmp_user_string_array.index(one_array[i])
tmp_user_string_array.slice!(string_index)
Can anyone see an issue here? It all makes sense to me.
I see what's happening. You're eliminating letters for non-matching words, which prevents matching words from being found.
For example, take this word list:
ant
bear
cat
dog
emu
And this input to your program:
catdog
The first word you look for is ant, which causes the a and t to be sliced out of catdog, leaving cdog. Now the word cat can no longer be found.
The cure is to make sure that your tmp_user_string_array really is a temporary array. Currently it's a reference to the original user_string_array, which means that you're destructively modifying the user input. You should make a copy of it before you start slicing and dicing.
Once you've got that working, you might like to think about more efficient approaches that don't require duplicating and slicing arrays. Consider this: what if you were to sort each word of your lexicon as well as the input string before starting to look for a match? This would turn the word cat into act and the input acatdog into aacdgot. Do you see how you could traverse the sorted word and the sorted input in search of a match without the need to do any slicing?
I am writing a small bit of code in Ruby that is supposed to redact a word that is specified by the user, regardless if the word that is being passed is all uppercase, lowercase or a combination of the two. The way that I tried to get around this was by just using the downcase! method on the strings being passed by the user. However, it would seem that it does not work correctly. For example, if the first string that is passed and stored in the variable "text" is in all uppercase and the second string that is passed and stored in the variable "redact" is all downcase, the program will fail to redact the word and will just print out everything in downcase.
Here is the code below:
puts "Enter what you want to search through"
text = gets.chomp.downcase!
puts "Enter word to be redacted"
redact = gets.chomp.downcase!
words = text.split(" ")
words.each do |word|
if word == redact
print "REDACTED "
else
print word + " "
end
end
The problem is that you use downcase! which will return nil if no change is made. The string itself is modified but the returned value is nil, which you save after in your text variable.
See the documentation about downcase and downcase! to understand the difference.
puts "Enter what you want to search through"
text = gets.chomp.downcase
puts "Enter word to be redacted"
redact = gets.chomp.downcase
words = text.split(" ")
words.each do |word|
if word == redact
print "REDACTED "
else
print word + " "
end
end
try it without the exclamation marks.
Okay,
I am doing the codeacademy ruby track and I am not stock with the problem.
I can make it works now, but I don't understand why it works.
instructions for exercise:
Let's start simple: write an .each loop that goes through words and just prints out each word it finds.
I have broken the problem into steps to try to understand why it works
but I am very confused.
My code for the problem is:
puts "Text to search through: " #ask user for input
text = gets.chomp
#store the user's input into the variable text
puts "Text to be reducted: "
#ask the user for input
redact = gets.chomp
#store the user's input into the variable redact
words = text.split(" ")
=begin
split the user's input into the variable words
store that input into the variable words
=end
words.each do |word|
=begin
creates a placeholder for the user's input
then attach an expression to the input stored in
the variable words one at a time. The variable
words holds the value of the variable text
=end
if word != redact
=begin
if word (which now holds the value of words that's
stored in the variable text, and which is the user's input)
is not equal to the value of the variable redact do something
=end
word = word + " "
=begin
increment the value of word by an empty space
why do I need to increment the value of word by an empty space?
=end
print "#{word}" #print the value of the variable word
else
print "REDACTED" #otherwise, print the value redacted
end
end
The program works if I use a string separated by an space and only if I change
word = word + ""
instead of
word = word + " "
I would truly appreciate if someone break it down for me, step by step.
I created a video of it for a more visual explanation of it.
here is the link: ruby redaction video
thank you.
The problem in your video is that "nelson" is not the same as "nelson ", and the Codeacademy scoring doesn't see a match when you append a space to the word before printing it.
I am reading this problem in July 2019..
So anybody who is reading this problem and getting confused with the below part asked by the user:
word = word + " "
=begin
increment the value of word by an empty space
why do I need to increment the value of word by an empty space?
So the answer is that the + sign is not for incrementing the value it's for adding a space and the + sign is used as string concatenator. So it has been placed there so that whatever words are being searched and displayed, they have a space between them.
Getting stuck on chapter 8:
Type as many words as we want
One word per line, continuing until we just press Enter on an empty line
Repeats the words back to us in alphabetical order.
Use 'sort'
So, here's what I got to, but I'm having funny issues with not getting the first word to push into the array [among other things]
# alphabetting
puts 'Tell us some of your favorite things!'
# create an array
words = []
while gets.chomp != ''
words.push gets.chomp
words.sort
puts words
end
Did this and it works now... Do I have to have "thing" in there though? Seems naughty to assign within a 'while' loop.
puts 'Tell us some of your favorite things!'
words = []
puts words
while (thing = gets.chomp) != ''
words.push thing
end
puts words.sort
Your first gets call is not referred to by anything, and is thrown out. It is not just the first word, but every other word that is going to be thrown out. The output routine should also be outside of the loop. A fix is:
words = []
while word = gets.chomp and not word.empty?
words.push(word)
end
puts words.sort
Try this:
puts 'Tell us some of your favorite things!'
words = []
while line = STDIN.gets
line = line.chomp
break if line.empty?
words << line.chomp
end
words = words.sort
words.each {|word| puts word }