Last active
December 21, 2015 10:18
-
-
Save lambda-fairy/6290775 to your computer and use it in GitHub Desktop.
Count the number of comparisons performed by a program
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
A simple mixin that counts the number of comparisons performed. Each | |
class it is mixed into keeps its own counter, which can be retrieved and | |
reset at whim. The code is written generically, and will work with any | |
orderable type. | |
In the COSC122 (first year computer science) course at the University of | |
Canterbury, one of the assignments is to implement a binary search. To | |
verify the algorithm, students have to manually increment a counter | |
every time they compare two values. This is annoying and error-prone, | |
and distracts from the purpose of the task. | |
This proposes a novel approach to the problem, by bumping the counter | |
automatically. | |
For an example, see the end of this module. | |
By Lambda Fairy (github.com/lfairy). Released into the public domain. | |
""" | |
import sys | |
if sys.version_info < (3, 0): | |
raise RuntimeError('This module only works under Python 3') | |
class Counter: | |
_counters = {} | |
@classmethod | |
def _reset(cls): | |
cls._counters[id(cls)] = 0 | |
@classmethod | |
def _get(cls): | |
return cls._counters.get(id(cls), 0) | |
@classmethod | |
def _increment(cls): | |
cls._counters[id(cls)] = 1 + cls._get() | |
def __lt__(self, other): | |
self._increment() | |
return super().__lt__(other) | |
def __gt__(self, other): | |
self._increment() | |
return super().__gt__(other) | |
def __le__(self, other): | |
self._increment() | |
return super().__le__(other) | |
def __ge__(self, other): | |
self._increment() | |
return super().__ge__(other) | |
def __eq__(self, other): | |
self._increment() | |
return super().__eq__(other) | |
if __name__ == '__main__': | |
# Mix everything together | |
class CountingInt(Counter, int): # Counter must come first | |
pass | |
# Create a list of values | |
import random | |
data = [CountingInt(x) for x in range(16)] | |
random.shuffle(data) | |
# Sort it | |
CountingInt._reset() | |
data.sort() | |
print('Sorting required', CountingInt._get(), 'comparisons') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment