At the core of our sock drawer implementation is a fundamental data structure which, for some reason, does not come standard in programming languages: a dictionary that has numerical values (and arbitrary keys). A number is a number. An array, or vector, is a list of numbers that can be indexed by their position in the vector. An arithmetic dictionary is a set of numbers that can be addressed by their associated key. Just as numbers, and arrays, can be combined via +, -, *, /, and compared with >,<, etc, so can arithmetic dictionaries. Let us start defining them. For brevity, we call them simply AD rather than ArithmeticDictionary. We note that Python includes, in the collections module, the cCounter class, which supports addition. ADs are a more general version of the counter class, as they support (or you can make them to support) all math operations you wish. In Python, to be able to have two ADs d1 and d2 and compute their sum via the syntax di + d2,We need to define the_add_ operation, and similarly for the other arithmetic operations. There is a fine point to be discussed. Arrays can be combined with arithmetical operations only when they are of the same dimensions, or when one can be "broadcast" to fit the dimension of the other. For dictionaries, however, the restriction to be able to combine only arithmetic dictionaries with the same keys would be too restrictive. If we have an AD d representing a sock drawer, and we want to add to it one yellow and two blue socks, we want to be able to write something like: d +- AD({'yellow": 1, 'blue': 2}) rather than worry that d might have different keys from {yellow', 'blue'}. Thus, in the definition of an operation, we will need to define suitable defaults for the missing values. In general, the suitable defaults are the neutral elements with respect to the operation: 0 for + and –, and 1 for X and /. Let us begin from addition and subtraction.

Database System Concepts
7th Edition
ISBN:9780078022159
Author:Abraham Silberschatz Professor, Henry F. Korth, S. Sudarshan
Publisher:Abraham Silberschatz Professor, Henry F. Korth, S. Sudarshan
Chapter1: Introduction
Section: Chapter Questions
Problem 1PE
icon
Related questions
Question
100%

Question 2, please.

Returns a pair consisting of the max value in the AD, and of the set of keys that attain that value.

 

In the implementation above, we have factored together what would have been the common part of the implementation of + and – in the
method _binary_op. The _binary_op method is a static method: it does not refer to a specific object. In this way, we can decide separately
what to provide to it as the left and right hand sides; this will be useful later, as we shall see. To call it, we have to refer to it via AD._binary_op
rather than self._binary_op,as would be the case for a normal (object) method. Furthermore, in the _binary_op method, we do not have
access to self, since self refers to a specific object, while the method is generic, defined for the class.
The _binary_op method combines values from its 1left and right operands using operator op, and the default neutral if a value is not
found. The two operands left and right are interpreted as dictionaries if they are a subclass of dict, and are interpreted as constants
otherwise.
We have defined our class AD as a subclass of the dictionary class dict. This enables us to apply to an AD all the methods that are defined for
a dictionary, which is really quite handy.
[] d1 = AD()
d1['red'] = 2
print(d1)
d2 = AD({'blue': 4, 'green': 5})
print(d2)
In the code above, note how we can write d1['red']:our ability to access ADs via the square-bracket notation is due to the fact that ADs, like
dictionaries, implement thegetitem method. Note also that AD inherits from dict even the initializer methods, so that we can pass to our
dictionary another dictionary, and obtain an AD that contains a copy of that dictionary.
We can see that addition and subtraction also work:
[] print(AD(red=2, green=3) + AD(red=1, blue=4))
print(AD(red=2, green=3) - AD (red=1, blue=4))
We let multiplication and division to you to implement. You need to implement the operators:
mul_
_truediv
floordiv_
[] ### Question 1: Implement multiplication and division
_mul
def ad_mul(self, other):
# Define
# YOUR CODE HERE
AD._mul
ad_mul
# Define below _truediv_, similarly.
# YOUR CODE HERE
# And finally, define below_floordiv_, for INTEGER division.
# YOUR CODE HERE
We will let you also implement max_items and min_items properties. The value of these properties should be a pair, consisting of the
maximum/minimum value, and of the set of keys that led to that value. The latter needs to be a set, because there are multiple key, value pairs
where the value is maximal or minimal. To avoid wasting your time, we will have you implement only the max_items property. If the AD is empty,
the property's value should be the pair (None, set()).
[] ### Question 2: Implement `max_items
def ad_max_items (self):
"*"Returns a pair consisting of the max value in the AD, and of the
set of keys that attain that value. This can be done in 7 lines of code."""
# YOUR CODE HERE
# Remember the use of the property decorator.
AD.max_items = property(ad_max_items)
[] ### Tests for `max_items
# For empty ADs, it has to return None as value, and the empty set as key set.
check_equal (AD() - max_items, (None, set()))
# Case of one maximum.
check_equal(AD(red=2, green=3, blue=1).max_items, (3, {'green'}))
# Case of multiple maxima.
check_equal (AD(red=2, yellow=3, blue=3, violet=3, pink=1).max_items,
(3, {'yellow', 'blue', 'violet'}))
Transcribed Image Text:In the implementation above, we have factored together what would have been the common part of the implementation of + and – in the method _binary_op. The _binary_op method is a static method: it does not refer to a specific object. In this way, we can decide separately what to provide to it as the left and right hand sides; this will be useful later, as we shall see. To call it, we have to refer to it via AD._binary_op rather than self._binary_op,as would be the case for a normal (object) method. Furthermore, in the _binary_op method, we do not have access to self, since self refers to a specific object, while the method is generic, defined for the class. The _binary_op method combines values from its 1left and right operands using operator op, and the default neutral if a value is not found. The two operands left and right are interpreted as dictionaries if they are a subclass of dict, and are interpreted as constants otherwise. We have defined our class AD as a subclass of the dictionary class dict. This enables us to apply to an AD all the methods that are defined for a dictionary, which is really quite handy. [] d1 = AD() d1['red'] = 2 print(d1) d2 = AD({'blue': 4, 'green': 5}) print(d2) In the code above, note how we can write d1['red']:our ability to access ADs via the square-bracket notation is due to the fact that ADs, like dictionaries, implement thegetitem method. Note also that AD inherits from dict even the initializer methods, so that we can pass to our dictionary another dictionary, and obtain an AD that contains a copy of that dictionary. We can see that addition and subtraction also work: [] print(AD(red=2, green=3) + AD(red=1, blue=4)) print(AD(red=2, green=3) - AD (red=1, blue=4)) We let multiplication and division to you to implement. You need to implement the operators: mul_ _truediv floordiv_ [] ### Question 1: Implement multiplication and division _mul def ad_mul(self, other): # Define # YOUR CODE HERE AD._mul ad_mul # Define below _truediv_, similarly. # YOUR CODE HERE # And finally, define below_floordiv_, for INTEGER division. # YOUR CODE HERE We will let you also implement max_items and min_items properties. The value of these properties should be a pair, consisting of the maximum/minimum value, and of the set of keys that led to that value. The latter needs to be a set, because there are multiple key, value pairs where the value is maximal or minimal. To avoid wasting your time, we will have you implement only the max_items property. If the AD is empty, the property's value should be the pair (None, set()). [] ### Question 2: Implement `max_items def ad_max_items (self): "*"Returns a pair consisting of the max value in the AD, and of the set of keys that attain that value. This can be done in 7 lines of code.""" # YOUR CODE HERE # Remember the use of the property decorator. AD.max_items = property(ad_max_items) [] ### Tests for `max_items # For empty ADs, it has to return None as value, and the empty set as key set. check_equal (AD() - max_items, (None, set())) # Case of one maximum. check_equal(AD(red=2, green=3, blue=1).max_items, (3, {'green'})) # Case of multiple maxima. check_equal (AD(red=2, yellow=3, blue=3, violet=3, pink=1).max_items, (3, {'yellow', 'blue', 'violet'}))
- Arithmetic Dictionaries
At the core of our sock drawer implementation is a fundamental data structure which, for some reason, does not come standard in
programming languages: a dictionary that has numerical values (and arbitrary keys).
A number is a number. An array, or vector, is a list of numbers that can be indexed by their position in the vector. An arithmetic dictionary is a set
of numbers that can be addressed by their associated key. Just as numbers, and arrays, can be combined via +, -, *, /, and compared with >, <,
etc, so can arithmetic dictionaries. Let us start defining them. For brevity, we call them simply AD rather than ArithmeticDictionary. We note that
Python includes, in the collections module, the Counter class, which supports addition. ADs are a more general version of the Counter class,
as they support (or you can make them to support) all math operations you wish.
In Python, to be able to have two ADs d1 and d2 and compute their sum via the syntax d1 + d2, we need to define the _add_ 0peration, and
similarly for the other arithmetic operations.
There is a fine point to be discussed. Arrays can be combined with arithmetical operations only when they are of the same dimensions, or when
one can be "broadcast" to fit the dimension of the other. For dictionaries, however, the restriction to be able to combine only arithmetic
dictionaries with the same keys would be too restrictive. If we have an AD d representing a sock drawer, and we want to add to it one yellow
and two blue socks, we want to be able to write something like:
d += AD({'yellow": 1, 'blue': 2})
rather than worry that d might have different keys from {'yellow', 'blue'}. Thus, in the definition of an operation, we will need to define suitable
defaults for the missing values. In general, the suitable defaults are the neutral elements with respect to the operation: 0 for + and –, and 1 for
x and /
Let us begin from addition and subtraction.
[] class AD(dict):
def _init_(self, *args, **kwargs):
"*"This initializer simply passes all arguments to dict, so that
we can create an AD with the same ease with which we can create
There is no need, indeed, to repeat the initializer,
but we leave it here in case we like to create attributes specific
a dict.
of an AD later."""
super ()._init_(*args, **kwargs)
def _add_(self, other):
return AD._binary_op(self, other, lambda x, y: x + y, e)
def _sub_(self, other):
return AD. binary_op(self, other, lambda x, y: x - y, e)
@staticmethod
def _binary_op(left, right, op, neutral):
r = AD()
1_keys = set(left.keys()) if isinstance(left, dict) else set()
r_keys = set(right.keys()) if isinstance(right, dict) else set()
for k in 1_keys | r_keys:
# If the right (or left) element is a dictionary (or an AD),
# we get the elements from the dictionary; else we use the right
# or left value itself. This implements a sort of dictionary
# broadcasting.
1_val = left.get(k, neutral) if isinstance(left, dict) else left
r_val = right.get (k, neutral) if isinstance(right, dict) else right
r[k] = op(1_val, r_val)
return r
In the implementation above, we have factored together what would have been the common part of the implementation of + and – in the
method _binary_op. The _binary_op method is a static method: it does not refer to a specific object. In this way, we can decide separately
what to provide to it as the left and right hand sides; this will be useful later, as we shall see. To call it, we have to refer to it via AD._binary_op
rather than self._binary_op,as would be the case for a normal (object) method. Furthermore, in the _binary_op method, we do not have
access to self, since self refers to a specific object, while the method is generic, defined for the class.
The _binary_op method combines values from its left and right operands using operator op, and the default neutral if a value is not
found. The two operands left and right are interpreted as dictionaries if they are a subclass of dict, and are interpreted as constants
otherwise.
We have defined our class AD as a subclass of the dictionary class dict. This enables us to apply to an AD all the methods that are defined for
a dictionary, which is really quite handy.
[] d1 = AD()
d1['red'] = 2
print(d1)
d2 = AD({'blue': 4, 'green': 5})
print(d2)
In the code above, note how we can write d1['red']: our ability to access ADs via the square-bracket notation is due to the fact that ADs, like
dictionaries, implement the _getitem_ method. Note also that AD inherits from dict even the initializer methods, so that we can pass to our
dictionary another dictionary, and obtain an AD that contains a copy of that dictionary.
We can see that addition and subtraction also work:
[ ] print(AD(red=2, green=3) + AD(red=1, blue=4))
print(AD(red=2, green=3) - AD (red-1, blue=4))
Transcribed Image Text:- Arithmetic Dictionaries At the core of our sock drawer implementation is a fundamental data structure which, for some reason, does not come standard in programming languages: a dictionary that has numerical values (and arbitrary keys). A number is a number. An array, or vector, is a list of numbers that can be indexed by their position in the vector. An arithmetic dictionary is a set of numbers that can be addressed by their associated key. Just as numbers, and arrays, can be combined via +, -, *, /, and compared with >, <, etc, so can arithmetic dictionaries. Let us start defining them. For brevity, we call them simply AD rather than ArithmeticDictionary. We note that Python includes, in the collections module, the Counter class, which supports addition. ADs are a more general version of the Counter class, as they support (or you can make them to support) all math operations you wish. In Python, to be able to have two ADs d1 and d2 and compute their sum via the syntax d1 + d2, we need to define the _add_ 0peration, and similarly for the other arithmetic operations. There is a fine point to be discussed. Arrays can be combined with arithmetical operations only when they are of the same dimensions, or when one can be "broadcast" to fit the dimension of the other. For dictionaries, however, the restriction to be able to combine only arithmetic dictionaries with the same keys would be too restrictive. If we have an AD d representing a sock drawer, and we want to add to it one yellow and two blue socks, we want to be able to write something like: d += AD({'yellow": 1, 'blue': 2}) rather than worry that d might have different keys from {'yellow', 'blue'}. Thus, in the definition of an operation, we will need to define suitable defaults for the missing values. In general, the suitable defaults are the neutral elements with respect to the operation: 0 for + and –, and 1 for x and / Let us begin from addition and subtraction. [] class AD(dict): def _init_(self, *args, **kwargs): "*"This initializer simply passes all arguments to dict, so that we can create an AD with the same ease with which we can create There is no need, indeed, to repeat the initializer, but we leave it here in case we like to create attributes specific a dict. of an AD later.""" super ()._init_(*args, **kwargs) def _add_(self, other): return AD._binary_op(self, other, lambda x, y: x + y, e) def _sub_(self, other): return AD. binary_op(self, other, lambda x, y: x - y, e) @staticmethod def _binary_op(left, right, op, neutral): r = AD() 1_keys = set(left.keys()) if isinstance(left, dict) else set() r_keys = set(right.keys()) if isinstance(right, dict) else set() for k in 1_keys | r_keys: # If the right (or left) element is a dictionary (or an AD), # we get the elements from the dictionary; else we use the right # or left value itself. This implements a sort of dictionary # broadcasting. 1_val = left.get(k, neutral) if isinstance(left, dict) else left r_val = right.get (k, neutral) if isinstance(right, dict) else right r[k] = op(1_val, r_val) return r In the implementation above, we have factored together what would have been the common part of the implementation of + and – in the method _binary_op. The _binary_op method is a static method: it does not refer to a specific object. In this way, we can decide separately what to provide to it as the left and right hand sides; this will be useful later, as we shall see. To call it, we have to refer to it via AD._binary_op rather than self._binary_op,as would be the case for a normal (object) method. Furthermore, in the _binary_op method, we do not have access to self, since self refers to a specific object, while the method is generic, defined for the class. The _binary_op method combines values from its left and right operands using operator op, and the default neutral if a value is not found. The two operands left and right are interpreted as dictionaries if they are a subclass of dict, and are interpreted as constants otherwise. We have defined our class AD as a subclass of the dictionary class dict. This enables us to apply to an AD all the methods that are defined for a dictionary, which is really quite handy. [] d1 = AD() d1['red'] = 2 print(d1) d2 = AD({'blue': 4, 'green': 5}) print(d2) In the code above, note how we can write d1['red']: our ability to access ADs via the square-bracket notation is due to the fact that ADs, like dictionaries, implement the _getitem_ method. Note also that AD inherits from dict even the initializer methods, so that we can pass to our dictionary another dictionary, and obtain an AD that contains a copy of that dictionary. We can see that addition and subtraction also work: [ ] print(AD(red=2, green=3) + AD(red=1, blue=4)) print(AD(red=2, green=3) - AD (red-1, blue=4))
Expert Solution
trending now

Trending now

This is a popular solution!

steps

Step by step

Solved in 3 steps with 3 images

Blurred answer
Knowledge Booster
Stack
Learn more about
Need a deep-dive on the concept behind this application? Look no further. Learn more about this topic, computer-science and related others by exploring similar questions and additional content below.
Similar questions
Recommended textbooks for you
Database System Concepts
Database System Concepts
Computer Science
ISBN:
9780078022159
Author:
Abraham Silberschatz Professor, Henry F. Korth, S. Sudarshan
Publisher:
McGraw-Hill Education
Starting Out with Python (4th Edition)
Starting Out with Python (4th Edition)
Computer Science
ISBN:
9780134444321
Author:
Tony Gaddis
Publisher:
PEARSON
Digital Fundamentals (11th Edition)
Digital Fundamentals (11th Edition)
Computer Science
ISBN:
9780132737968
Author:
Thomas L. Floyd
Publisher:
PEARSON
C How to Program (8th Edition)
C How to Program (8th Edition)
Computer Science
ISBN:
9780133976892
Author:
Paul J. Deitel, Harvey Deitel
Publisher:
PEARSON
Database Systems: Design, Implementation, & Manag…
Database Systems: Design, Implementation, & Manag…
Computer Science
ISBN:
9781337627900
Author:
Carlos Coronel, Steven Morris
Publisher:
Cengage Learning
Programmable Logic Controllers
Programmable Logic Controllers
Computer Science
ISBN:
9780073373843
Author:
Frank D. Petruzella
Publisher:
McGraw-Hill Education