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