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:

Google billboard
Google billboard that appeared in 2004 at several places in the USA: Silicon Valley, Cambridge (Massachusetts), Seattle and Austin (Texas).

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.

Assignment

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:

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:

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$$

Example

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