An entertaining curiosity that has nothing to do with the actual assignment. In 2004 a mysterious billboard appeared in Silicon Valley, Cambridge (Massachusetts), Seattle and Austin (Texas). It read:
Most people know that the mathematical constant $$e$$ (2.718281828…) is the base of natural logarithms1, but searching for a 10-digit prime string is a considerable task. Luckily, the first such string (7427466391) in $$e$$ already starts at position 101:
2.718281828459045235360287471352662497757247093699959574966967627724076630353
547594571382178525166427427466391932003059921817413596629043572900334295260
595630738132328627943490763233829880753195251019011573834187930702154089149
934884167509244761460668082264800168477411853742345442437107539077744992069
551702761838606261331384583000752044933826560297606737113200709328709127443
Solvers who went to 7427466391.com2 found an even more difficult problem to solve. But solving that led them to a page at Google Labs … inviting them to submit a resume.
An interval $$[l, u]$$ with $$l \leq u$$ is an abbreviation for the collection of all integers $$n$$ for which $$l \leq n \leq u$$. As such, the interval $$[19, 25]$$ represents the collection $$\{19, 20, 21, 22, 23, 24, 25\}$$. We represent an interval as a list (list) or a tuple (tuple) with two integers $$l, u \in \mathbb{Z}$$ (int), where $$l \leq u$$.
We represent an integer collection as a list (list), a tuple (tuple) or a set (set) containing integers (int) and/or intervals. It is allowed that an integer appears more than once in a collection, that an integer from a collection belongs to an interval from the collection, and that an interval from a collection overlaps with another interval from the collection. As such, the collection
$$\{33, [27, 30], 32, 25, [20, 24], 31, 19\}$$
and the collection
$$\{19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33\}$$
represent the same integer collection.
The normal form of an integer collection is represented as a list (list) containing integers (int) and/or intervals, and must meet the following conditions:
as many integers as possible are contained in an interval
intervals group as many integers as possible
integers and intervals are listed in increasing order
intervals are represented as a list (list) with two integers (int)
intervals containing a single integer ($$[n, n]$$) are represented as the integer $$n$$ (int)
These conditions on the normal form yield a unique representation for the integer collection. The two integer collections that were used as an example above, have the following normal form
$$[[19, 25], [27, 33]]$$
Define a class Collection that can be used to represent integer collections. An integer collection must be passed when creating a collection (Collection). If the argument passed does not represent a valid integer collection, an AssertionError must be raised with the message invalid collection. In addition, the class must support at least the following methods, that take no arguments:
The method numbers must return a set (set) containing all integers (int) in the collection.
The method normal_form must return the normal form (list) of the integer collection.
If a collection $$c$$ (Collection) is passed to the built-in function len, the function must return the number (int) of integers in collection $$c$$. If a collection $$c$$ (Collection) is passed to the built-in function str, the function must return a string representation (str) of the normal form of collection $$c$$. If a collection $$c$$ (Collection) is passed to the built-in function repr, the function must return a string (str) containing a Python expression that creates a new collection (Collection) from the normal form of collection $$c$$.
Make sure the following operations yield a new collection (Collection) when they operate on two collections (Collection):
operator | example | description |
---|---|---|
- | $$A$$ - $$B$$ | collection with all integers that occur in collection $$A$$ but not in collection $$B$$ |
& | $$A$$ & $$B$$ | collection with all integers that occur in collection $$A$$ and in collection $$B$$ |
| | $$A$$ | $$B$$ | collection with all integers that occur in collection $$A$$ or in collection $$B$$, or in both collections |
^ | $$A$$ ^ $$B$$ | collection with all integers that occur in collection $$A$$ or in collection $$B$$, but not in both collections |
Make sure the following Boolean operations are interpreted in the following way when they operate on two collections (Collection):
operator | example | description |
---|---|---|
< | $$A$$ < $$B$$ | checks if all integers in collection $$A$$ also occur in collection $$B$$, and that collection $$B$$ contains at least one extra integer |
<= | $$A$$ <= $$B$$ | checks if all integers in collection $$A$$ also occur in collection $$B$$ |
== | $$A$$ == $$B$$ | checks if collections $$A$$ and $$B$$ contain the same integers |
!= | $$A$$ != $$B$$ | checks if collections $$A$$ and $$B$$ do not contain the same integers |
> | $$A$$ > $$B$$ | checks if all integers in collection $$B$$ also occur in collection $$A$$, and that collection $$A$$ contains at least one extra integer |
>= | $$A$$ >= $$B$$ | checks if all integers in collection $$B$$ also occur in collection $$A$$ |
>>> A = Collection([33, [27, 30], 32, 25, [20, 24], 31, 19])
>>> A.numbers()
{19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33}
>>> len(A)
14
>>> A.normal_form()
[[19, 25], [27, 33]]
>>> print(A)
[[19, 25], [27, 33]]
>>> A
Collection([[19, 25], [27, 33]])
>>> B = Collection([22, 26, 30])
>>> A - B
Collection([[19, 21], [23, 25], [27, 29], [31, 33]])
>>> B - A
Collection([26])
>>> A | B
Collection([[19, 33]])
>>> A & B
Collection([22, 30])
>>> A ^ B
Collection([[19, 21], [23, 29], [31, 33]])
>>> C = Collection([[1, 5], [7, 7]])
>>> D = Collection([[1, 5], [7, 8]])
>>> C == Collection([1, 2, 3, 4, 5, 7])
True
>>> C == D
False
>>> C != D
True
>>> C < D
True
>>> C <= D
True
>>> C > D
False
>>> C >= D
False
>>> D > C
True
>>> D >= C
True