timeit

Програмиране с Python

Курс във Факултета по Математика и Информатика към СУ

Решение на Аритметични изрази от Бисер Кръстев

Обратно към всички решения

Към профила на Бисер Кръстев

Резултати

  • 1 точка от тестове
  • 1 отнета точка
  • 0 точки общо
  • 1 успешни тест(а)
  • 18 неуспешни тест(а)

Код

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
from numbers import Number


class Expressible(object):
    def __add__(self, other):
        return create_expression((self, ADD, other))

    def __sub__(self, other):
        return create_expression((self, SUB, other))

    def __mul__(self, other):
        return create_expression((self, MUL, other))

    def __truediv__(self, other):
        return create_expression((self, DIV, other))

    def __floordiv__(self, other):
        return create_expression((self, FDIV, other))

    def __mod__(self, other):
        return create_expression((self, MOD, other))


class Const(Expressible):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return str(self.value)

    def evaluate(self, **var):
        return self.value


class Variable(Expressible):
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return str(self.name)

    def evaluate(self, **var):
        return var[self.name]


class Operator(object):
    def __init__(self, symbol, function):
        self.name = symbol
        self.value = function

    def __str__(self):
        return self.name

    def apply(self, lhs, rhs):
        return self.value(lhs, rhs)

    def evaluate(self, lhs, rhs):
        return apply(lhs, rhs)


class Expression(Expressible):
    def __init__(self, structure):
        self.value = structure

    def __str__(self):
        return "expr"

    def _throw(self, exp, got):
        left = str(exp)
        right = type(got).__name__
        raise Exception("Expected {}, got {}".format(left, right))

    @property
    def variable_names(self):
        return self._names(self.value)

    def _names(self, struct):
        if isinstance(struct, (int, long, float, complex)):
            return list()
        if type(struct) is Const:
            return list()
        if type(struct) is Operator:
            return list()
        if type(struct) is Variable:
            return [struct.name]

        names = list()
        for item in struct:
            names.extend(self._names(item))

        return names

    def evaluate(self, **var):
        return self._eval(self.value, **var)

    def _eval(self, struct, **var):
        def unwrap(item):
            if isinstance(item, (int, long, float, complex)):
                return item
            if type(item) is Expression:
                return item.evaluate(**var)
            if type(item) is Const:
                return item.evaluate(**var)
            if type(item) is Variable:
                return item.evaluate(**var)
            if type(item) is tuple:
                return self._eval(item, **var)
            self._throw("const/var/tuple", item)

        state = 0
        lhs = None
        op = None
        rhs = None

        for item in struct:
            if type(item) is Operator:
                if state == 1:
                    op = item
                    state = 2
                else:
                    self._throw("op", item)
            else:
                if state == 0:
                    lhs = unwrap(item)
                    state = 1
                elif state == 2:
                    rhs = unwrap(item)
                    lhs = op.apply(lhs, rhs)
                    state = 1

        return lhs


def create_constnat(value):
    return Const(value)


def create_variable(name):
    return Variable(name)


def create_operator(symbol, function):
    return Operator(symbol, function)


def create_expression(structure):
    return Expression(structure)


ADD = create_operator('+', lambda lhs, rhs: lhs + rhs)
SUB = create_operator('-', lambda lhs, rhs: lhs - rhs)
MUL = create_operator('*', lambda lhs, rhs: lhs * rhs)
DIV = create_operator('/', lambda lhs, rhs: lhs / rhs)
FDIV = create_operator('//', lambda lhs, rhs: lhs // rhs)
MOD = create_operator('%', lambda lhs, rhs: lhs % rhs)

Лог от изпълнението

EEEEEEEEEEEEEEEEE.E
======================================================================
ERROR: test_constant_and_right_hand_side_literal (test.TestArithmeticsWithLiterals)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_create_expression_with_literal (test.TestArithmeticsWithLiterals)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_left_hand_side_literal_and_constant (test.TestArithmeticsWithLiterals)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_left_hand_side_literal_and_variable (test.TestArithmeticsWithLiterals)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_string_conversion_with_literals (test.TestArithmeticsWithLiterals)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_variable_and_right_hand_side_literal (test.TestArithmeticsWithLiterals)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_constants (test.TestConstants)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 21, in setUp
    self.three = solution.create_constant(3)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_string_conversion (test.TestConstants)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 21, in setUp
    self.three = solution.create_constant(3)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_both_nested_operands (test.TestExpressionObjects)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_deep_expression (test.TestExpressionObjects)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_deep_string_conversion (test.TestExpressionObjects)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_evaluate_with_extra_kwargs (test.TestExpressionObjects)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_one_nested_operand (test.TestExpressionObjects)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_simple_addition (test.TestExpressionObjects)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_simple_string_conversion (test.TestExpressionObjects)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_variables_and_constants_arithmetics (test.TestNativeOperators)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_variables_and_constants_extra_operators (test.TestNativeOperators)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/d20160322-5045-1apjirt/test.py", line 36, in setUp
    self.two = solution.create_constant(2)
AttributeError: module 'solution' has no attribute 'create_constant'

======================================================================
ERROR: test_variables (test.TestVariables)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/data/rails/pyfmi-2016/releases/20160307095126/lib/language/python/runner.py", line 67, in thread
    raise result
NameError: name 'long' is not defined

----------------------------------------------------------------------
Ran 19 tests in 0.047s

FAILED (errors=18)

История (1 версия и 2 коментара)

Бисер обнови решението на 18.03.2016 11:24 (преди над 1 година)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
from numbers import Number


class Expressible(object):
    def __add__(self, other):
        return create_expression((self, ADD, other))

    def __sub__(self, other):
        return create_expression((self, SUB, other))

    def __mul__(self, other):
        return create_expression((self, MUL, other))

    def __truediv__(self, other):
        return create_expression((self, DIV, other))

    def __floordiv__(self, other):
        return create_expression((self, FDIV, other))

    def __mod__(self, other):
        return create_expression((self, MOD, other))


class Const(Expressible):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return str(self.value)

    def evaluate(self, **var):
        return self.value


class Variable(Expressible):
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return str(self.name)

    def evaluate(self, **var):
        return var[self.name]


class Operator(object):
    def __init__(self, symbol, function):
        self.name = symbol
        self.value = function

    def __str__(self):
        return self.name

    def apply(self, lhs, rhs):
        return self.value(lhs, rhs)

    def evaluate(self, lhs, rhs):
        return apply(lhs, rhs)


class Expression(Expressible):
    def __init__(self, structure):
        self.value = structure

    def __str__(self):
        return "expr"

    def _throw(self, exp, got):
        left = str(exp)
        right = type(got).__name__
        raise Exception("Expected {}, got {}".format(left, right))

    @property
    def variable_names(self):
        return self._names(self.value)

    def _names(self, struct):
        if isinstance(struct, (int, long, float, complex)):
            return list()
        if type(struct) is Const:
            return list()
        if type(struct) is Operator:
            return list()
        if type(struct) is Variable:
            return [struct.name]

        names = list()
        for item in struct:
            names.extend(self._names(item))

        return names

    def evaluate(self, **var):
        return self._eval(self.value, **var)

    def _eval(self, struct, **var):
        def unwrap(item):
            if isinstance(item, (int, long, float, complex)):
                return item
            if type(item) is Expression:
                return item.evaluate(**var)
            if type(item) is Const:
                return item.evaluate(**var)
            if type(item) is Variable:
                return item.evaluate(**var)
            if type(item) is tuple:
                return self._eval(item, **var)
            self._throw("const/var/tuple", item)

        state = 0
        lhs = None
        op = None
        rhs = None

        for item in struct:
            if type(item) is Operator:
                if state == 1:
                    op = item
                    state = 2
                else:
                    self._throw("op", item)
            else:
                if state == 0:
                    lhs = unwrap(item)
                    state = 1
                elif state == 2:
                    rhs = unwrap(item)
                    lhs = op.apply(lhs, rhs)
                    state = 1

        return lhs


def create_constnat(value):
    return Const(value)


def create_variable(name):
    return Variable(name)


def create_operator(symbol, function):
    return Operator(symbol, function)


def create_expression(structure):
    return Expression(structure)


ADD = create_operator('+', lambda lhs, rhs: lhs + rhs)
SUB = create_operator('-', lambda lhs, rhs: lhs - rhs)
MUL = create_operator('*', lambda lhs, rhs: lhs * rhs)
DIV = create_operator('/', lambda lhs, rhs: lhs / rhs)
FDIV = create_operator('//', lambda lhs, rhs: lhs // rhs)
MOD = create_operator('%', lambda lhs, rhs: lhs % rhs)
  • Изрично сме казали да очаквате валиден вход. Нямаш нужда от тези изключения.
  • Имплементацията ти на _eval е страшно сложна. Опрости малко.
  • Можеш да опростиш if isinstance(item, (int, long, float, complex)) като използваш numbers.Number. Всички числа в Python са негови наследници, именно поради тази причина.
  • Винаги предпочитай isinstance пред type при такива проверки. В реда на нещата е някой да дефинира наследници на твоите типове и не е нужно да чупиш държанието им.
  • Const не е непременно лошо име, но е единственото съкращение измежду класовете в решението ти, което го прави неконсистентно. Или съкрати всички или преименувай този клас на Constant. Аз бих избрал второто.