Arithmetic sequence Ruby - ruby

It is a code to find the missing sequence of an arithmetic sequence and finding common difference and also checking is it is an increasing or decreasing sequence. Take user input for further operation
For Ex: enter array elements
2 4 6 10 12 14
missing number is 8 instead of
enter array elements
2
4
6
10
12
14
missing number is 8
puts "enter arithmetic sequence"
o = Array.new
x = gets.chomp
item = x.split(" ")
o.push(item)
puts "#{o}"
len = o.length
sum = (len + 1) * (o[0] + o[len - 1]) / 2
summ = 0
o.each { |a| summ+=a }
res = sum - summ
if(o[1]>o[0])
puts "its an increasing sequence"
else
puts "its a decreasing sequence"
end
common_difference = o[1] - o[0]
puts "Common difference is #{common_difference}"
puts "missing number is #{res}"
The operations like sum common difference are working, but requirement is that we need to take user input in a single line instead of taking in multiple line, split that and store in an array.
For taking sum I used actual sum - target sum method.
Main issue is that it rise an error
`*': Array can't be coerced into Integer
How to convert array elements that is in string format to int using to_i method or Integer method
Expected Output
i/p 2 4 6 8 12 14
o/p
missing number 10

requirement is that we need to take user input in a single line instead of taking in multiple line, split that and store in an array
gets.chomp returns a string with trailing newline removed, e.g. (the 2nd line being user input)
x = gets.chomp
2 4 6 8 12 14
x #=> "2 4 6 8 12 14"
split converts that string to an array:
x.split
#=> ["2", "4", "6", "8", "12", "14"]
what's missing is the conversion to integer. To convert each element of an array, there's map:
x.split.map { |s| s.to_i }
#=> => [2, 4, 6, 8, 12, 14]
or its short-hand notation:
x.split.map(&:to_i)
#=> => [2, 4, 6, 8, 12, 14]
applied to your code:
puts "enter arithmetic sequence"
x = gets.chomp
o = x.split.map(&:to_i)
puts "#{o}"
# ...
Note that there's no need to create an empty array. You can just assign the result of map to o.
The rest of your code seems to work as expected. But you should check out Cary Swoveland's answer for more succinct way of finding the missing element.

Try this:
def missing_number(arr)
((arr.size + 1) * (arr.first + arr.last))/2 - arr.sum
end
missing_number [2, 4, 6, 10, 12, 14] #=> 8
missing_number [11, 8, 5, 2, -4, -7] #=> -1
missing_number [1.2, 2.0, 2.4, 2.8, 3.2] #=> 1.6000000000000014
Suppose arr were not missing any values. For example,
arr = [2, 4, 6, 8, 10, 12, 14]
Then:
arr.sum
#=> 56
which, because it is an arithmetic series, we could alternatively compute as follows:
(arr.size * (arr.first + arr.last))/2
#=> 56
In fact,
arr = [2, 4, 6, 10, 12, 14]
and
arr.sum
#=> 48
As I explained above, we can calculate the sum of the values of arr after the missing value has been inserted as follows:
((arr.size + 1) * (arr.first + arr.last))/2
#=> 56
The missing value therefore equals 56 - 48 #=> 8.
Here is another way to find the missing value that is slightly less efficient.
def missing_number(arr)
arr.each_cons(2).max_by { |a,b| (b-a).abs }.sum/2
end
missing_number [2, 4, 6, 10, 12, 14] #=> 8
missing_number [11, 8, 5, 2, -4, -7] #=> -1
missing_number [1.2, 2.0, 2.4, 2.8, 3.2] #=> 1.6
Suppose
arr = [11, 8, 5, 2, -4, -7]
The steps are as follows.
enum = arr.each_cons(2)
#=> #<Enumerator: [11, 8, 5, 2, -4, -7]:each_cons(2)>
We can see the (5) values that the enumerator will generate and pass to Enumerable#max_by by converting enum to an array:
enum.to_a
#=> [[11, 8], [8, 5], [5, 2], [2, -4], [-4, -7]]
Next let's look at the values that max_by will compare:
enum.map { |a,b| (b-a).abs }
#=> [3, 3, 3, 6, 3]
We therefore obtain the following:
c = enum.max_by { |a,b| (b-a).abs }
#=> [2, -4]
The last two steps calculate the average of 2 and -4:
d = c.sum
#=> -2
d/2
#=> -1

Related

Array#bsearch in Ruby returns nil if the 0 index value is the ONLY value that meets the condition

I provided test cases below, this is just a question to scratch my curiosity.
The ruby documentation for Array#bsearch says:
"This method returns the i-th element. If i is equal to ary.size, it returns nil."
This explanation just isn't clicking in my head yet. Can someone explain it a bit more in-depth?
def greater_than_8(ary)
a = ary.bsearch { |x| x.to_f > 8 }
a.nil? || a.to_f < 8 ? "No number greater than 8" : a
end
ary = [0, 4, 7, 10, 12]
puts greater_than_8(ary)
#=> 10
# Shouldn't this return 14?
ary = [14, 3, 7]
puts greater_than_8(ary)
#=> "No number greater than 8"
# THERE IT IS!
ary = [14, 13, 7]
puts greater_than_8(ary)
#=> 14
ary = [8, 8, 8, 8]
puts greater_than_8(ary)
#=> "No number greater than 8"
ary = [8.01, 123]
puts greater_than_8(ary)
#=> 8.01
ary = ["one hundred", "151", "120", 9]
puts greater_than_8(ary)
#=> 151
Welcome to stack overflow! A precondition for binary search is that the list to be searched must be sorted which [14, 3, 7] is not. Calling your function on the sorted version ([3, 7, 14]) should yield the result you expect.
the elements of the array must be monotone (or sorted) with respect to the block.
Part of the documentation for Array#bsearch is the following requirement:
You can use this method in two modes: a find-minimum mode and a find-any mode. In either case, the elements of the array must be monotone (or sorted) with respect to the block.
In your example you are using find-minimum mode. From there we look at some of your inputs you've used and see if they are monotone or not.
# Monotone increasing, allowed
ary = [0, 4, 7, 10, 12]
# Not monotone, not allowed
ary = [14, 3, 7]
# Monotone decreasing, allowed
ary = [14, 13, 7]

Ruby Second Smallest Number and index

Trying to use Ruby to find the second smallest number and the index from an input. I have the logic working from a hard coded array but can't seem to get the input from a user to work successfully. Thoughts?
print "Enter a list of numbers: "
nums = [gets]
#nums = [3,1,7,5]
lists = nums.sort
A = lists[1]
B = nums.find_index(A)
print "The second smallest number is: #{A} and the index is #{B}"
Suppose the user entered
str = " 2, -3 , 4, 1\n"
Then
arr = str.split(/ *, */).map(&:to_i)
#=> [2, -3, 4, 1]
The regular expression matches zero or more spaces followed by a comma followed by zero or more spaces.
The second smallest element, together with its index, can be obtained as follows.
n, i = arr.each_with_index.min(2).last
#=> [1, 3]
n #=> 1
i #=> 3
See Enumerable#min.
The steps are as follows.
enum = arr.each_with_index
#=> #<Enumerator: [2, -3, 4, 1]:each_with_index>
We can see the elements that will be generated by this enumerator by converting it to an array.
enum.to_a
#=> [[2, 0], [-3, 1], [4, 2], [1, 3]]
Continuing,
a = enum.min(2)
#=> [[-3, 1], [1, 3]]
min(2) returns the two smallest elements generated by enum. min compares each pair of elements with the method Array#<=>. (See especially the third paragraph of the doc.) For example,
[2, 0] <=> [-3, 1]
#=> 1
[4, 2] <=> [1, 3]
#=> 1
[1, 3] <=> [1, 4]
#=> -1
min would therefore order these pairs as follows.
[2, 0] > [-3, 1]
[4, 2] > [1, 3]
[1, 3] < [1, 4]
I've included the last example (though enum.to_a does not contain a second 1 at index 4) to illustrate that the second element of each two-element array serves as a tie-breaker.
As we want the second-smallest element of arr there is one final step.
n, i = a.last
#=> [1, 3]
n #=> 1
i #=> 3
Note that
n, i = [3, 2, 4, 2].each_with_index.min(2).last
#=> [2, 3]
n #=> 2
If we wanted n to equal 3 in this case we could write
n, i = [3, 2, 4, 2].uniq.each_with_index.min(2).last
#=> [3, 0]
n #=> 3
If the entries were floats or a mix of floats and integers we need only replace to_i with to_f.
str = "6.3, -1, 2.4, 3\n"
arr = str.split(/ *, */).map(&:to_f)
#=> [6.3, -1.0, 2.4, 3.0]
n, i = arr.each_with_index.min(2).last
#=> [2.4, 2]
n #=> 2.4
i #=> 2
Scan Input Strings and Map to Integers
The Kernel#gets method returns a String, so you have to parse and sanitize the user input to convert it to an Array. For example:
nums = gets.scan(/\d+/).map &:to_i
This uses String#scan to parse the input string, and Array#map to feed each element of the resulting array to String#to_i. The return value of this method chain will be an Array, which is then assigned to your nums variable.
Results of Example Data
Given input with inconsistent spacing or numbers of digits like:
1,2, 3, 4, 5, 10, 201
the method chain will nevertheless assign sensible values to nums. For example, the input above yields:
#=> [1, 2, 3, 4, 5, 10, 201]

Sorting in Ruby by conditions

I have this array:
arr = [3, 8, 2, 13, 7]
I need to sort the elements first by the number of 1's of their bits and then by the decimal:
bits | decimal
-----+--------
10 | 2
11 | 3
0001 | 8
111 | 7
1011 | 13
to get the result:
[2, 3, 8, 7, 13]
I have this code:
arr = arr.sort { |x, y| x <=> y }
arr = arr.sort { |x, y| x.to_s(2).count(?1) <=> y.to_s(2).count(?1) }
arr # => [2, 8, 3, 13, 7]
How can I fix it?
arr.sort_by { |item| [item.to_s(2).count(?1), item] }
# => [2, 8, 3, 7, 13]
This contradicts the stated desired output, but I believe is consistent with the description of the problem (and that the stated desired output is incorrect): 2, 8 have 1 bit each, 3 has 2, 7 and 13 have 3 bits each; 2 comes before 8, 7 before 13.
This works because the default comparator for arrays is to compare them elementwise; e.g. for 2 and 8, the comparator is seeing [1, 2] <=> [1, 8]; since the first element is same, the second element is compared as a tiebreaker.
I took "decimal" to mean "the numeric value", as represented in OP's code; if it is to be taken literally as "the decimal representation", then
arr.sort_by { |item| [item.to_s(2).count(?1), item.to_s] }
# => [2, 8, 3, 13, 7]

How to handle negative iterator passed in function?

I am working on a manual rotate function in Ruby. But I ran into issue there are negative offsets passed in some examples. Is it possible to iterate from a negative number up to a specified index(not sure what that index would be)?
def my_rotate(arr, offset=1)
if offset < 1
for i in offset
arr.push(arr.shift)
end
else
for i in 1..offset
arr.push(arr.shift)
end
end
arr
end
Following with your code, you can use Array#pop and Array#unshift (which are the opposites of Array#push and Array#shift):
def my_rotate(array, offset=1)
arr = array.dup
if offset < 1
for i in 1..offset.abs
arr.unshift(arr.pop)
end
else
for i in 1..offset
arr.push(arr.shift)
end
end
arr
end
Notice the change in line 5 for i in 1..offset.abs to be able to loop the array, and the addition of line 2 arr = array.dup to prevent the original array from being mutated.
This is pretty much how Array#rotate does it (in C).
Code
class Array
def my_rotate(n=1)
n %= self.size
self[n..-1].concat(self[0,n])
end
end
Examples
arr = [1,2,3,4]
arr.my_rotate 0 #=> [1,2,3,4]
arr.my_rotate #=> [2, 3, 4, 1]
arr.my_rotate 1 #=> [2, 3, 4, 1]
arr.my_rotate 4 #=> [1, 2, 3, 4]
arr.my_rotate 5 #=> [2, 3, 4, 1]
arr.my_rotate 9 #=> [2, 3, 4, 1]
arr.my_rotate -1 #=> [4, 1, 2, 3]
arr.my_rotate -4 #=> [1, 2, 3, 4]
arr.my_rotate -5 #=> [4, 1, 2, 3]
arr.my_rotate -9 #=> [4, 1, 2, 3]
Explanation
The line
n %= self.size
which Ruby's parser expands to
n = n % self.size
converts n to an integer between 0 and self.size - 1. Moreover, it does so for both positive and negative values of n.
The line
self[n..-1].concat(self[0,n])
appends the first n elements of arr to an array comprised of the last arr.size - n elements of arr. The resulting array is then returned by the method.
If you do not wish to add this method to the class Array you could of course define it def my_rotate(arr, n)....

Convert an array in ruby into an output stream

I have an array [2, 4, 6, 8, 3], i need to convert it into an output stream as below:
2 4 6 8 3
Converting into string and chopping the commas and quotes is not helping as it always prints as "2 4 6 8 3" if it is a string.
This is the input given:
5
2 4 6 8 3
This is the code i wrote
def insertionSort( ar)
key = ar.last
(ar.size-2).downto(0){
|x|
if(key < ar[x])
ar[x+1] = ar[x]
p ar
else
ar[x+1] = key
p ar
break
end
}
end
# Tail starts here
count = gets.to_i
ar = gets.strip.split.map {|i| i.to_i}
insertionSort( ar )
My Output:
[2, 4, 6, 8, 8]
[2, 4, 6, 6, 8]
[2, 4, 4, 6, 8]
[2, 3, 4, 6, 8]
Expected Outuput:
2 4 6 8 8
2 4 6 6 8
2 4 4 6 8
2 3 4 6 8
Test Result:
Fail
Your question isn't at all clear, but, maybe this is what you want:
ary = [2, 4, 6, 8, 3]
ary.join(' ') # => "2 4 6 8 3"
ary * ' ' # => "2 4 6 8 3"
Perhaps you don't understand how to loop?
ary = [2, 4, 6, 8, 3]
5.times do
puts ary.join(' ')
end
# >> 2 4 6 8 3
# >> 2 4 6 8 3
# >> 2 4 6 8 3
# >> 2 4 6 8 3
# >> 2 4 6 8 3
Or maybe you don't understand how command-line apps read STDIN?
Dealing with STDIN is useful when writing pipes: Chaining one small specialized application to another, and letting them collectively do a big task is the basic premise for *nix systems. Monolithic apps that try to do everything are a major PITA to write/maintain and use.
If you want to read a single line of input, either from STDIN or the keyboard, gets is good. If you want to read a series of lines, look at Ruby's ARGF class, and become very familiar with how STDIN and $stdin work.
Writing a Ruby command-line script is easy, but, just like doing it in Perl, Python or C, you have to be aware how the incoming data is accessed, what type of data it is (always a string), and how it's structured: characters terminated by a new-line ("\n") or carriage-return+new-line ("\r\n").
Perhaps you don't understand how to_i works?
"2 4 6 8 3".to_i # => 2
"24683".to_i # => 24683
"2_4_6_8_3".to_i # => 24683
to_i reads the string from the first character and continues until it finds a non-digit. So, in the above examples, 2 is the first digit in the first string, followed by a space. The space is a non-digit so to_i stops processing and only returns 2. In the second example, there are no spaces, so to_i processes the entire string and returns it as a single value. In the third, because Ruby, like some other languages, accepts _ as a part of a numeric string, to_i returns the full value again. _ is used to mark the comma positions in values, like 1_000_000.
As you write more code, take the time to write it clearly and cleanly. You want code that reduces the visual noise and makes it easy to take into your brain. Ruby makes it easy to write clean and expressive code that is easy to understand, but bad coding style can reduce Ruby code to unreadable quickly, especially to those of us who are used to seeing it written in an idiomatic style.
This isn't an attempt to fix your algorithm, it's just to show how you should style your code:
def insertion_sort(ar)
key = ar.last
(ar.size - 2).downto(0) { |x|
if (key < ar[x])
ar[x + 1] = ar[x]
p ar
else
ar[x + 1] = key
p ar
break
end
}
end
# Tail starts here
count = gets.to_i
ar = gets.strip.split.map { |i| i.to_i }
insertion_sort(ar)
Methods are always written in snake_case, never CamelCase.
Use whitespace; It gives your eyes and brain logical breaks that help define what is going on. Operators and control structures benefit from having whitespace before and after, and above and below.
Use spaces to indent, with tab-stops set to 2-spaces. This is the Ruby standard. Why those? Consistency as people move code between different editors; If you're working in a professional coding house you'll probably find a lot more rigid coding standards in place.
> a = [1, 2, 3, 4]
> puts "[#{a.join(', ')}]"
=> [1, 2, 3, 4]
Does not work on multi-dimensional arrays, or arrays within arrays.
> a = [1, 2, [3, 4, 5, 6], [7, 8, 9]]
> puts "[#{a.join(', ')}]"
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
But, if you do this, it should work for multi-dimensional arrays:
Example 1:
> a = [1, 2, [3, 4, 5, 6], [7, 8, 9]]
> a.each do |sub_a|
> puts "[#{a.join(', ')}]"
> end
=> [1, 2, [3, 4, 5, 6], [7, 8, 9]]
Example 2:
> a = [1, [2, [3, 4, [5, 6, 7, 8], 9, 0]], 'x', 'y', 'z']
> a.each do |sub_a|
> puts "[#{a.join(', ')}]"
> end
=> [1, [2, [3, 4, [5, 6, 7, 8], 9, 0]], "x", "y", "z"]
After reading the HackerRank "Insertion Point" question you referenced, the input appears to be coming from stdin. If your code includes
s = gets
it will wait for you to enter a string. Suppose you enter 1 2 3 4 (no quotes). Then s will hold "1 2 3 4\n".
If you want to convert this to an array:
a = s.split # => ["1","2","3","4"]
If you want the elements of a to be integers, rather than strings:
a.map! {|e| e.to_i} # => [1,2,3,4]
which (since Ruby version 1.9) can also be written:
a.map!(&:to_i) # => [1,2,3,4]
The 'Ruby way' would be to chain these operations:
a = gets.split.map(&:to_i) # => [1,2,3,4]
Note that we don't need ! with map now.
If you want this array to be a row i of some (existing array) b
b[i] = a

Resources