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
137
138
import collections
import numbers


class Operation:

    def __init__(self, name, function):
        self.name = name
        self.function = function

    def __str__(self):
        return self.name

add = Operation('+', lambda x, y: x + y)
subtract = Operation('-', lambda x, y: x - y)
multiply = Operation('*', lambda x, y: x * y)
divide = Operation('/', lambda x, y: x / y)


class Expression:

    def __init__(self, iterable=()):
        self.iterable = iterable

    def resolve(self, expression, **kwargs):
        if isinstance(expression, collections.Iterable):
            return self.evaluate_iterable(expression, **kwargs)
        elif isinstance(expression, numbers.Number):
            return expression

        return expression.evaluate(**kwargs)

    def evaluate_iterable(self, iterable, **kwargs):
        iterator = iter(iterable)
        left = self.resolve(next(iterator), **kwargs)

        for operator in iterator:
            right = self.resolve(next(iterator), **kwargs)
            left = operator.function(left, right)

        return left

    def evaluate(self, **kwargs):
        return self.evaluate_iterable(self.iterable, **kwargs)

    def variable_names_generator(self, iterable):
        for expression in iterable:
            if isinstance(expression, Variable):
                yield expression.name
            elif isinstance(expression, Expression):
                for var_name in expression.variable_names:
                    yield var_name
            elif isinstance(expression, collections.Iterable):
                for var_name in self.variable_names_generator(expression):
                    yield var_name

    @property
    def variable_names(self):
        return tuple(set(self.variable_names_generator(self.iterable)))

    def __str__(self):
        result = '('
        for expression in self.iterable:
            if isinstance(expression, collections.Iterable):
                result += str(Expression(expression))
            elif isinstance(expression, Operation):
                result += ' ' + str(expression) + ' '
            else:
                result += str(expression)

        return result + ')'

    def __add__(self, other):
        return Expression((self, add, other))

    def __radd__(self, other):
        return Expression((other, add, self))

    def __sub__(self, other):
        return Expression((self, subtract, other))

    def __rsub__(self, other):
        return Expression((other, subtract, self))

    def __mul__(self, other):
        return Expression((self, multiply, other))

    def __rmul__(self, other):
        return Expression((other, multiply, self))

    def __truediv__(self, other):
        return Expression((self, divide, other))

    def __rtruediv__(self, other):
        return Expression((other, divide, self))


class Constant(Expression):

    def __init__(self, value):
        Expression.__init__(self)
        self.value = value

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

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


class Variable(Expression):

    def __init__(self, name):
        Expression.__init__(self, (name,))
        self.name = name

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

    def __str__(self):
        return self.name


def create_constant(constant):
    return Constant(constant)


def create_variable(var_name):
    return Variable(var_name)


def create_operator(operator_name, operator):
    return Operation(operator_name, operator)


def create_expression(iterable):
    return Expression(iterable)

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

................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.158s

FAILED (errors=1)

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

Илия обнови решението на 15.03.2016 16:01 (преди почти 2 години)

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
import collections


class Operation:

    def __init__(self, name, function):
        self.name = name
        self.function = function

    def evaluate(self, x, y):
        return self.function(x, y)

    def __str__(self):
        return self.name

Operation.plus = Operation('+', lambda x, y: x + y)
Operation.minus = Operation('-', lambda x, y: x - y)
Operation.multiply = Operation('*', lambda x, y: x * y)
Operation.divide = Operation('/', lambda x, y: x / y)


class Expression:

    def __init__(self, expression):
        self.expression = expression

    def resolve(self, expression, **kwargs):
        if isinstance(expression, collections.Iterable):
            return self.evaluate_iterable(expression, **kwargs)

        return expression.evaluate(**kwargs)

    def evaluate_iterable(self, iterable, **kwargs):
        iterator = iter(iterable)
        left = self.resolve(iterator.__next__(), **kwargs)

        for operator in iterator:
            right = self.resolve(iterator.__next__(), **kwargs)
            left = operator.evaluate(left, right)

        return left

    def evaluate(self, **kwargs):
        return self.evaluate_iterable(self.expression, **kwargs)

    def to_string(self, iterable):
        result = ''
        for expression in iterable:
            if isinstance(expression, collections.Iterable):
                result += '(' + self.to_string(expression) + ')'
            elif isinstance(expression, Operation):
                result += ' ' + str(expression) + ' '
            else:
                result += str(expression)

        return result

    @property
    def variable_names_generator(self):
        for expression in self.expression:
            if isinstance(expression, Variable):
                yield expression.name
            elif isinstance(expression, collections.Iterable):
                yield self.variable_names()

    @property
    def variable_names(self):
        return tuple(self.variable_names_generator)

    def __str__(self):
        return '(' + self.to_string(self.expression) + ')'

    def __add__(self, other):
        return Expression((self, Operation.plus, other))

    def __sub__(self, other):
        return Expression((self, Operation.minus, other))

    def __mul__(self, other):
        return Expression((self, Operation.multiply, other))

    def __div__(self, other):
        return Expression((self, Operation.divide, other))


class Constant(Expression):

    def __init__(self, value):
        self.value = value

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

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


class Variable(Expression):

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

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

    def __str__(self):
        return self.name


def create_constant(constant):
    return Constant(constant)


def create_variable(var_name):
    return Variable(var_name)


def create_operator(operator_name, operator):
    return Operation(operator_name, operator)


def create_expression(iterable):
    return Expression(iterable)

Илия обнови решението на 15.03.2016 16:03 (преди почти 2 години)

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
import collections


class Operation:

    def __init__(self, name, function):
        self.name = name
        self.function = function

    def evaluate(self, x, y):
        return self.function(x, y)

    def __str__(self):
        return self.name

Operation.plus = Operation('+', lambda x, y: x + y)
Operation.minus = Operation('-', lambda x, y: x - y)
Operation.multiply = Operation('*', lambda x, y: x * y)
Operation.divide = Operation('/', lambda x, y: x / y)


class Expression:

    def __init__(self, expression):
        self.expression = expression

    def resolve(self, expression, **kwargs):
        if isinstance(expression, collections.Iterable):
            return self.evaluate_iterable(expression, **kwargs)

        return expression.evaluate(**kwargs)

    def evaluate_iterable(self, iterable, **kwargs):
        iterator = iter(iterable)
        left = self.resolve(iterator.__next__(), **kwargs)

        for operator in iterator:
            right = self.resolve(iterator.__next__(), **kwargs)
            left = operator.evaluate(left, right)

        return left

    def evaluate(self, **kwargs):
        return self.evaluate_iterable(self.expression, **kwargs)

    def to_string(self, iterable):
        result = ''
        for expression in iterable:
            if isinstance(expression, collections.Iterable):
                result += '(' + self.to_string(expression) + ')'
            elif isinstance(expression, Operation):
                result += ' ' + str(expression) + ' '
            else:
                result += str(expression)

        return result

    @property
    def variable_names_generator(self):
        for expression in self.expression:
            if isinstance(expression, Variable):
                yield expression.name
            elif isinstance(expression, collections.Iterable):
                yield self.variable_names_generator()

    @property
    def variable_names(self):
        return tuple(self.variable_names_generator)

    def __str__(self):
        return '(' + self.to_string(self.expression) + ')'

    def __add__(self, other):
        return Expression((self, Operation.plus, other))

    def __sub__(self, other):
        return Expression((self, Operation.minus, other))

    def __mul__(self, other):
        return Expression((self, Operation.multiply, other))

    def __div__(self, other):
        return Expression((self, Operation.divide, other))


class Constant(Expression):

    def __init__(self, value):
        self.value = value

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

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


class Variable(Expression):

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

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

    def __str__(self):
        return self.name


def create_constant(constant):
    return Constant(constant)


def create_variable(var_name):
    return Variable(var_name)


def create_operator(operator_name, operator):
    return Operation(operator_name, operator)


def create_expression(iterable):
    return Expression(iterable)


Илия обнови решението на 15.03.2016 16:08 (преди почти 2 години)

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
import collections


class Operation:

    def __init__(self, name, function):
        self.name = name
        self.function = function

    def evaluate(self, x, y):
        return self.function(x, y)

    def __str__(self):
        return self.name

Operation.plus = Operation('+', lambda x, y: x + y)
Operation.minus = Operation('-', lambda x, y: x - y)
Operation.multiply = Operation('*', lambda x, y: x * y)
Operation.divide = Operation('/', lambda x, y: x / y)


class Expression:

    def __init__(self, iterable):
        self.iterable = iterable

    def resolve(self, expression, **kwargs):
        if isinstance(expression, collections.Iterable):
            return self.evaluate_iterable(expression, **kwargs)

        return expression.evaluate(**kwargs)

    def evaluate_iterable(self, iterable, **kwargs):
        iterator = iter(iterable)
        left = self.resolve(iterator.__next__(), **kwargs)

        for operator in iterator:
            right = self.resolve(iterator.__next__(), **kwargs)
            left = operator.evaluate(left, right)

        return left

    def evaluate(self, **kwargs):
        return self.evaluate_iterable(self.iterable, **kwargs)

    def to_string(self, iterable):
        result = ''
        for expression in iterable:
            if isinstance(expression, collections.Iterable):
                result += '(' + self.to_string(expression) + ')'
            elif isinstance(expression, Operation):
                result += ' ' + str(expression) + ' '
            else:
                result += str(expression)

        return result

    @property
    def variable_names_generator(self):
        for expression in self.iterable:
            if isinstance(expression, Variable):
                yield expression.name
            elif isinstance(expression, collections.Iterable):
                yield self.variable_names_generator()

    @property
    def variable_names(self):
        return tuple(self.variable_names_generator)

    def __str__(self):
        return '(' + self.to_string(self.iterable) + ')'

    def __add__(self, other):
        return Expression((self, Operation.plus, other))

    def __sub__(self, other):
        return Expression((self, Operation.minus, other))

    def __mul__(self, other):
        return Expression((self, Operation.multiply, other))

    def __div__(self, other):
        return Expression((self, Operation.divide, other))


class Constant(Expression):

    def __init__(self, value):
        self.value = value

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

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


class Variable(Expression):

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

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

    def __str__(self):
        return self.name


def create_constant(constant):
    return Constant(constant)


def create_variable(var_name):
    return Variable(var_name)


def create_operator(operator_name, operator):
    return Operation(operator_name, operator)


def create_expression(iterable):
    return Expression(iterable)

Илия обнови решението на 15.03.2016 20:19 (преди почти 2 години)

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
import collections
import numbers


class Operation:

    def __init__(self, name, function):
        self.name = name
        self.function = function

    def evaluate(self, x, y):
        return self.function(x, y)

    def __str__(self):
        return self.name

Operation.plus = Operation('+', lambda x, y: x + y)
Operation.minus = Operation('-', lambda x, y: x - y)
Operation.multiply = Operation('*', lambda x, y: x * y)
Operation.divide = Operation('/', lambda x, y: x / y)


class Expression:

    def __init__(self, iterable):
        self.iterable = iterable

    def resolve(self, expression, **kwargs):
        if isinstance(expression, collections.Iterable):
            return self.evaluate_iterable(expression, **kwargs)
        elif isinstance(expression, numbers.Number):
            return expression

        return expression.evaluate(**kwargs)

    def evaluate_iterable(self, iterable, **kwargs):
        iterator = iter(iterable)
        left = self.resolve(next(iterator), **kwargs)

        for operator in iterator:
            right = self.resolve(next(iterator), **kwargs)
            left = operator.evaluate(left, right)

        return left

    def evaluate(self, **kwargs):
        return self.evaluate_iterable(self.iterable, **kwargs)

    def to_string(self, iterable):
        result = ''
        for expression in iterable:
            if isinstance(expression, collections.Iterable):
                result += '(' + self.to_string(expression) + ')'
            elif isinstance(expression, Operation):
                result += ' ' + str(expression) + ' '
            else:
                result += str(expression)

        return result

    @property
    def variable_names_generator(self):
        for expression in self.iterable:
            if isinstance(expression, Variable):
                yield expression.name
            elif isinstance(expression, collections.Iterable):
                yield self.variable_names_generator()

    @property
    def variable_names(self):
        return tuple(self.variable_names_generator)

    def __str__(self):
        return '(' + self.to_string(self.iterable) + ')'

    def __add__(self, other):
        return Expression((self, Operation.plus, other))

    def __radd__(self, other):
        return self.__add__(other)

    def __sub__(self, other):
        return Expression((self, Operation.minus, other))

    def __rsub__(self, other):
        return self.__sub__(other)

    def __mul__(self, other):
        return Expression((self, Operation.multiply, other))

    def __rmul__(self, other):
        return self.__mul__(other)

    def __div__(self, other):
        return Expression((self, Operation.divide, other))

    def __rdiv__(self, other):
        return self.__div__(other)


class Constant(Expression):

    def __init__(self, value):
        self.value = value

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

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


class Variable(Expression):

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

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

    def __str__(self):
        return self.name


def create_constant(constant):
    return Constant(constant)


def create_variable(var_name):
    return Variable(var_name)


def create_operator(operator_name, operator):
    return Operation(operator_name, operator)


def create_expression(iterable):
    return Expression(iterable)

Илия обнови решението на 15.03.2016 20:37 (преди почти 2 години)

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
import collections
import numbers


class Operation:

    def __init__(self, name, function):
        self.name = name
        self.function = function

    def evaluate(self, x, y):
        return self.function(x, y)

    def __str__(self):
        return self.name

Operation.add = Operation('+', lambda x, y: x + y)
Operation.subtract = Operation('-', lambda x, y: x - y)
Operation.multiply = Operation('*', lambda x, y: x * y)
Operation.divide = Operation('/', lambda x, y: x / y)


class Expression:

    def __init__(self, iterable):
        self.iterable = iterable

    def resolve(self, expression, **kwargs):
        if isinstance(expression, collections.Iterable):
            return self.evaluate_iterable(expression, **kwargs)
        elif isinstance(expression, numbers.Number):
            return expression

        return expression.evaluate(**kwargs)

    def evaluate_iterable(self, iterable, **kwargs):
        iterator = iter(iterable)
        left = self.resolve(next(iterator), **kwargs)

        for operator in iterator:
            right = self.resolve(next(iterator), **kwargs)
            left = operator.evaluate(left, right)

        return left

    def evaluate(self, **kwargs):
        return self.evaluate_iterable(self.iterable, **kwargs)

    def to_string(self, iterable):
        result = ''
        for expression in iterable:
            if isinstance(expression, collections.Iterable):
                result += '(' + self.to_string(expression) + ')'
            elif isinstance(expression, Operation):
                result += ' ' + str(expression) + ' '
            else:
                result += str(expression)

        return result

    @property
    def variable_names_generator(self):
        for expression in self.iterable:
            if isinstance(expression, Variable):
                yield expression.name
            elif isinstance(expression, collections.Iterable):
                yield self.variable_names_generator()

    @property
    def variable_names(self):
        return tuple(self.variable_names_generator)

    def __str__(self):
        return '(' + self.to_string(self.iterable) + ')'

    def __add__(self, other):
        return Expression((self, Operation.add, other))

    def __radd__(self, other):
        return Expression((other, Operation.add, self))

    def __sub__(self, other):
        return Expression((self, Operation.subtract, other))

    def __rsub__(self, other):
        return Expression((other, Operation.subtract, self))

    def __mul__(self, other):
        return Expression((self, Operation.multiply, other))

    def __rmul__(self, other):
        return Expression((other, Operation.multiply, self))

    def __truediv__(self, other):
        return Expression((self, Operation.divide, other))

    def __rtruediv__(self, other):
        return Expression((other, Operation.divide, self))


class Constant(Expression):

    def __init__(self, value):
        self.value = value

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

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


class Variable(Expression):

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

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

    def __str__(self):
        return self.name


def create_constant(constant):
    return Constant(constant)


def create_variable(var_name):
    return Variable(var_name)


def create_operator(operator_name, operator):
    return Operation(operator_name, operator)


def create_expression(iterable):
    return Expression(iterable)

Илия обнови решението на 15.03.2016 23:58 (преди почти 2 години)

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
import collections
import numbers


class Operation:

    def __init__(self, name, function):
        self.name = name
        self.function = function

    def evaluate(self, x, y):
        return self.function(x, y)

    def __str__(self):
        return self.name

Operation.add = Operation('+', lambda x, y: x + y)
Operation.subtract = Operation('-', lambda x, y: x - y)
Operation.multiply = Operation('*', lambda x, y: x * y)
Operation.divide = Operation('/', lambda x, y: x / y)


class Expression:

    def __init__(self, iterable=()):
        self.iterable = iterable

    def resolve(self, expression, **kwargs):
        if isinstance(expression, collections.Iterable):
            return self.evaluate_iterable(expression, **kwargs)
        elif isinstance(expression, numbers.Number):
            return expression

        return expression.evaluate(**kwargs)

    def evaluate_iterable(self, iterable, **kwargs):
        iterator = iter(iterable)
        left = self.resolve(next(iterator), **kwargs)

        for operator in iterator:
            right = self.resolve(next(iterator), **kwargs)
            left = operator.evaluate(left, right)

        return left

    def evaluate(self, **kwargs):
        return self.evaluate_iterable(self.iterable, **kwargs)

    def to_string(self, iterable):
        result = ''
        for expression in iterable:
            if isinstance(expression, collections.Iterable):
                result += '(' + self.to_string(expression) + ')'
            elif isinstance(expression, Operation):
                result += ' ' + str(expression) + ' '
            else:
                result += str(expression)

        return result

    def variable_names_generator(self, iterable):
        for expression in iterable:
            if isinstance(expression, Variable):
                yield expression.name
            elif isinstance(expression, Expression):
                for var_name in expression.variable_names:
                    yield var_name
            elif isinstance(expression, collections.Iterable):
                yield self.variable_names_generator(expression)

    @property
    def variable_names(self):
        return tuple(set(self.variable_names_generator(self.iterable)))

    def __str__(self):
        return '(' + self.to_string(self.iterable) + ')'

    def __add__(self, other):
        return Expression((self, Operation.add, other))

    def __radd__(self, other):
        return Expression((other, Operation.add, self))

    def __sub__(self, other):
        return Expression((self, Operation.subtract, other))

    def __rsub__(self, other):
        return Expression((other, Operation.subtract, self))

    def __mul__(self, other):
        return Expression((self, Operation.multiply, other))

    def __rmul__(self, other):
        return Expression((other, Operation.multiply, self))

    def __truediv__(self, other):
        return Expression((self, Operation.divide, other))

    def __rtruediv__(self, other):
        return Expression((other, Operation.divide, self))


class Constant(Expression):

    def __init__(self, value):
        Expression.__init__(self)
        self.value = value

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

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


class Variable(Expression):

    def __init__(self, name):
        Expression.__init__(self, (name,))
        self.name = name

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

    def __str__(self):
        return self.name


def create_constant(constant):
    return Constant(constant)


def create_variable(var_name):
    return Variable(var_name)


def create_operator(operator_name, operator):
    return Operation(operator_name, operator)


def create_expression(iterable):
    return Expression(iterable)

Илия обнови решението на 16.03.2016 00:02 (преди почти 2 години)

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
import collections
import numbers


class Operation:

    def __init__(self, name, function):
        self.name = name
        self.function = function

    def evaluate(self, x, y):
        return self.function(x, y)

    def __str__(self):
        return self.name

Operation.add = Operation('+', lambda x, y: x + y)
Operation.subtract = Operation('-', lambda x, y: x - y)
Operation.multiply = Operation('*', lambda x, y: x * y)
Operation.divide = Operation('/', lambda x, y: x / y)


class Expression:

    def __init__(self, iterable=()):
        self.iterable = iterable

    def resolve(self, expression, **kwargs):
        if isinstance(expression, collections.Iterable):
            return self.evaluate_iterable(expression, **kwargs)
        elif isinstance(expression, numbers.Number):
            return expression

        return expression.evaluate(**kwargs)

    def evaluate_iterable(self, iterable, **kwargs):
        iterator = iter(iterable)
        left = self.resolve(next(iterator), **kwargs)

        for operator in iterator:
            right = self.resolve(next(iterator), **kwargs)
            left = operator.evaluate(left, right)

        return left

    def evaluate(self, **kwargs):
        return self.evaluate_iterable(self.iterable, **kwargs)

    def to_string(self, iterable):
        result = ''
        for expression in iterable:
            if isinstance(expression, collections.Iterable):
                result += '(' + self.to_string(expression) + ')'
            elif isinstance(expression, Operation):
                result += ' ' + str(expression) + ' '
            else:
                result += str(expression)

        return result

    def variable_names_generator(self, iterable):
        for expression in iterable:
            if isinstance(expression, Variable):
                yield expression.name
            elif type(expression) is Expression:
                for var_name in expression.variable_names:
                    yield var_name
            elif isinstance(expression, collections.Iterable):
                yield self.variable_names_generator(expression)

    @property
    def variable_names(self):
        return tuple(set(self.variable_names_generator(self.iterable)))

    def __str__(self):
        return '(' + self.to_string(self.iterable) + ')'

    def __add__(self, other):
        return Expression((self, Operation.add, other))

    def __radd__(self, other):
        return Expression((other, Operation.add, self))

    def __sub__(self, other):
        return Expression((self, Operation.subtract, other))

    def __rsub__(self, other):
        return Expression((other, Operation.subtract, self))

    def __mul__(self, other):
        return Expression((self, Operation.multiply, other))

    def __rmul__(self, other):
        return Expression((other, Operation.multiply, self))

    def __truediv__(self, other):
        return Expression((self, Operation.divide, other))

    def __rtruediv__(self, other):
        return Expression((other, Operation.divide, self))


class Constant(Expression):

    def __init__(self, value):
        Expression.__init__(self)
        self.value = value

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

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


class Variable(Expression):

    def __init__(self, name):
        Expression.__init__(self, (name,))
        self.name = name

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

    def __str__(self):
        return self.name


def create_constant(constant):
    return Constant(constant)


def create_variable(var_name):
    return Variable(var_name)


def create_operator(operator_name, operator):
    return Operation(operator_name, operator)


def create_expression(iterable):
    return Expression(iterable)

  • Да закачаш add, substract, multiply и divide директно като атрибути на Operate не е много яко. По-добре да са просто имена в scope-а на файла ти.
  • evaluate на Operator е малко безполезна. Можеш просто да запишеш function като evaluate или да викаш function на оператор обектите, вместо evaluate.
  • наличието на resolve, evaluate и evaluate_iterable трябва да те наведе на мисълта, че може да стане и малко по-лесно, само с един доса по-кратък метод, но може би ще трябва да промениш малко начина, по който си пазиш данните(hint: изразите, които моделираме за всъщност двоични дървета).
  • variable_names_generator и variable_names няма смисъл да съществуват отделно. Същото се отнася и за to_string и __str__.

Илия обнови решението на 20.03.2016 17:05 (преди над 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
import collections
import numbers


class Operation:

    def __init__(self, name, function):
        self.name = name
        self.function = function

    def __str__(self):
        return self.name

add = Operation('+', lambda x, y: x + y)
subtract = Operation('-', lambda x, y: x - y)
multiply = Operation('*', lambda x, y: x * y)
divide = Operation('/', lambda x, y: x / y)


class Expression:

    def __init__(self, iterable=()):
        self.iterable = iterable

    def resolve(self, expression, **kwargs):
        if isinstance(expression, collections.Iterable):
            return self.evaluate_iterable(expression, **kwargs)
        elif isinstance(expression, numbers.Number):
            return expression

        return expression.evaluate(**kwargs)

    def evaluate_iterable(self, iterable, **kwargs):
        iterator = iter(iterable)
        left = self.resolve(next(iterator), **kwargs)

        for operator in iterator:
            right = self.resolve(next(iterator), **kwargs)
            left = operator.function(left, right)

        return left

    def evaluate(self, **kwargs):
        return self.evaluate_iterable(self.iterable, **kwargs)

    def variable_names_generator(self, iterable):
        for expression in iterable:
            if isinstance(expression, Variable):
                yield expression.name
            elif isinstance(expression, Expression):
                for var_name in expression.variable_names:
                    yield var_name
            elif isinstance(expression, collections.Iterable):
                for var_name in self.variable_names_generator(expression):
                    yield var_name

    @property
    def variable_names(self):
        return tuple(set(self.variable_names_generator(self.iterable)))

    def __str__(self):
        result = '('
        for expression in self.iterable:
            if isinstance(expression, collections.Iterable):
                result += str(Expression(expression))
            elif isinstance(expression, Operation):
                result += ' ' + str(expression) + ' '
            else:
                result += str(expression)

        return result + ')'

    def __add__(self, other):
        return Expression((self, add, other))

    def __radd__(self, other):
        return Expression((other, add, self))

    def __sub__(self, other):
        return Expression((self, subtract, other))

    def __rsub__(self, other):
        return Expression((other, subtract, self))

    def __mul__(self, other):
        return Expression((self, multiply, other))

    def __rmul__(self, other):
        return Expression((other, multiply, self))

    def __truediv__(self, other):
        return Expression((self, divide, other))

    def __rtruediv__(self, other):
        return Expression((other, divide, self))


class Constant(Expression):

    def __init__(self, value):
        Expression.__init__(self)
        self.value = value

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

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


class Variable(Expression):

    def __init__(self, name):
        Expression.__init__(self, (name,))
        self.name = name

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

    def __str__(self):
        return self.name


def create_constant(constant):
    return Constant(constant)


def create_variable(var_name):
    return Variable(var_name)


def create_operator(operator_name, operator):
    return Operation(operator_name, operator)


def create_expression(iterable):
    return Expression(iterable)

Благодаря за съветите, но resolve, evaluate и evaluate_iterable не се сетих как да ги оправя. variable_names_generator също, защото ми трябва да извикам сет над резултата от функцията.

Предполагам, че след като излязат резултатите ще мога да видя от колеги как се реализира като двоично дърво.