Ruby next multiple - ruby

Is there another way to write 'a'.next.next? I've looked all over and can't seem to find it.
I've tried multiplying the .next but I keep getting errors.

Well, this might not be a good idea in the case here, but if you're looking to chain a method n times in general, you can do something like this:
2.times.inject('a') { |s| s.next }
# => 'c'
20.times.inject('a') { |s| s.next }
# => 'u'
This starts with the value 'a', runs a block that calls next, then each successive result is fed back into the block.
For what it's worth, monkey-patching String can be fine for trivial scripts, but personally I'd try to look for other solutions first, like just adding a utility function to your class/module:
def repeat_next(str, n = 1)
n.times.inject(str) { |s| s.next }
end
A shortcut for your specific problem, (a.ord + 2).chr, potentially exists, although it's not the same thing.

You can just redefine String.next like this:
class String
alias_method :next1, :next
def next(n = 1)
str = self
for i in 1..n
str = str.next1
end
str
end
end
puts 'a'.next
puts 'a'.next(2)
puts 'a'.next(20)

If you're looking for a more succinct way of doing this, you could use: ('a'.ord + 2).chr. This will convert 'a' to a numerical representation (with the "ord" method), increment it by two, then converts it back to the character representation (with "chr").

You can monkey-patch the String class in ruby to add a method to do this for you:
class String
def get_nth_char(n)
current = self
while n > 0 do
current = current.next
n = n - 1
end
current
end
end
So you can do 'a'.get_nth_char(2) # => 'c'

Related

ruby do map and compact together

I'm new to ruby and this looks wrong but works fine
def get_internal_deps
self.internal_dependencies = self.sources.map do |f|
s = File.open(File.join(self.dir, f)).grep(/\d{8}-\w{5}/)
if s.length > 0
{:file => f, :line => s}
end
end.compact
#how crazy does that look?
end
So how do I do this without having an end.compact?
Some notes
Your method is called get_internal_deps, but it looks like it actually sets an instance variable.
You could define internal_dependencies and use caching.
In this case, you'd need to remove any attr_reader/writer/accessor for #internal_dependencies.
File.open(f) isn't really clean.
You don't need self in self.dir or self.sources
:line is an Array. Shouldn't it be called :lines?
2 separate, short methods might be better than a bigger one.
Refactored code
def internal_dependencies
#internal_dependencies ||= sources.map{|s| parse_dependency(s) }
.reject{|h| h[:line].empty? }
end
private
def parse_dependency(source)
{
file: source,
line: File.readlines(File.join(dir, source)).grep(/\d{8}-\w{5}/)
}
end
To avoid compact one might use reduce (Enumerable#each_with_object in this particular case) instead of map:
def get_internal_deps
self.internal_dependencies = sources.each_with_object do |f, acc|
s = File.open(File.join(self.dir, f)).grep(/\d{8}-\w{5}/)
acc << {:file => f, :line => s} if s.length > 0
end
end
Also, note that an explicit self receiver might make sense in a case of assignment, but it is completely redundant in RHO (sources in this snippet.)

Reversing a Ruby String, without .reverse method

I am working on this coding challenge, and I have found that I am stuck. I thought it was possible to call the .string method on an argument that was passed in, but now I'm not sure. Everything I've found in the Ruby documentation suggests otherwise. I'd really like to figure this out without looking at the solution. Can someone help give me a push in the right direction?
# Write a method that will take a string as input, and return a new
# string with the same letters in reverse order.
# Don't use String's reverse method; that would be too simple.
# Difficulty: easy.
def reverse(string)
string_array = []
string.split()
string_array.push(string)
string_array.sort! { |x,y| y <=> x}
end
# These are tests to check that your code is working. After writing
# your solution, they should all print true.
puts(
'reverse("abc") == "cba": ' + (reverse("abc") == "cba").to_s
)
puts(
'reverse("a") == "a": ' + (reverse("a") == "a").to_s
)
puts(
'reverse("") == "": ' + (reverse("") == "").to_s
)
This is the simplest one line solution, for reversing a string without using #reverse, that I have come across -
"string".chars.reduce { |x, y| y + x } # => "gnirts"
Additionally, I have never heard of the #string method, I think you might try #to_s.
Easiest way to reverse a string
s = "chetan barawkar"
b = s.length - 1
while b >= 0
print s[b]
b=b-1
end
You need to stop the search for alternative or clever methods, such as altering things so you can .sort them. It is over-thinking the problem, or in some ways avoiding thinking about the core problem you have been asked to solve.
What this test is trying to get you you to do, is understand the internals of a String, and maybe get an appreciation of how String#reverse might be implemented using the most basic string operations.
One of the most basic String operations is to get a specific character from the string. You can get the first character by calling string[0], and in general you can get the nth character (zero-indexed) by calling string[n].
In addition you can combine or build longer strings by adding them together, e.g. if you had a="hell" and b="o", then c = a + b would store "hello" in the variable c.
Using this knowledge, find a way to loop through the original string and use that to build the reverse string, one character at a time. You may also need to look up how to get the length of a string (another basic string method, which you will find in any language's string library), and how to loop through numbers in sequence.
You're on the right track converting it to an array.
def reverse(str)
str.chars.sort_by.with_index { |_, i| -i }.join
end
Here is a solution I used to reverse a string without using .reverse method :
#string = "abcde"
#l = #string.length
#string_reversed = ""
i = #l-1
while i >=0 do
#string_reversed << #string[i]
i = i-1
end
return #string_reversed
Lol, I am going through the same challenge. It may not be the elegant solution, but it works and easy to understand:
puts("Write is a string that you want to print in reverse")
#taking a string from the user
string = gets.to_s #getting input and converting into string
def reverse(string)
i = 0
abc = [] # creating empty array
while i < string.length
abc.unshift(string[i]) #populating empty array in reverse
i = i + 1
end
return abc.join
end
puts ("In reverse: " + reverse(string))
Thought i'd contribute my rookie version.
def string_reverse(string)
new_array = []
formatted_string = string.chars
new_array << formatted_string.pop until formatted_string.empty?
new_array.join
end
def reverse_str(string)
# split a string to create an array
string_arr = string.split('')
result_arr = []
i = string_arr.length - 1
# run the loop in reverse
while i >=0
result_arr.push(string_arr[i])
i -= 1
end
# join the reverse array and return as a string
result_arr.join
end

Ruby - Populate and Array with returned method values

So, pretend we have the following three methods that check a grid to determine if there is a winner, and will return true if there is.
def win_diagonal?
# Code here to check for diagonal win.
end
def win_horizontal?
# Code here to check for horizontal win.
end
def win_vertical?
# Code here to check for vertical win.
end
I would like to push the returned values of each method into an Array instead of literally using the method names. Is this possible?
def game_status
check_wins = [win_vertical?, win_diagonal?, win_horizontal?]
if check_wins.uniq.length != 1 # When we don't have only false returns from methods
return :game_over
end
end
What you are looking for will indeed work in ruby.
def hello_world?
"hello world!"
end
a = [hello_world?]
Prints out
=> ["hello world!"]
Hope that helps. IRB is your friend when you wonder if something is possible in Ruby :-)
Simpler way (and very readable) yet:
def game_status
win_vertical? || win_diagonal? || win_horizontal?
end
If, for example, win_vertical? returns true, the other algorithms won't even need to run. You return immediately.
Or, if you need to know in which way the user won, I mean, if you need to preserve the results of all methods after they ran, you can use a hash, like:
{:vertical => win_vertical?, :diagonal => win_diagonal?, :horizontal => win_horizontal?}
This solution, like the array one, is worse than the first one above for it runs all algorithms all the time. If they are complex, you may have a problem. =)
You can do something like this when you really want to store all return values in an array:
def game_status
check_wins = [win_vertical?, win_diagonal?, win_horizontal?]
return :game_over if check_wins.any?
end
For readability I would prefer:
def game_status
return :game_over if win_vertical? || win_diagonal? || win_horizontal?
end

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"

How do I make multiple combinations with a string in ruby?

Input should be a string:
"abcd#gmail.com"
Output should be an Array of strings:
["abcd#gmail.com",
"a.bcd#gmail.com",
"ab.cd#gmail.com",
"abc.d#gmail.com",
"a.b.cd#gmail.com",
"a.bc.d#gmail.com",
"a.b.c.d#gmail.com"]
The idea: "Make every possible combination in the first string part ("abcd") with a dot. Consecutive dots are not allowed. There are no dots allowed in the beginning and in the end of the first string part ("abcd")"
This is what I've came up with so far:
text,s = "abcd".split""
i=0
def first_dot(text)
text.insert 1,"."
end
def set_next_dot(text)
i = text.rindex(".")
text.delete_at i
text.insert(i+1,".")
end
My approach was
write a function, that sets the first dot
write a function that sets the next dot
...(magic)
I do not know how to put the pieces together. Any Idea? Or perhaps a better way?
thanx in advance
edit:
I think I found the solution :)
I will post it in about one hour (it's brilliant -> truth tables, binary numbers, transposition)
...and here the solution
s = "abc"
states = s.length
possibilites = 2**states
def set_space_or_dot(value)
value.gsub("0","").gsub("1",".")
end
def fill_with_leading_zeros(val, states)
if val.length < states
"0"*(states-val.length)+val
else
val
end
end
a = Array.new(possibilites,s)
a = a.map{|x| x.split ""}
b = [*0...possibilites].map{|x| x.to_s(2).to_s}
b = b.map{|x| fill_with_leading_zeros x,states}
b = b.map{|x| x.split ""}
c = []
for i in 0 ... a.size
c[i] = (set_space_or_dot (a[i].zip b[i]).join).strip
end
Changing pduersteler answer a little bit:
possibilities = []
string = "abcd#example.com"
(string.split('#')[0].size-1).times do |pos|
possibility = string.dup
possibilities << possibility.insert(pos+1, '.')
end
How about this (probably needs a bit more fine-tuning to suit your needs):
s = "abcd"
(0..s.size-1).map do |i|
start, rest = [s[0..i], s[(i+1)..-1]]
(0..rest.size-1).map { |j| rest.dup.insert(j, '.') }.map { |s| "#{start}#{s}"}
end.flatten.compact
#=> ["a.bcd", "ab.cd", "abc.d", "ab.cd", "abc.d", "abc.d"]
An option would be to iterate n times through your string moving the dot, where n is the amount of chars minus 1. This is what you're doing right now, but without defining two methods.
Something like this:
possibilities = []
string = "abcd#example.com"
(string.split('#')[0].size-1).times do |pos|
possibilities << string.dup.insert(pos+1, '.')
end
edit
Now tested. THanks to the comments, you need to call .dup on the string before the insert. Otherwise, the dot gets inserted into the string and will stay there for each iteration causing a mess. Calling .dup onthe string will copy the string and works on the copy instead, leaving the original string untouched.

Resources