Iterate through alphabet in Ruby until X - ruby

When using input x, I'm trying to iterate through the alphabet through to that point so, if I put in 44, I'll iterate to 18 from this method.
I can see a lot of methods on SO for iteration a..z, a..zzz, etc, but less for iteration to position x and outputting the associated letters. Is there a ruby method for flipping an input letter to a number within a dynamic range?
def get_num(x)
pos = x%26
(1..pos).each do |c|
puts c
#outputs letter for position c
# end
end
get_num(44) # => Expected: 44%26 = 18; iterate 1 to 18 (pos) to get A..R list as output.

Using the #Integer.chr method, 'a'..'z' == 97..122, and 'A'..'Z' == 65..90 That means:
def get_num(x)
pos = x%26
(96+pos).chr
end
get_num(44)
#=> "r"
OR
def get_num(x)
pos = x%26
(64+pos).chr
end
get_num(44)
#=> "R"
So, to complete your method:
def get_num(x)
pos = x%26
(1..pos).each do |c|
puts (c+64).chr
end
end
get_num(44)
#=>
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R

Related

Ruby - Find the longest non-repeating substring in any given string

I am working on an assignment where I have to take user input of a string and search through it to find the longest non-repeating string in it. So for example:
If the string is:
"abcabcabcdef"
My output needs to be:
"abcdef is the longest substring at the value of 6 characters"
Here is my poorly made code:
class Homework_4
puts "Enter any string of alphabetical characters: "
user_input = gets
longest_str = 0
empty_string = ""
map = {}
i = 0
j = 0
def long_substr()
while j < str_len
if map.key?(user_input[j])
i = [map[user_input[j]], i].max
end
longest_str = [longest_str, j - i + 1].max
map[user_input[j]] = j + 1
j += 1
end
longest_str
end
long_substr(user_input)
end
I have been working on this for over 6 hours today and I just can't figure it out. It seems like the internet has many ways to do it. Almost all of them confuse me greatly and don't really explain what they're doing. I don't understand the syntax they use or any of the variables or conditions.
All I understand is that I need to create two indicators that go through the inputted string searching for a non-repeating substring (sliding window method). I don't understand how to create them, what to make them do or even how to make them find and build the longest substring. It is very confusing to try and read the code that is full of random letters, symbols, and conditions. I'm sure my code is all sorts of messed up but any help or tips that could point me in the right direction would be greatly appreciated!
def uniq?(s)
# All letters of s uniq?
return s.chars.uniq == s.chars
end
def subs(s)
# Return all substrings in s.
(0..s.length).inject([]){|ai,i|
(i..s.length - i).inject(ai){|aj,j|
aj << s[i,j]
}
}.uniq
end
def longest_usub(s)
# Return first longest substring of s.
substrings(s).inject{|res, s| (uniq?(s) and s.length > res.length) ? s : res}
end
ruby's inject is actually a reduce function, where inject(optional_start_value){<lambda expression>} - and the lambda expression is similar to Python's lambda x, y: <return expression using x and y> just that lambda expressions are strangely written in Ruby as {|x, y| <return expression using x and y>}.
Python's range(i, y) is Ruby's i..y.
Python's slicing s[i:j] is in Ruby s[i..j] or s[i,j].
<< means add to end of the array.
Second solution (inspired by #Rajagopalan's answer)
def usub(s)
# Return first chunk of uniq substring in s
arr = []
s.chars do |char|
break if arr.include? char
arr << char
end
arr.join
end
def usubs(s)
# Return each position's usub() in s
(0..s.length).to_a.map{|i| usub(s[i,s.length])}
end
def longest_usub(s)
# return the longest one of the usubs() over s
usubs(s).max_by(&:length)
end
then you can do:
longest_usub("abcabcabcdef")
## "abcdef"
I have asssumed that a string is defined to be repeating if it contains a substring s of one or one more characters that is followed by the same substring s, and that a string is non-repeating if it is not repeating.
A string is seen to be repeating if and only if it matches the regular expression
R = /([a-z]+)\1/
Demo
The regular expression reads, "match one or more letters that are saved to capture group one, then match the content of capture group 1".
For convenience we can construct a simple helper method.
def nonrepeating?(str)
!str.match? R
end
I will perform a binary search to find the longest non-repeating string. First, I need a second helper method:
def find_nonrepeating(str, len)
0.upto(str.size-len) do |i|
s = str[i,len]
return s if nonrepeating?(s)
end
nil
end
find_nonrepeating("abababc", 7) #=> nil
find_nonrepeating("abababc", 6) #=> nil
find_nonrepeating("abababc", 5) #=> nil
find_nonrepeating("abababc", 4) #=> "babc"
find_nonrepeating("abababc", 3) #=> "aba"
find_nonrepeating("abababc", 2) #=> "ab"
find_nonrepeating("abababc", 1) #=> "a"
We may now implement the binary search.
def longest(str)
longest = ''
low = 0
high = str.size - 1
while low < high
mid = (low + high)/2
s = find_nonrepeating(str, mid)
if s
longest = s
low = mid + 1
else
high = mid - 1
end
end
longest
end
longest("dabcabcdef")
#=> "bcabcdef"
a = "abcabcabcdef"
arr = []
words = []
b=a
a.length.times do
b.chars.each do |char|
break if arr.include? char
arr << char
end
words << arr.join
arr.clear
b=b.chars.drop(1).join
end
p words.map(&:chars).max_by(&:length).join
Output
"abcdef"

String count without using ".length" or ".size" methods?

I am new to the ruby and was practicing a code. I want to count the letters in a string by a self written code, without using #length or #size method. I have searched online but am unable to find anything relating to my query. I would appreciate if anyone could help me out in this simple program.
Other option, mapping String#chars with index then picking the last:
str = "123456"
str.chars.map.with_index { |_, i| i + 1 }.last
#=> 6
It generates an Array, but we are not looking for efficiency here.
Or even using String#index with offset:
str = "aaaa"
str.index(str[-1], -1) + 1
#=> 4
It looks for the index of the latest char starting from the end.
You can do that using any String method that enumerates characters. The most obvious is String#each_char, as #knut mentioned in a comment.
def str_length(str)
enum = str.each_char
n = 0
loop do
enum.next
n += 1
end
n
end
str_length "Zaphod"
#=> 6
Let's see what is happening here.
str = "Zaphod"
enum = str.each_char
#=> #<Enumerator: "123456":each_char>
n = 0
loop do
s = enum.next
n += 1
puts "s = #{s}, n = #{n}"
end
n #=> 6
prints
s = Z, n = 1
s = a, n = 2
s = p, n = 3
s = h, n = 4
s = o, n = 5
s = d, n = 6
See Enumerator#next. After enum.next #=> "d" is executed enum.next is executed once more, raising a StopIteration exception. That exception is handled by Kernel#loop by breaking out of the loop.
As I said at the outset, any String method could be used that enumerates characters. For example, enum = str.gsub(/./).
The same approach could be used for any class that implements a method that enumerates elements of a collection. For example, we could add a method to the Enumerable module, which would then be available for every class that includes that module.
module Enumerable
def my_length
enum = each
n = 0
loop do
enum.next
n += 1
end
n
end
end
[1,2,3,4].my_length
#=> 4
{ a: 1, b: 2 }.my_length
#=> 2
(1..5).my_length
#=> 5

Ruby - Finding the longest palindromic substring in a string

I understand how to find if one string is a palindrome
string1 == string1.reverse
It's a little more difficult though with multiple palindromes in a string
"abcdxyzyxabcdaaa"
In the above string, there are 4 palindromes of length greater than 1
"xyzyx", "yzy", "aaa" and "aa"
In this case, the longest palindrome is "xyxyx", which is 5 characters long.
How would I go about solving this problem though.
I know of the array#combination method, but that won't work in this case.
I was thinking of implementing something like this
def longest_palindrome(string)
palindromes = []
for i in 2..string.length-1
string.chars.each_cons(i).each {|x|palindromes.push(x) if x == x.reverse}
end
palindromes.map(&:join).max_by(&:length)
end
If your just looking for the largest palindrome substring, Here is a quick and dirty solution.
def longest_palindrome(string, size)
string.size.times do |start| # loop over the size of the string
break if start + size > string.size # bounds check
reverse = string[start, size].reverse
if string.include? reverse #look for palindrome
return reverse #return the largest palindrome
end
end
longest_palindrome(string, size - 1) # Palindrome not found, lets look for the next smallest size
end
def longest_palindrome(string)
longest = ''
i = 0
while i < string.length
j = 1
while (i + j) <= string.length
x = string.slice(i, j)
if (x.length > longest.length) && (x == x.reverse)
longest = x
end
j += 1
end
i += 1
end
longest
end
The slice method is handy to have for solving this problem. Test each substring with the classic double while loop approach with (i, j) representing a starting index and length of the substring respectively. string.slice(start_index, substring_length)
The String#slice method works like this:
"bdehannahc".slice(3, 8) == "hannah" # which is a palindrome and would be
# found by the method introduced above
This checks if the entire string str is a palindrome. If it is, we're finished; if not, check all substrings of length str.size-1. If one is a palindrome, we're finished; if not, check substrings of length str.size-1, and so on.
def longest_palindrome(str)
arr = str.downcase.chars
str.length.downto(1) do |n|
ana = arr.each_cons(n).find { |b| b == b.reverse }
return ana.join if ana
end
end
longest_palindrome "abcdxyzyxabcdaaa"
#=> "xyzyx"
longest_palindrome "abcdefghba"
#=> "a"
The key method here is Enumerable#each_cons.
Here is another solution, using less features of Ruby and iteration instead of recursion:
def longest_palindrome(string)
# to find the longest palindrome, start with whole thing
substr_start = 0
substr_length = string.length
while substr_length > 0 # 1 is a trivial palindrome and the end case
# puts 'substr_length is:' + substr_length.to_s
while substr_start <= string.length - substr_length
# puts 'start is: ' + substr_start.to_s
if palindrome?(string.slice(substr_start,substr_length))
puts 'found palindrome: ' + string.slice(substr_start,substr_length)
return string.slice(substr_start,substr_length)
end
substr_start += 1
end
substr_start = 0 # inner loop ctr reset
substr_length -= 1
end
puts 'null string tested?'
return ''
end

I ran into issue here with splitting array and adding it up

i am trying to find if array has 2 digits number and if i find one i want to add the two digit and make it single. then add all the numbers in array to come up with a a sum. here is my code so far. and also i am a noob and learning
class Imei
attr_accessor :Imei, :split_total1, :split_total2
def initialize(imei)
#imei = imei.to_i
#split_total1 = []
#split_total2 = []
end
def check_two_digit(num)
if num.to_s.length == 2
num = num.to_s.split(//).partition.with_index{|_,i| i.odd?}
num.each do |a, b|
a.to_i + b.to_i
end
else
num.to_i
end
end
def check_imei
if #imei.to_s.length == 15
split1, split2 = #imei.to_s.split(//).partition.with_index{|_, i| i.odd?}
split1.each do |a|
#split_total1 << check_two_digit(a.to_i * 2)
end
split2.pop
split2.each do |a|
#split_total2 << a.to_i
end
else
puts "IMEI NUMBER INVALID"
end
end
end
imei = Imei.new(123456789102222)
imei.check_imei
puts imei.split_total1.inspect
puts imei.split_total2.inspect
Find below the Luhn Algorithm I wrote in ruby
def luhn_10_valid? imei
digits = imei.reverse.chars.map(&:to_i)
digits.each_with_index.inject(0) do |sum, (digit, i)|
digit *= 2 if i.odd?
digit -= 9 if digit > 9
sum += digit
end % 10 == 0
end
For Luhn algorithm I really like the divmod method, which simplifies things
array.reverse.each_slice(2).map { |x, y|
y ||= 0
[x, (y * 2).divmod(10)]
}.flatten.inject(:+) % 10 == 0
If a contains only non-negative integers, this is one Ruby-like way to compute the sum:
a.reduce(0) {|t,i| t + (((10..99).cover? i) ? i.divmod(10).reduce(:+) : i )}
Explanation:
If i => 46, (10..99).cover?(46) => true, 46.divmod(10) => [4,6], [4,6].reduce(:+) => 10. Recall that reduce is aka inject. [4,6]reduce(:+) has the same result as (but,technically, is not 'equivalent to'):
[4,6].reduce { |u,j| u+j }
The zero initial value is needed for the first reduce, as
a[46].reduce {|t,i| t+(((10..99).cover? i) ? i.divmod(10).reduce(:+):i)}
#=> 46
which is incorrect.
If a instead contains string representations of integers and/or the integers may be negative, let me know and I'll change my answer accordingly.

Variable and expressions in ruby

I am trying to create a ruby program where three numbers are entered and their sum is taken but if any numbers are the same they don't count toward the sum.
example (4,5,4) = 5
My problem is with my expressions. If i enter the same number I get multiple output for various combination. example enter 5,5,5 = 15,5,0
if a != b or c then
puts a+b+c
elsif b != a or c then
puts a+b+c
elsif c != a or b then
puts a+b+c
end
if a == b then
puts c
elsif a == c then
puts b
elsif b == c then
puts a
end
if a == b and c then
puts 0
elsif b == a and c then
puts 0
elsif c == a and b then
puts 0
end
Solving it with two beautiful self explanatory one-liners
array = [a,b,c]
array = array.keep_if {|item| array.count(item) == 1 }
array.inject(0){|sum,item| sum + item}
-The first line creates an array with your parameters.
-The second line only keep the items whose count equals to 1 (remove the ones that appear more than one time), and store that on the array.
-The third line sums all the remaining elements.
VoilĂ , the ruby way :)

Resources