Repeat Method to Give "string" an "x" amounts of times - ruby

I'm trying to write a method that will take two arguments, one for the string, and the other the number of times it will be repeated. here is the code of i have:
def repeat(text,c=2)
c.times do print text end
end
repeat ("hi")
problem here is, I want to have the result to be "hi hi"
i tried "puts" but that starts a new line...
[ print text " + " text ] doesn't work as well...
thanks for the help!

Your question is unclear. If all you want is to print the text repeated n times, use String#*
def repeat(text, n=2)
print text * n
end
Your example result says you want "hi hi" implying you would like spaces between each repetition. The most concise way to accomplish that is to use Array#*
def repeat(text, n=2)
print [text] * n * ' '
end

Simply multiply the string by the number, Ruby is smart enough to know what you mean ;)
pry(main)> "abcabcabc" * 3
=> "abcabcabcabcabcabcabcabcabc"

Or you could do something like:
def repeat(text, c=2)
print c.times.collect { text }.join(' ')
end

Enumerator#cycle returns an enumerator:
puts ['hi'].cycle(3).to_a.join(' ')
# => hi hi hi
Breaking down the code:
['hi'] creates an array containing a string
cycle(3) creates an enumerator from the array that repeats the elements 3 times
.to_a creates an array from the enumerator so that the join method of Array can create the final output string.

def repeat(text, c=2)
print Array.new(c, text).join(' ')
end

I am new to ruby, but I thought this solution worked well for me and I came up with it myself.
def repeat(word, i=2)
word + (" #{word}" * (i-1))
end

You can try this:
def repeat(text, c=2)
print ((text + ' ')*c).strip
end

def repeat(text, c=2)
print ([text]*c).join(' ')
end
Perhaps easier to read. Unless, is there any reason to use the .collect method instead?

I don't see the point in creating an array (with or without collect()) and then calling join(). This works too:
def repeat(text, c=2)
c.times { |i| print text; print ' ' unless i+1 == c }
end
Although, it is a little more verbose (which is arguably un-ruby like) it does less work (which maybe makes more sense).

Related

Join a ruby enumerator into a string

I have an instance of Enumerator::Generator that yields strings. I need to join them into a single string.
What's a good way of doing this? I notice that * doesn't work. I know I can .map {|x| x} first but that seems rather un-idiomatic
I think in this case I' might reach for inject/reduce (aliases for the same method, reduce as a name makes more sense, to me) with the + operator:
enum.reduce(:+)
# or, passing in a block
enum.reduce(&:+)
As a full example:
# never used Enumerator::Generator directly, but you called it out specifically
# in your question, and this seems to be doing the trick to get it working
enum = Enumerator::Generator.new do |y|
y.yield "ant"
y.yield "bear"
y.yield "cat"
end
p enum.reduce(&:+) # output: "antbearcat"
# crude example of modifying the strings as you join them
p enum.reduce('') { |memo, word| memo += word.upcase + ' ' }
# output: "ANT BEAR CAT "
a=["Raja","gopalan"].to_enum #let's assume this is your enumerator
Write the following code
p a.map(&:itself).join
Or
p a.to_a.join
output
"Rajagopalan"

Making a sorted array of user's input

I'm learning Ruby with 'Learn to Program' by Chris Pine. On chapter 10 I should write a program where the user types as many words as he like and when he's done, he can just press Enter on an empty line and exit.
I came up with this:
puts "Type whatever you want!"
index = 0
word = ''
array = []
while word != nil
word << gets.chomp
array[index] = word
index = index + 1
end
puts ''
puts array.sort
But that doesn't work. What did I miss? Is there another way I could define word without having to repeat it?
The word will not have nil value. It will be an empty string. So you need to check for that:
while word != ""
# or even better
while !word.empty?
Also, you are adding everything to your word. You probably want to assign to it instead:
word = gets.chomp
Per author's comment:
begin
# your code here
end while !word.empty?
# OR more readable
begin
# your code here
end until word.empty?
It seems like there's a simpler solution, if I'm reading the question correctly.
You could do something like this:
user_input = gets.chomp.split(" ").sort
ex)
input: bananas clementine zebra tree house plane mine
output: ["bananas", "clementine", "house", "mine", "plane", "tree", "zebra"]
Here's a simple loop that you could do just for kicks:
arr = []
arr << $_.strip until gets =~ /^\s*$/
puts arr.sort
$_ is a special variable that evaluates to the last input read from STDIN. So basically this reads "Call gets and check if the input is just spaces. If it is then break out of the loop, otherwise append the last input with whitespace removed value onto the array and continue looping."
Or even more fun, a one liner:
puts [].tap {|arr| arr << $_.strip until gets =~ /^\s*$/}.sort
Basically same thing as above except using tap to initialize the variable.
To answer your questions:
Is there another way I could define word without having to repeat it?
Use side effects of assignment. In ruby when you assign a variable the return value of that assignment is the assigned variable, as in:
irb(main):001:0> (variable = 2) == 2
=> true
The idea would be to put the assignment in the your conditional. If I were to write something like this in a comprehensible loop, as opposed to those above, I'd write something like this:
arr = []
while !(word = gets.strip).empty?
arr << word
end
puts arr.sort
Using loop might simplify the code:
a = []
loop do
input = gets.chomp
if input.empty?
break
else
a << input
end
end
a.sort!
puts a

Ruby modify a piece of a string

Totally new to Ruby. This is a simple homework assignment. The secret_code function needs to take in input string and perform the following actions:
In the first block of letters before a space, capitalize all but the first char
Reverse the string
So if the input were "super duper", the output should be "repud REPUs".
I coded the function as follows:
def secret_code(input)
input.split(" ").first[1..-1].each_char do |i|
input[i] = i.upcase
end
return input.reverse
end
It passes the unit tests, but I am wondering if there is a better way to code it. Is it possible to avoid using the loop? I tried
return input.split(" ").first[1..-1].upcase.reverse
But that didn't quite work. Any thoughts on how to clean this up are appreciated!
"super duper".sub(/(?<=.)\S+/, &:upcase).reverse
How about this:
def secret_code(input)
first_space = input.index(' ')
(input[0] + input[1...first_space].upcase + input[first_space..-1]).reverse
end
Note that in Ruby, the last expression evaluate in a method is always returned, so you can omit the final return.
s = "super duper"
words = s.split(' ')
words.first[1..-1] = words.first[1..-1].upcase
words.each { |word| word.reverse! }
s = words.reverse.join(' ')
puts s # => repud REPUs
Not necessarily any better, but sure, it can be done without a loop...
def f x
(b = [(a = x.split)[0].upcase, *a.drop(1)].join(' ').reverse)[-1] = x[0, 1]
return b
end
You can try the below:
a = "super duper"
p a.gsub(a.split[0...1].join(' '),a.split[0...1].join(' ').capitalize.swapcase).reverse
Output:
"repud REPUs"

Remove string values that differ only in case from an array (Ruby)

So, here's the preface:
I'm quite a beginner in Ruby. I'm working on a anagram finding script (find all anagrams in a text file). The essence is: I create a dictionary where key is word code and value is an array with words that refer to this code. It is like that: {"abdeis"=>["abides", "biased"] ,"achr"=>["char"], ... }. In the end I just print out the values with length of >1. So good so far.
Here's the deal: I want to modify the output, so that such cases are omitted: ["Wood", "wood", "WooD"] - all are different in case only. But such cases should stay: ["Doom", "DooM", "mood"].
My current piece of code:
def print_anagram(anagram_dict)
anagram_list = anagram_dict.values
anagram_list.each { |i|
if i.length > 1
print i.join("\t")
print "\n"
else
next
end
}
end
anagram_dict is a dictionary mentioned above.
What checks should I make to throw these cases away? The things I think of seem way to bulky to me. Thanks in advance!
def print_anagram(anagram_dict)
anagram_list = anagram_dict.values
anagram_list.each do |i|
next if i.map(&:downcase).uniq.length == 1
if i.length > 1
print i.join("\t")
print "\n"
else
next
end
end
end
What this does:
make all Strings lowercase
get only unique elements from the array
if you only have one unique element, all elements are the same
map(&:downcase) is a shorter way of doing: map { |element| element.downcase }
Does this do what you want?
def print_anagram(anagram_dict)
anagram_list = anagram_dict.values.uniq{|word| word.downcase}
# rest of your code

Using each in Ruby

I am starting to learn ruby and am trying to figure out a way to if i have an array of 16 numbers, to print those numbers 4 at a time using only the each method. I can easily do this with a loop but i am lacking full understanding of the each method in Ruby so this gives me some trouble.
I have the following:
x=[*1..16]
index=0
x.each do |element|
puts element[index]
index=index+3
end
Now obviously this is completely wrong and i know that but i wanted to put something on here. A little advice would be great.
Thank you
A possible solution:
a = (1..16)
a.each_slice(4) { |s| p s[3] }
EDIT: If you want print 4 elements on one line, then skip to the next line and print the next 4 elements, etc
a = (1..16)
a.each_slice(4) { |s| puts s.join(' ') }
Or using each only
a = (1..16)
a.each { |i| print i.to_s + ' '; print "\n" if i % 4 == 0 }
Try each_slice http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-each_slice.
Using that would look something like
(1..16).each_slice(4) do |x|
puts x.inspect
end

Resources