Найти нечетный int - Ruby Nested Loop Error - PullRequest
0 голосов
/ 09 сентября 2018

Я задавал этот вопрос в отношении кодовых войн: «Для массива найдите целое число, которое появляется нечетное число раз. Всегда будет только одно целое число, которое будет появляться нечетное количество раз».

Код:

def find_it(seq)
  int = []
  for a in seq do
    count = 0
    for b in seq do
      if a == b
        count += 1
      end
    end
    if count % 2.0 != 0
      int << b
    end
  end      
  puts int.uniq[0].to_i
end

Он был протестирован с парой входных данных, но ответы были неверны для этих двух массивов:

find_it([1,1,2,-2,5,2,4,4,-1,-2,5]) - возвращает 5 вместо -1

find_it([1,1,1,1,1,1,10,1,1,1,1]) - возвращает 1 вместо 10

Что не так с моим кодом?

Ответы [ 4 ]

0 голосов
/ 10 сентября 2018

Спасибо за подробные ответы, сейчас я перебираю ответы всех.Я новичок в Ruby, и я все еще нахожусь в процессе изучения методов / правил их использования / обозначения Big O, поэтому я очень ценю вклад каждого.Codewar перечислил несколько лучших решений.Это кажется самым быстрым на данный момент:

def find_it(seq)   
   seq.detect { |n| seq.count(n).odd? } 
end
0 голосов
/ 10 сентября 2018
def find_it(seq)
  seq.group_by{|x| x}.select{|k, v| (v.count % 2.0 !=0)}.first[0]
end

Приведенный выше код будет принимать последовательность в массиве.Здесь мы группируемся по элементам:

Например:

[1,1,2,-2,5,2,4,4,-1,-2,5].group_by{|x| x}
# => {1=>[1, 1], 2=>[2, 2], -2=>[-2, -2], 5=>[5, 5], 4=>[4, 4], -1=>[-1]}

после получения вышеуказанных результатов мы находим, что количество элементов нечетное с условием выбора.

ex:

[1,1,2,-2,5,2,4,4,-1,-2,5].group_by{|x| x}.select{|k, v| (v.count % 2.0 !=0)}

мы получим результаты как {-1=>[-1]}

мы принимаем ключ как элемент результата.

0 голосов
/ 10 сентября 2018

@ aimen_alt прав насчет вашей ошибки

но давайте разберем вашу проблему.

Во-первых, вам нужно рассчитать внешний вид каждого числа. Во-вторых, вам нужно найти тот, у которого нечетное количество появлений. В соответствии с проблемой, существует только один такой номер, поэтому вы можете вернуть его сразу.

Вы можете пойти своим путем и сделать это в O(N^2) сложности, отсканировав свою последовательность для каждого элемента в последовательности (поэтому N элементов в последовательности умножаются на размер последовательности N = N*N) , Вы можете сделать это линейно *, построив Hash, и тогда вы сможете получить ключ с нечетным значением:

def find_it(seq)
  numbers = {}
  seq.each do |item|
    numbers[item] = numbers[item].to_i + 1
  end
  numbers.select{ |k,v| v.odd? }.first.first
end

чтобы быть более идиоматическим, вы можете использовать group_by для группировки самих чисел:

seq = [1, 2, 6, 1, 2]
seq.group_by{ |item| item }
#=> {1=>[1, 1], 2=>[2, 2], 6=>[6]}

Вы можете видеть, что каждое значение является массивом, и вам просто нужно получить одно с нечетным количеством элементов:

seq = [1, 2, 6, 1, 2]
seq.group_by{ |item| item }.select{ |k, v| v.size.odd? }
#=> {6=>[6]}

И последнее, что вы хотели бы сделать, это получить значение ключа:

seq.group_by{ |item| item }.select{ |k, v| v.size.odd? }.keys.first

Итак, окончательное решение будет

def find_it(seq)
  seq.group_by{ |item| item }
     .select{ |k, v| v.size.odd? }
     .keys
     .first
end

как упомянул @pascalbetz:

def find_it(seq)
  seq.group_by{ |item| item }
     .find{ |k, v| v.size.odd? }
     .first
end
0 голосов
/ 10 сентября 2018
if count % 2.0 != 0
      int << b
    end

Проблема, с которой вы здесь сталкиваетесь, заключается в том, что вы помещаете b вместо целого в массив целых чисел, поэтому происходит то, что вместо того значения, которое вы подсчитали, вы помещаете последнее значение b, которое является последним значением элемент в массиве независимо от того, что условие счетчика является нечетным числом, хотя b и counter не имеют ничего общего друг с другом. чтобы исправить это, вы заменяете b на a, чтобы оно выдвигало проверяемое вами значение по сравнению с другими элементами во втором цикле

фикс:

if count % 2.0 != 0
      int << a
    end

похожий, но более простой код, который выполняет аналогичную работу, за исключением более короткого и понятного способа:

def find_it(seq)
  numberWithOddCount = 0
  seq.each do |currentElement|
    counter = 0
    seq.each { |elementToCompare| counter += 1 if currentElement == elementToCompare}
    numberWithOddCount = currentElement if counter % 2 != 0
  end
  numberWithOddCount
end

Просто добавили несколько битов, которые вы также можете использовать для сокращения и упрощения кода.

Счастливого кодирования!

Примечание:

Вы могли бы творчески использовать встроенные методы ruby, чтобы заставить код делать то, что вы хотите, в несколько строк (или даже в одну строку), например, то, что @iGian делал в комментариях к вопросам, но если вы все еще плохо знакомы с ruby, тогда Лучше всего использовать эти методы один за другим, изучая их, иначе вы будете сбиты с толку. Но если вы готовы потратить время на их изучение, я предлагаю вам взять его код и разделить выполнение каждого метода в отдельной строке и вывести то, что сделал каждый метод, чтобы знать, что и для чего. и практиковаться в использовании каждого отдельно.

...