timeit

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

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

Решение на Аритметични изрази от Димо Дрънгов

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

Към профила на Димо Дрънгов

Резултати

  • 9 точки от тестове
  • 0 бонус точки
  • 9 точки общо
  • 18 успешни тест(а)
  • 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
class BaseExpression:
    pass


class Constant(BaseExpression):
    def __init__(self, value):
        self.value = value

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

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


def create_constant(value):
    return Constant(value)


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

    def __str__(self):
        return self.name

    def evaluate(self, **kwargs):
        if self.name in kwargs:
            self.value = kwargs[self.name]
        return self.value


def create_variable(name):
    return Variable(name)


class Operator:
    def __init__(self, name, func):
        self.name = name
        self.func = func

    def __str__(self):
        return self.name


operators = {}


def create_operator(name, func):
    if name in operators:
        operators[name].func = func
    else:
        operators[name] = Operator(name, func)
    return operators[name]


def find_variables(expr, result):
    if isinstance(expr, Variable) and expr.name not in result:
        result += expr.name
    elif isinstance(expr, Expression):
        find_variables(expr.expr1, result)
        find_variables(expr.expr2, result)
    return result


class Expression(BaseExpression):
    def __init__(self, expr):
        if isinstance(expr[0], tuple):
            self.expr1 = Expression(expr[0])
        else:
            self.expr1 = expr[0]
        self.oper = expr[1]
        if isinstance(expr[2], tuple):
            self.expr2 = Expression(expr[2])
        else:
            self.expr2 = expr[2]
        self.variable_names = find_variables(self, [])

    def __str__(self):
        return '({} {} {})'.format(self.expr1, self.oper, self.expr2)

    def evaluate(self, **kwargs):
        if isinstance(self.expr1, BaseExpression):
            expr1_value = self.expr1.evaluate(**kwargs)
        else:
            expr1_value = self.expr1
        if isinstance(self.expr2, BaseExpression):
            expr2_value = self.expr2.evaluate(**kwargs)
        else:
            expr2_value = self.expr2
        return operators[self.oper.name].func(expr1_value, expr2_value)


def create_expression(ex):
    return Expression(ex)


def rev_args(func):
    def new_func(self, other):
        return func(other, self)
    return new_func


def plus(self, other):
    if '+' not in operators:
        create_operator('+', lambda a, b: a+b)
    return Expression((self, operators['+'], other))


def minus(self, other):
    if '-' not in operators:
        create_operator('-', lambda a, b: a-b)
    return Expression((self, operators['-'], other))


def mult(self, other):
    if '*' not in operators:
        create_operator('*', lambda a, b: a*b)
    return Expression((self, operators['*'], other))


def div(self, other):
    if '/' not in operators:
        create_operator('/', lambda a, b: a/b)
    return Expression((self, operators['/'], other))


BaseExpression.__add__ = plus
BaseExpression.__sub__ = minus
BaseExpression.__mul__ = mult
BaseExpression.__truediv__ = div
BaseExpression.__radd__ = rev_args(plus)
BaseExpression.__rsub__ = rev_args(minus)
BaseExpression.__rmul__ = rev_args(mult)
BaseExpression.__rtruediv__ = rev_args(div)

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

................E..
======================================================================
ERROR: test_variables_and_constants_extra_operators (test.TestNativeOperators)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/data/rails/pyfmi-2016/releases/20160307095126/lib/language/python/runner.py", line 67, in thread
    raise result
TypeError: unsupported operand type(s) for ** or pow(): 'Variable' and 'Variable'

----------------------------------------------------------------------
Ran 19 tests in 0.117s

FAILED (errors=1)

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

Димо обнови решението на 17.03.2016 12:49 (преди над 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
class Constant:
    def __init__(self, value):
        self.value = value

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

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

    def __setattr__(self, prop, val):
        if prop == 'value' and getattr(self, prop, False) == False:
            super().__setattr__(prop, val)


def create_constant(value):
    return Constant(value)


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

    def __str__(self):
        return self.name

    def evaluate(self, **kwargs):
        if self.name in kwargs:
            self.value = kwargs[self.name]
        return self.value


def create_variable(name):
    return Variable(name)


class Operator:
    def __init__(self, name, func):
        self.name = name
        self.func = func

    def __str__(self):
        return self.name


operators = {'+': Operator('+', lambda a, b: a+b),
             '-': Operator('-', lambda a, b: a-b),
             '*': Operator('*', lambda a, b: a*b),
             '/': Operator('/', lambda a, b: a/b)}


def create_operator(name, func):
    if name in operators:
        operators[name].func = func
    else:
        operators[name] = Operator(name, func)
    return operators[name]


def find_variables(expr, res):
    if isinstance(expr, Variable) and expr.name not in res:
        res += expr.name
    elif isinstance(expr, Expression):
        find_variables(expr.expr1, res)
        find_variables(expr.expr2, res)
    return res


def is_evaluable(ex):
    if(isinstance(ex, Variable) or isinstance(ex, Constant) or
       isinstance(ex, Expression)):
        return True
    return False


class Expression:
    def __init__(self, expr):
        if isinstance(expr[0], tuple):
            self.expr1 = Expression(expr[0])
        else:
            self.expr1 = expr[0]
        self.oper = expr[1]
        if isinstance(expr[2], tuple):
            self.expr2 = Expression(expr[2])
        else:
            self.expr2 = expr[2]
        self.variable_names = find_variables(self, [])

    def __str__(self):
        return '({} {} {})'.format(self.expr1, self.oper, self.expr2)

    def evaluate(self, **kwargs):
        if is_evaluable(self.expr1):
            res1 = self.expr1.evaluate(**kwargs)
        else:
            res1 = self.expr1
        if is_evaluable(self.expr2):
            res2 = self.expr2.evaluate(**kwargs)
        else:
            res2 = self.expr2
        return operators[self.oper.name].func(res1, res2)


def create_expression(ex):
    return Expression(ex)


def plus(self, other):
    if '+' not in operators:
        create_operator('+', lambda a, b: a+b)
    return Expression((self, operators['+'], other))


def rplus(self, other):
    return plus(other, self)


def minus(self, other):
    if '-' not in operators:
        create_operator('-', lambda a, b: a-b)
    return Expression((self, operators['-'], other))


def rminus(self, other):
    return minus(other, self)


def mult(self, other):
    if '*' not in operators:
        create_operator('*', lambda a, b: a*b)
    return Expression((self, operators['*'], other))


def rmult(self, other):
    return mult(other, self)


def div(self, other):
    if '/' not in operators:
        create_operator('/', lambda a, b: a/b)
    return Expression((self, operators['/'], other))


def rdiv(self, other):
    return div(other, self)


Variable.__add__ = Constant.__add__ = Expression.__add__ = plus
Variable.__sub__ = Constant.__sub__ = Expression.__sub__ = minus
Variable.__mul__ = Constant.__mul__ = Expression.__mul__ = mult
Variable.__truediv__ = Constant.__truediv__ = Expression.__truediv__ = div
Variable.__radd__ = Constant.__radd__ = Expression.__radd__ = rplus
Variable.__rsub__ = Constant.__rsub__ = Expression.__rsub__ = rminus
Variable.__rmul__ = Constant.__rmul__ = Expression.__rmul__ = rmult
Variable.__rtruediv__ = Constant.__rtruediv__ = Expression.__rtruediv__ = rdiv
  • Constant.__setattr__ ти е напълно излишен. Също така сравнявай с False, използвайки оператора is.

  • res е лошо име за променлива

  • Направил едни оператори да са едни и същи за Variable, Constant и Expression. Имаш случай, в който те интересува дали дадено име на сочи към едно от тези трите (isinstance(ex, Variable) or isinstance(ex, Constant) or isinstance(ex, Expression)) и проверката не изглежда особено добре. Това си плаче за базов клас :)

Димо обнови решението на 17.03.2016 17:21 (преди над 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
class BaseExpression:
    pass


class Constant(BaseExpression):
    def __init__(self, value):
        self.value = value

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

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


def create_constant(value):
    return Constant(value)


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

    def __str__(self):
        return self.name

    def evaluate(self, **kwargs):
        if self.name in kwargs:
            self.value = kwargs[self.name]
        return self.value


def create_variable(name):
    return Variable(name)


class Operator:
    def __init__(self, name, func):
        self.name = name
        self.func = func

    def __str__(self):
        return self.name


operators = {}


def create_operator(name, func):
    if name in operators:
        operators[name].func = func
    else:
        operators[name] = Operator(name, func)
    return operators[name]


def find_variables(expr, result):
    if isinstance(expr, Variable) and expr.name not in result:
        result += expr.name
    elif isinstance(expr, Expression):
        find_variables(expr.expr1, result)
        find_variables(expr.expr2, result)
    return result


class Expression(BaseExpression):
    def __init__(self, expr):
        if isinstance(expr[0], tuple):
            self.expr1 = Expression(expr[0])
        else:
            self.expr1 = expr[0]
        self.oper = expr[1]
        if isinstance(expr[2], tuple):
            self.expr2 = Expression(expr[2])
        else:
            self.expr2 = expr[2]
        self.variable_names = find_variables(self, [])

    def __str__(self):
        return '({} {} {})'.format(self.expr1, self.oper, self.expr2)

    def evaluate(self, **kwargs):
        if isinstance(self.expr1, BaseExpression):
            expr1_value = self.expr1.evaluate(**kwargs)
        else:
            expr1_value = self.expr1
        if isinstance(self.expr2, BaseExpression):
            expr2_value = self.expr2.evaluate(**kwargs)
        else:
            expr2_value = self.expr2
        return operators[self.oper.name].func(expr1_value, expr2_value)


def create_expression(ex):
    return Expression(ex)


def rev_args(func):
    def new_func(self, other):
        return func(other, self)
    return new_func


def plus(self, other):
    if '+' not in operators:
        create_operator('+', lambda a, b: a+b)
    return Expression((self, operators['+'], other))


def minus(self, other):
    if '-' not in operators:
        create_operator('-', lambda a, b: a-b)
    return Expression((self, operators['-'], other))


def mult(self, other):
    if '*' not in operators:
        create_operator('*', lambda a, b: a*b)
    return Expression((self, operators['*'], other))


def div(self, other):
    if '/' not in operators:
        create_operator('/', lambda a, b: a/b)
    return Expression((self, operators['/'], other))


BaseExpression.__add__ = plus
BaseExpression.__sub__ = minus
BaseExpression.__mul__ = mult
BaseExpression.__truediv__ = div
BaseExpression.__radd__ = rev_args(plus)
BaseExpression.__rsub__ = rev_args(minus)
BaseExpression.__rmul__ = rev_args(mult)
BaseExpression.__rtruediv__ = rev_args(div)