3

I am trying to find the duplicate values in an array of strings between 1 to 1000000.

However, with the code I have, I get the output as all the entries that are doubled.

So for instance, if I have [1,2,3,4,3,4], it gives me the output of 3 4 3 4 instead of 3 4.

Here is my code:

array = [gets]

if array.uniq.length == array.length
  puts "array does not contain duplicates"
else
  puts "array does contain duplicates"
  print array.select{ |x| array.count(x) > 1}
end

Also, every time I test my code, I have to define the array as array = [1,2,3,4,5,3,5]. The puts works but it does not print when I use array [gets].

Can someone help me how to fix these two problems?

Vitalii Elenhaupt
  • 7,146
  • 3
  • 27
  • 43
Shaili Parikh
  • 107
  • 1
  • 3
  • 11
  • 5
    `a.select{ |x| a.count(x) > 1}.uniq` try this – Vrushali Pawar Jun 03 '15 at 06:06
  • May be [duplicate of this](http://stackoverflow.com/questions/8921999/ruby-how-to-find-and-return-a-duplicate-value-in-array) – Gagan Gami Jun 03 '15 at 06:19
  • `gets` returns a string delimited with a newline. You can't input an array like that. You need something like `array = gets.chomp.split.map(&:to_i)` and expect the user to enter, say, `1 2 3 4 5`, followed by return. – Cary Swoveland Jun 03 '15 at 06:21
  • So how do I do do it? It asks me for an array between 1 to 1000000. How do I submit my answer then? – Shaili Parikh Jun 03 '15 at 06:22
  • Are you sure you have to use `gets`, rather than simply being given an arbitrary array `arr`? If you must use `gets`, you can only get a string, so you will have to break it up into separate elements and convert that to an array. Of course, the user will have to follow your instructions on how to format the string for conversion to an array. – Cary Swoveland Jun 03 '15 at 06:29
  • @CarySwoveland I am sorry what does arr do? Is it similar to gets? I just need an input string – Shaili Parikh Jun 03 '15 at 06:36
  • `arr` is just the name of an arbitrary array. If I asked, how would you determine the number of elements contained in an array `arr` (or `a` or `array`...), you would answer, `arr.size`. By contrast, `gets` is a method. – Cary Swoveland Jun 03 '15 at 06:39
  • Oh ok thanks! I thought it was a method so I got confused haha. – Shaili Parikh Jun 03 '15 at 06:42
  • Reversing the order of operations should improve efficiency: `a.uniq.select { |x| a.count(x) > 1 }`. – Cary Swoveland Jun 03 '15 at 08:21
  • @CarySwoveland it is working well now. I had a question. I want the values in my input array to only range for 1 to 1000000. Is there any way to make sure that it doesn't go past it? – Shaili Parikh Jun 03 '15 at 13:30
  • I'm not sure if I understand your question. If you already have an array of numbers `arr`, you can check `arr.max` to see if any numbers exceed one million. If you are referring to entries made by the user, you could have the user enter each value of the array separately (followed by return), and write something like: `loop do; puts "Enter the next value of the array (not more than 1,000,000) followed by 'return' (or just 'return' alone if there are no more values)"; val = gets.chomp; break if val.empty?; val = val.to_i; if val > 1_000_000, puts "Value is too large" else arr << val; end`. – Cary Swoveland Jun 03 '15 at 18:38

5 Answers5

5

How I wish we had a built-in method Array#difference:

class Array
  def difference(other)
    h = other.tally
    reject { |e| h[e] > 0 && h[e] -= 1 }
  end
end

though @user123's answer is more straightforward. (Array#difference is probably the more efficient of the two, as it avoids the repeated invocations of count.) See my answer here for a description of the method and links to its use.

In a nutshell, it differs from Array#- as illustrated in the following example:

a = [1,2,3,4,3,2,4,2]
b = [2,3,4,4,4]

a - b          #=> [1]
a.difference b #=> [1, 3, 2, 2]

For the present problem, if:

arr = [1,2,3,4,3,4]

the duplicate elements are given by:

arr.difference(arr.uniq).uniq
  #=> [3, 4]
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
4

For your first problem, you need to uniq function like

array.select{ |x| array.count(x) > 1}.uniq

For your second problem, when you receive a value using array = [gets] it would receive your entire sequence of array numbers as a single string, so everything would be stored in a[0] like ["1, 2 3 4\n"].

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
RAJ
  • 898
  • 7
  • 16
1
puts "Enter array"
array = gets.chomp.split(",").map(&:to_i)
if array.uniq.length == array.length
  puts "array does not contain duplicates"
else
  puts "array does contain duplicates"
  print array.select{ |x| array.count(x) > 1}.uniq
end

copy this code in ruby file and try to run using

ruby file_name.rb

Vrushali Pawar
  • 3,753
  • 1
  • 13
  • 22
0

Coming to your 'gets' problem,

When you are doing a gets, your are basically getting a string as an input but not an array.

2.2.0 :001 > array = [gets]
1,2,1,4,1,2,3
 => ["1,2,1,4,1,2,3\n"]

See the above example, how the ruby interpreter took all your elements as a single string and put it in an array as a single array element. So you need to explicitly convert the input to an array with comma as a delimiter. The below will address both your questions.

array = gets.chomp
array = array.split(',').map(&:to_i)
if array.uniq.length == array.length
  puts "array does not contain duplicates"
else
  puts "array does contain duplicates"
  print array.select{ |x| array.count(x) > 1}.uniq!
end
Sri Harsha Kappala
  • 3,339
  • 26
  • 23
  • 30
0

Classical method

   array = [1,2,2,3,4,5,5,5,56,7,8,2,1,3]
   duplicates = []

    0.upto(array.size-1) do |i|
    
       (i+1).upto (array.size-1) do |j|
          if(array[i] == array [j])
            duplicates.push(array[i])
          end
       end
    end

    puts "duplicates=> #{duplicates}"
ruud
  • 743
  • 13
  • 22