Chop last character of string - ruby

I want to make program which takes the string and chop last character each time and print result to console:
With an input string of Hello, the result should be:
Hello
Hell
Hel
He
H
This is my code so far:
def test_string
puts "Put your string in: "
string = gets.chomp
while string.length == 0
puts string.chop(/.$/)
end
end
puts test_string

Use chop!:
string = gets.chomp
# Print full string, e.g. "Hello"
puts string
# Print remaining... e.g. "Hell", "Hel", etc.
while string.length != 0
puts string.chop!
end

Following code does not modify the original string
string = gets.chomp
l = string.length
l.times do |i|
puts string[0..(l-i-1)]
end

You can also create an array filling it with the string N times, and for each time, get a character less from it:
str = 'Hello'
Array.new(str.size) { |index| str[0...str.size - index] }.each { |str| p str }
# "Hello"
# "Hell"
# "Hel"
# "He"
# "H

Related

How can I capitalize a letter from a word one at a time, then add each instance of the word with a caps letter into a array?

My code:
def wave(str)
ary = []
increase_num = 0
str = str.chars
until increase_num > str.size
ary << str[increase_num].upcase && increase_num += 1
end
end
What it's supposed to do:
wave("hello") => ["Hello", "hEllo", "heLlo", "helLo", "hellO"]
I would really appreciate some help, as you probably know by looking at it I'm relatively new.
str = "hello"
str.size.times.map { |i| str[0,i] << str[i].upcase << str[i+1..] }
#=> ["Hello", "hEllo", "heLlo", "helLo", "hellO"]
I would go about it as follows:
def wave(str)
str = str.downcase # so we can ensure a wave even if the original string had capitalization
str.each_char.with_index.map do |c,idx|
str[0...idx].concat(c.upcase,str[idx.+(1)..-1])
end
end
wave("hello")
#=> ["Hello", "hEllo", "heLlo", "helLo", "hellO"]
str.each_char.with_index.map do |c,idx| - This converts the String into an Enumerator and yields each character and its index to the map block.
str[0...idx] - In the block we slice the string into characters 0 through index (exclusive)
.concat(c.upcase,str[idx.+(1)..-1]) - Then we concatenate that with the current character upcased and the remaining portion of the String (index + 1 through the end of the String)
First 2 passes will look like:
# idx = 0
# c = "h"
# str[0...idx].concat(c.upcase,str[idx.+(1)..-1])
"".concat("H","ello")
# idx = 1
# c = "e"
# str[0...idx].concat(c.upcase,str[idx.+(1)..-1])
"h".concat("E","llo")

String compressor (Ruby)

Here is my code in ruby for a word compression.
For any given word (e.g. abbbcca) the compressed word/output should be in the format as "letter+repetition" (for above example, output: a1b3c2a1).
Here I'm so close to the completion but my result isn't in the expected format. It's counting the whole letters in string.chars.each thus resulting output as a2b3c2a2.
Any help?
def string_compressor(string)
new_string = []
puts string.squeeze
string.squeeze.chars.each { |s|
count = 0
string.chars.each { |w|
if [s] == [w]
count += 1
end
}
new_string << "#{s}#{count}"
puts "#{new_string}"
}
if new_string.length > string.length
return string
elsif new_string.length < string.length
return new_string
else "Equal"
end
end
string_compressor("abbbcca")
'abbbcca'.chars.chunk{|c| c}.map{|c, a| [c, a.size]}.flatten.join
Adapted from a similar question.
Similar:
'abbbcca'.chars.chunk{|c| c}.map{|c, a| "#{c}#{a.size}"}.join
See chunk documentation
You can use a regular expression for that.
'abbbcca'.gsub(/(.)\1*/) { |m| "%s%d" % [m[0], m.size] }
#=> "a1b3c2a1"
The regular expression reads, "match any character, capturing it in group 1. Then match the contents of capture group 1 zero or more times".
As you said, your code counts every letter in the string, not just the one grouped next to one another.
Here's a modified version :
def display_count(count)
if count == 1
""
else
count.to_s
end
end
def string_compressor(string)
new_string = ''
last_char = nil
count = 0
string.chars.each do |char|
if char == last_char
count += 1
else
new_string << "#{last_char}#{display_count(count)}" if last_char
last_char = char
count = 1
end
end
new_string << "#{last_char}#{display_count(count)}" if last_char
new_string
end
p string_compressor('abbbcca') #=> "ab3c2a"
p string_compressor('aaaabbb') #=> "a4b3"
p string_compressor('aabb') #=> "a2b2"
p string_compressor('abc') #=> "abc"
Note that with display_count removing 1s from the string, new_string can never be longer than string. It also probably isn't a good idea to return Equal as a supposedly compressed string.
To decompress the string :
def string_decompressor(string)
string.gsub(/([a-z])(\d+)/i){$1*$2.to_i}
end
p string_decompressor("a5b11") #=> "aaaaabbbbbbbbbbb"
p string_decompressor("ab3c2a") #=> "abbbcca"

Replacing a char in Ruby with another character

I'm trying to replace all spaces in a string with '%20', but it's not producing the result I want.
I'm splitting the string, then going through each character. If the character is " " I want to replace it with '%20', but for some reason it is not being replaced. What am I doing wrong?
def twenty(string)
letters = string.split("")
letters.each do |char|
if char == " "
char = '%20'
end
end
letters.join
end
p twenty("Hello world is so played out")
Use URI.escape(...) for proper URI encoding:
require 'uri'
URI.escape('a b c') # => "a%20b%20c"
Or, if you want to roll your own as a fun learning exercise, here's my solution:
def uri_escape(str, encode=/\W/)
str.gsub(encode) { |c| '%' + c.ord.to_s(16) }
end
uri_escape('a b!c') # => "a%20%20b%21c"
Finally, to answer your specific question, your snippet doesn't behave as expected because the each iterator does not mutate the target; try using map with assignment (or map!) instead:
def twenty(string)
letters = string.split('')
letters.map! { |c| (c == ' ') ? '%20' : c }
letters.join
end
twenty('a b c') # => "a%20b%20c"
If you want to first split the string on spaces, you could do this:
def twenty(string)
string.split(' ').join('%20')
end
p twenty("Hello world is so played out")
#=> "Hello%20world%20is%20so%20played%20out"
Note that this is not the same as
def twenty_with_gsub(string)
string.gsub(' ', '%20')
end
for if
string = 'hi there'
then
twenty(string)
#=> "hi%20there"
twenty_with_gsub(string)
#=> "hi%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20there"

How to replace text in a ruby string

I am trying to write a very simple method in Ruby which takes a string and an array of words and checks if the string contains any of the words and if it does it replaces them with their uppercase.
I made an attempt but its not great due to my level of Ruby skills.
def(my_words,my_sentence)
#split the sentence up into an array of words
my_sentence_words = my_sentence.split(/\W+/)
#nested loop that checks the words array for each brand
my_sentence_words.each do |i|
my_words.each do |i|
#if it finds a brand in the words and sets them to be uppercase
if my_words[i] == my_sentence_words[i]
my_sentence_words[i] == my_sentence_words[i].up.case
end
end
end
#put the words array into one string
words.each do |i|
new_sentence = ("" + my_sentence_words[i]) + " "
end
end
I am getting: can't convert string into integer error
def convert(mywords,sentence)
regex = /#{mywords.join("|")}/i
sentence.gsub(regex) { |m| m.upcase }
end
convert(%W{ john james jane }, "I like jane but prefer john")
#=> "I like JANE but prefer JOHN"
This will work better. It loops through the brands, searches for each, and replaces with the uppercase version.
brands = %w(sony toshiba)
sentence = "This is a sony. This is a toshiba."
brands.each do |brand|
sentence.gsub!(/#{brand}/i, brand.upcase)
end
Results in the string.
"This is a SONY. This is a TOSHIBA."
For those who like Ruby foo!
sentence.gsub!(/#{brands.join('|')}/i) { |b| b.upcase }
And in a function
def capitalize_brands(brands, sentence)
sentence.gsub(/#{brands.join('|')}/i) { |b| b.upcase }
end
You get this error because i doesn't start from 0 as you expected, in each method i is an element of array, and has string type, it's a first word from your sentence:
my_sentence_words = ["word"]
my_sentence_words.each do |i|
puts i.length #=> 4
puts i.type #=> String
puts i #=> word
end
So you try to call my_sentence_words[word] instead of my_sentence_words[0]. You can try method each_index that passes index of element instead of element itself`:
def check(str, *arr)
upstr = str.split(' ')
upstr.eachindex do |i| #=> i is index
arr.each_index do |j|
upstr[i].upcase! if upstr[i] == arr[j]
end
end
upstr
end
check("This is my sentence", "day", "is", "goal", "may", "my")
#=>["This", "IS", "MY", "sentence"]

Ruby: Method return without a block

I am trying to make this code return when called without a block. The uncommented lines at the bottom is what I'm trying to get to return. The first uncommented line should return in tut, second line converted to english and the last should be in english. And why is the line " puts eng " returning up and down and not in sentence form? Thanks for any and all help.
Here's my code:
class Tut
##consonants = ["b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z"]
def is_tut? string
if string =~ /^(([b-df-hj-np-z]ut)|([aeiou\s])|[[:punct:]])+$/i
yield
else
false
end
end
def self.to_tut string
string.each_char do |c|
c += "ut" if ##consonants.find { |i| i == c.downcase }
yield c if block_given?
end
end
def self.to_english string
array = string.split //
array.each do |c|
if ##consonants.find { |i| i == c.downcase }
array.shift
array.shift
end
yield c if block_given?
end
end
end
#Tut.to_tut( "Wow! Look at this get converted to Tut!" ) { |c| print c }
# should output : Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!
#puts
#puts
tut = Tut.to_tut( "Wow! Look at this get converted to Tut!" )
puts "from return: #{tut}"
puts
#Tut.to_tut( "Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!" ) { |c| print c }
#should outout : Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!
#puts
#puts
tut = Tut.to_tut( "Wutowut! Lutookut atut tuthutisut gutetut cutonutvuteruttutedut tuto Tututut!" )
puts "from return: #{tut}"
#puts
#tut_string = ""
#Tut.to_tut( "I'm in tut but I want to be in english." ) { |c| tut_string += c }
#puts tut_string
# should output : I'mut inut tututut bututut I wutanuttut tuto bute inut enutgutlutisuthut.
puts
#Tut.to_english( tut_string ){ |c| print c }
# should output : I'm in tut but I want to be in english.
lan = Tut.to_english( tut )
puts lan
(Opening note: You normally don't want to modify an Enumerable object while iterating over it, since that makes it much harder to read the code and debug it.)
Your to_tut doesn't retain your modifications because the "c" block variable is a copy of the string slice, instead of a reference to part of the string (if it were a ref, you'd be able to use << to append; "+=" still wouldn't work because it reassigns rather than changing the ref). That's just how each_char works, since a String doesn't contain references.
If you wanted to modify the string in place, you'd probably have to count backwards and then insert the 'ut' by index via string#[]= . But that's way complicated so I'll present a couple alternates.
Working to_tut #1:
def self.to_tut string
string.chars.map do |c|
yield c if block_given?
# this must be the last expression the block
if ##consonants.find { |i| i == c.downcase }
c + 'ut'
else
c
end
end.join
end
Working to_tut #2 - this is probably the most ruby-ish way to do it:
def self.to_tut string
string.gsub(/[#{##consonants.join}]/i) {|match|
yield match if block_given?
# this must be the last expression in the block
match + 'ut'
}
end
Your to_english doesn't work because array.shift always removes the first element of the array. Instead, you want to track the current index, and remove 2 chars starting from index+1.
Working to_english:
def self.to_english2 string
array = string.split //
array.each_with_index do |c, idx|
if ##consonants.find { |i| i == c.downcase }
array.slice!(idx+1, 2)
end
yield c if block_given?
end
array.join
end
Regarding why your "puts lan" returns one char per line - it's because your to_english returns an array. You'll want to call join to convert it.
The methods to_tut and to_english are giving you wrong answers when used without a block. This happens because ruby always returns the last value evaluated in your method. In your code that will be the result of the string.each_char for to_tut or array.each for to_english. In both cases, the result contains the original input, which is consequently returned and printed.
As to the puts eng, it prints the array returned by array.each of to_english.

Resources