LINUX.ORG.RU

Питон, генератор списков.

 ,


0

1

В догонку к предыдущей теме:python, учеба, списки.
сделал такой код:

range(len(
def reverse_roman(text):
    roman_dict = {'I': 1, 'V':5, 'X':10, 'L':50,
     'C':100, 'D':500, 'M':1000}

    numbers = [roman_dict[ch] for ch in text]

    for n in range(len(numbers) - 1):
        if numbers[n] < numbers[n + 1]:
            numbers[n] = -numbers[n]

    return sum(numbers)
Вопрос. Как переписать цикл (и стоит ли) в генератор sum(и т.д.)?



Последнее исправление: masterdilly (всего исправлений: 7)

Я не знаток римской системы исчисления, но разве такая запись XXC не должна означать 80? Если должна, то твой код не работает.

Aswed ★★★★★
()
Ответ на: комментарий от Aswed

Я не знаток римской системы исчисления, но разве такая запись XXC не должна означать 80? Если должна, то твой код не работает.

Нет, по-моему, такая запись вообще не является корректной. Вычитать можно только одну цифру, а 80 будет LXXX. По-хорошему, надо, наверное, этот случай проверять и выбрасывать исключение.

proud_anon ★★★★★
()
for n in xrange(len(numbers)-1): # просто range() в python3

или

for n, _ in enumerate(numbers[:-1]):
MyTrooName ★★★★★
()
Последнее исправление: MyTrooName (всего исправлений: 1)

Ну если вычитание может быть только одного символа, тогда количество итераций по спискам можно сократить с трех до одной.

acc  = roman_dict[text[0]]
last = acc
for n in text[1:]:
    n = roman_dict[n]
    acc += n - last*2 if n > last else n
    last = n
return acc

Aswed ★★★★★
()
Ответ на: комментарий от vvn_black

убрал, действительно не нужно, работает без него.

masterdilly
() автор топика
Ответ на: комментарий от MyTrooName

str = str[len(roman):] # питон - говно

боюсь представить что тебе тут не нравится, обычный срез. Кроме того что тут затирается buildin функция. Но это твой косяк, которому нет прощения

Dred ★★★★★
()
Ответ на: комментарий от MyTrooName

Зачем столько циклов? )

ROMAN = {
    'M': 1000, 'CM': 900, 'D': 500, 'CD': 400, 'C': 100, 'XC': 90,
    'L': 50, 'XL': 40, 'X': 10, 'IX': 9, 'V': 5, 'IV': 4, 'I': 1
}


def from_roman(roman):
    res = 0
    i = 0
    while i < len(roman):
        try:
            res += ROMAN[roman[i: i + 2]]
            i += 2
        except KeyError:
            res += ROMAN[roman[i]]
            i += 1
    return res

vvn_black ★★★★★
()
Ответ на: комментарий от masterdilly

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

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

Я читал, только не программировал (так, треугольник нарисовать).

masterdilly
() автор топика
Ответ на: комментарий от vvn_black

Зачем столько циклов? )

твой вариант распарсит «IVX». я сначала кидал ValueError, если строка читалась не до конца, но выкинул

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

Нет, потому, что так не писали (хотя мы не знаем) римляне ;)

masterdilly
() автор топика
Ответ на: комментарий от MyTrooName

Проверил, имеет место такая проблема. Получается, надо откусывать от списка? А можно тогда это делать с конца? Чтобы использовать pop()?

masterdilly
() автор топика
Ответ на: комментарий от MyTrooName

Ага, действительно, косяк.

def from_roman(roman):
    res = []
    i = 0
    r = 0
    while i < len(roman):
        try:
            r = ROMAN[roman[i: i + 2]]
            i += 2
        except KeyError:
            r = ROMAN[roman[i]]
            i += 1
        if res and r > res[-1]:
            raise ValueError
        res.append(r)
    return sum(res)
vvn_black ★★★★★
()
Ответ на: комментарий от masterdilly

Проверил, имеет место такая проблема. Получается, надо откусывать от списка? А можно тогда это делать с конца? Чтобы использовать pop()?

«IL» - недопустимая комбинация. список всех допустимых комбинаций в моем примере есть. там есть определенная закономерность, но поскольку список короткий, проще перечислить все комбинации явно.

твой вариант тоже можно доработать, но это будет сложнее; и не исключено, что после нескольких упрощений он в итоге превратится в мой

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

Да, да... Тоесть получается, надо всё время с начала рассматривать. А можно смотреть с конца? чтобы выталкивать из списка значения, а не создавать срез?

masterdilly
() автор топика
Ответ на: комментарий от vvn_black

ага. он на IVIVIVIV и IIIIIIII дает ValueError. в отличие от. )

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

Как-то так, но с оговоркой 3.6+

https://repl.it/Ja0u/3

ROMAN = {
    'M': 1000, 'CM': 900, 'D': 500, 'CD': 400, 'C': 100, 'XC': 90,
    'L': 50, 'XL': 40, 'X': 10, 'IX': 9, 'V': 5, 'IV': 4, 'I': 1
}


def from_roman(roman):
    res = 0
    i = 0
    while i < len(roman):
        try:
            res += ROMAN[roman[i: i + 2]]
            i += 2
        except KeyError:
            try:
                res += ROMAN[roman[i]]
                i += 1
            except KeyError:
                raise ValueError
    assert to_roman(res) == roman
    return res


def to_roman(number):
    """ """
    assert number >= 1
    res = ''
    for k, v in ROMAN.items():
        while number >= v:
            res += k
            number -= v
    return res
vvn_black ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.