Home > Blockchain >  How to find same characters in two random strings? (Ruby)
How to find same characters in two random strings? (Ruby)

Time:12-06

I am busy working through some problems I have found on the net and I feel like this should be simple but I am really struggling.

Say you have the string 'AbcDeFg' and the next string of 'HijKgLMnn', I want to be able to find the same characters in the string so in this case it would be 'g'.

Perhaps I wasn't giving enough information - I am doing Advent of Code and I am on day 3. I just need help with the first bit which is where you are given a string of characters - you have to split the characters in half and then compare the 2 strings. You basically have to get the common character between the two. This is what I currently have:

file_data = File.read('Day_3_task1.txt')
arr = file_data.split("\n")

finals = []
arr.each do |x|
  len = x.length
  divided_by_two = len / 2
  second = x.slice!(divided_by_two..len).split('')
  first = x.split('')
  count = 0
  (0..len).each do |z|
    first.each do |y|
      if y == second[count]
        finals.push(y)
      end
    end
    count  = 1
  end 
end

finals = finals.uniq

Hope that helps in terms of clarity :)

CodePudding user response:

Did you try to convert both strings to arrays with the String#char method and find the intersection of those arrays? Like this:

string_one = 'AbcDeFg'.chars
string_two = 'HijKgLMnn'.chars
string_one & string_two # => ["g"]

CodePudding user response:

One way to do that is to use the method String#scan with the regular expression

rgx = /(.)(?!.*\1.*_)(?=.*_.*\1)/

I'm not advocating this approach. I merely thought some readers might find it interesting.

Suppose

str1 = 'AbcDgeFg'
str2 = 'HijKgLMnbn'

Now form the string

str = "#{str1}_#{str2}"
  #=> "AbcDeFg_HijKgLMnbn"

I've assumed the strings contain letters only, in which case they are separated in str with any character other than a letter. I've used an underscore. Naturally, if the strings could contain underscores a different separator would have to be used.

We then compute

str.scan(rgx).flatten
  #=> ["b", "g"]

Array#flatten is needed because

str.scan(rgx)
  #=>[["b"], ["g"]]

The regular expression can be written in free-spacing mode to make it self-documenting:

rgx =
  /
  (.)    # match any character, same to capture group 1
  (?!    # begin a negative lookahead
    .*   # match zero or more characters 
    \1   # match the contents of capture group 1
    .*   # match zero or more characters 
    _    # match an underscore
  )      # end the negative lookahead
  (?=    # begin a positive lookahead
    .*   # match zero or more characters 
    _    # match an underscore
    .*   # match zero or more characters 
    \1   # match the contents of capture group 1
  )      # end the positive lookahead
  /x     # invoke free-spacing regex definition mode

Note that if a character appears more than once in str1 and at least once in str2 the negative lookahead ensures that only the last one in str1 is matched, to avoid returning duplicates.


Alternatively, one could write

str.gsub(rgx).to_a

The uses the (fourth) form of String#gsub which takes a single argument and no block and returns an enumerator.

  • Related