Страницы

Поиск по вопросам

суббота, 11 января 2020 г.

Определить: сколько раз последовательность меняет знак?

#python


import random

x=0
for i in range(7):
    for j in range(2):
        a=random.randint(-15,15)
        print(a, end=' ')
        if a<0 : x+=1
    print()

    print("Отрицательных чисел:", x)


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


Ответы

Ответ 1



Лучше разделить код, который генерирует случайные числа, от кода, который считает перемены знака: def count_sign_reversals(numbers): it = iter(numbers) sign = next(it, 0) < 0 count = 0 for n in it: if sign is not (n < 0): count += 1 sign = not sign # sign changed return count Пример: >>> import random >>> count_sign_reversals(random.randint(-15, 15) for _ in range(7*2)) 8 # one of possible answers >>> count_sign_reversals([1, -2, 3]) 2 >>> count_sign_reversals([1, -2]) 1 >>> count_sign_reversals([-1, 2]) 1 >>> count_sign_reversals([-1, -2]) 0 >>> count_sign_reversals([1, 2]) 0 >>> count_sign_reversals([1]) 0 >>> count_sign_reversals([]) 0 Если хочется 0 и -0.0 различать, то можно отфильтровать через math.copysign(): from functools import partial numbers = map(partial(math.copysign, 1), numbers)

Ответ 2



Самый простой, да и надежный путь - наивное решение со счетчиком и циклом. Но это не наш метод. Для начала текст, потом код. Возьмем вот такой массив как пример: [-3, -4, 5, -5, 0, 3, -3] и оставим вместо самих чисел только их знак: 1 для положительных, -1 для отрицательных: [-1, -1, 1, -1, 1, 1, -1]. Теперь будем брать последовательно два рядом стоящих числа (их знака). Вот так будет выглядеть последовательность: -3, -4 (-1, -1); -4, 5 (-1, 1); 5, -5 (1, -1); -5, 0 (-1, 1); 0, 3 (1, 1); 3, -3 (1, -1). Таких пар чисел будет ровно len(list) - 1, т.е. длина списка минус 1. Представьте, что все числа положительны. Тогда сумма всех пар знаков (т.е. единиц) будет равна (len(list) - 1) * 2. Хорошо, если вы не просто поверите на слово, а проверите данный тезис. Каждая пара чисел с разными знаками уменьшает сумму на 2. Обозначим сумму этих пар знаков как summ и исходя из всего вышесказанного количество смен знаков будет равно ((len(list) - 1) * 2 - summ) / 2. Распишем сумму как сумму элементов массива с индексами: summ := |a0 + a1| + |a1 + a2| + |a2 + a3| + |a3 + a4| + |a4 + a5| + |a5 + a6|, где |...| - это модуль числа. На этом в общем-то и все: import random # Все, что касается знаков спихиваем на библиотеку # Ибо можно попасть на всякие нехорошие вещи типа -0.0, nan, -nan и т.д. # Однако copysign вычисляет в процессе арктангенс(!!!) от числа и нельзя сказать, что # это очень быстро. Для ультра быстроты можно поиграть с битовыми сдвигами from math import copysign LIST_LEN = 7 target_list = [random.randint(-15, 15) for _ in range(LIST_LEN)] only_ones_list = [copysign(1, element) for element in target_list] summ = 0 for i in range(len(only_ones_list) - 1): summ += abs(only_ones_list[i] + only_ones_list[i + 1]) sign_change_count = ((len(only_ones_list) - 1) * 2 - summ) / 2 print(target_list) print(only_ones_list) print(sign_change_count) >>> [-6, 12, -3, -11, -12, -13, 7] >>> [-1, 1, -1, -1, -1, -1, 1] >>> 3.0 Список из знаков можно не составлять, конечно же, а сразу пройти по исходному. Теперь самое сложное - чем данное может быть полезным. Во-первых, никаких рассуждений о знаковости нуля или nan или еще чего угодно. Мы используем стандартную функцию и не паримся. Теоретически можно обойтись совсем без условных операторов (внутри abs и copysign) - получение знака и модуль числа можно попробовать вычислить хитрыми битовыми операциями. Также теоретически сложение быстрее, чем умножение, однако разница будет заметна на больших массивах.

Ответ 3



Если два числа имеют разные знаки - их произведение отрицательно В этом смысле 0 обрабатывается корректно, он не меняет знак независимо от того положительно или отрицательно предыдущее число, т.к. сам ноль знака не имеет. Правда неясно, меняет ли знак последовательность (-1, 0, +1). С одной стороны ни одна пара соседних элементов не имеет разного знака, с другой - есть и положительные и отрицательные элементы. def count(l): prev = 0 r = 0 for value in l: r += 1 if prev * value < 0 else 0 prev = value if value != 0 else prev return r print count([-1, 0, 1, -1, 0, 0, 0, 2, 0, -1]) # -> 4 Так последовательность (-1,0,+1) даст результат 1. Если внутри цикла вместо prev = value if value != 0 else prev написать prev = value - посчитает число пар соседних элементов с разными знаками. (Ни пара 0, -1 ни пара 0, +1 разного знака не имеют). Вообще вместо prev * value < 0 можно написать явно (prev > 0 and value < 0) or (prev < 0 and value > 0) будет просто более громоздко. Зато можно будет считать 0 и положительным и отрицательным меняя соответствующие неравенства на >=.

Комментариев нет:

Отправить комментарий