Решение анаграммы Хакеранка в ruby - PullRequest
1 голос
/ 28 января 2020
def anagram(s)
  counter = 0

  if s.length.even?
    splitter = s.chars.each_slice(s.length / 2).map(&:join)
    left = splitter[0]
    right = splitter[1]
    return 0 if right == left

    counter = left.length

    leftchar = left.split
    rightchar = right.split

    rightchar.each do |n|
      leftchar.each do |m|
        counter -= 1 while n == m
      end
    end
    counter
  else
    return -1
  end
end

Здравствуйте, я пытаюсь решить проблему в Hackerank в ruby. Программа должна вернуть количество символов, которые должны быть изменены в строке, которая была разделена, чтобы соответствовать другой строке. То есть, если само слово не является анаграммой.

Пока:

  • Сначала я проверяю, является ли строка хотя бы первой, прежде чем разбить строку на две части, в противном случае программа должна вернуть -1.
  • Далее, после разбиения строки, я пытаюсь проверить, не может ли присутствовать символ в правой строке, отсутствующий в левой строке. И так как моя программа должна возвращать количество символов, которое необходимо изменить, для каждого символа, найденного слева, присутствует справа, я минус один из длины слева.

Вот так мои логики c является. Но я, кажется, что-то упускаю. Есть ли какие-либо предложения и хедз-ап я могу получить от этого? Спасибо.

1 Ответ

1 голос
/ 29 января 2020

Одним из многих способов сделать это является следующее.

def min_nbr_swaps(str)
  return -1 unless str.size.even?
  half = str.size/2
  str1 = str[0,half]
  str2 = str[half,half] 
  h = str2.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 }
  str1.each_char.count do |c|
    case h[c]
    when 0
      true
    else
      h[c] -= 1
      false
    end
  end
end

min_nbr_swaps('aaabbb')   #=>  3
min_nbr_swaps('ab')       #=>  1
min_nbr_swaps('abc')      #=> -1
min_nbr_swaps('mnop')     #=>  2
min_nbr_swaps('xyyx')     #=>  0 
min_nbr_swaps('xaxbbbxx') #=>  1

Шаги следующие.

str = 'xaxbbbxx'

str.size.even?
  #=> 8.even? => true, so do not return -1
half = str.size/2
  #=> 4 
str1 = str[0,half]
  #=> "xaxb" 
str2 = str[half,half] 
  #=> "bbxx" 
h = str2.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 }

Используется форма Ха sh :: new , которая принимает аргумент, называемый значением по умолчанию. Все это означает, что когда парсер Ruby расширяется h[c] += 1 до

h[c] = h[c] + 1

h[c] справа, возвращается значение по умолчанию h, 0, если h не имеет ключ c. Например, когда h пусто,

h['x'] = h['x'] + 1 #=> 0 + 1 => 1
h['x'] = h['x'] + 1 #=> 1 + 1 => 2

h не имеет ключа 'x' в первом выражении, поэтому h[c] справа возвращает значение по умолчанию, 0 тогда как h имеет этот ключ во втором выражении, поэтому значение по умолчанию не применяется.

Продолжение,

enum = str1.each_char
  #=> #<Enumerator: "xaxb":each_char> 

Теперь мы используем метод Enumerable # count для определения количества символов в str1, которые необходимо изменить.

enum.count do |c|
  case h[c]
  when 0
    true
  else
    h[c] -= 1
    false
  end
end
  #=> 4

Первый элемент, переданный в блок count, - str1[0] #=> 'x'.

c = 'x'

При h['x'] #=> 2 оператор case выполняет

h['x'] -= 1

и возвращает false, что означает, что x изменять не нужно. Теперь h #=> {"b"=>2, "x"=>1}

Далее переменной блока присваивается значение str1[1] #=> 'a':

c = 'a'

Как h['a'] #=> 0, оператор case возвращает true, что означает a необходимо изменить. Здесь h[a] возвращает значение по умолчанию , 0, поскольку h не имеет ключа a. h не изменяется.

Остальные вычисления аналогичны, все возвращают false. count возвращает 1, поскольку блок возвращает true только для 1 из 4 символов в str1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...