Aufgabenstellung

  1. Lade die Datei secret.dat herunter. Sie enthält viele Zeilen, in denen jeweils zwei Zahlen stehen. Jedes Paar von Zahlen stellt eine Koordinate (x, y) dar, an der ein “Treffer” gelandet ist. Summiert man alle Treffer für jede Koordinate und stellt das Ergebnis als Bild dar, ergibt sich eine “geheime Botschaft”. (Die Koordinate (0, 0) ist oben links)

    Beispiel:

    0 0
    1 0
    0 1
    1 0
    0 0
    1 0

    Ergibt folgendes “Bild” von 2x2 Pixeln:

    2 3   (0, 0) (1, 0)
    1 0   (0, 1) (1, 1)
  1. Ein solches Bild kann man im PGM-Format darstellen. Schreibe folgenden Inhalt in eine Datei bild.pgm und öffne sie mit einem Bildbetrachtungsprogramm, um das PGM-Format zu verstehen.

    P2
    2 2
    3
    2 3
    1 0
  1. Schreibe ein Programm in Python 3, das eine solches Bild im PGM-Format aus der Datei secret.dat erzeugt.

Hilfestellung: Benutze folgende Datei secret.py mit leeren Funktionen als Vorlage. Die enthaltenen Docstrings zeigen, wie die Funktionen sich verhalten sollten.

def parse_point(line):
    """Return a tuple (x, y) from a line containing the numbers "<x> <y>".

    >>> parse_point('17 23')
    (17, 23)
    """
    pass  # ersetze durch eigenen Code

def count_hits(points):
    """Return a dictionary containing for each point how often it occurs.

    >>> points = [(1, 2), (5, 8), (1, 2), (6, 3)]
    >>> counts = count_hits(points)
    >>> counts[(1, 2)]
    2
    >>> counts[(5, 8)]
    1
    """
    pass  # ersetze durch eigenen Code

def scale_counts(counts):
    """Scale the counts such that the maximum value is 255.

    >>> scaled = scale_counts({(1, 1): 100, (2, 2): 50})
    >>> scaled[(1, 1)]
    255
    >>> scaled[(2, 2)]
    127
    """
    pass  # ersetze durch eigenen Code

def read_hits(f):
    """Return a list of points (x, y) contained in the open file f."""
    pass  # ersetze durch eigenen Code

def format_row(counts, row, columns):
    """Take the counts at the given row number (y) and return a string giving
    the count at each column (x), assuming the given number of columns.

    >>> counts = {(1, 2): 3, (2, 2): 7, (3, 1): 5}
    >>> format_row(counts, row=1, columns=4)
    '0 0 0 5'
    >>> format_row(counts, row=2, columns=4)
    '0 3 7 0'
    """
    pass  # ersetze durch eigenen Code

def print_pgm_header(columns, rows):
    """Print the PGM header.

    >>> print_pgm_header(columns=10, rows=5)
    P2
    10 5
    255
    """
    pass  # ersetze durch eigenen Code

Benutze doctest, um zu prüfen, dass alle Funktionen richtig implementiert sind. Am Ende sollte folgendes Skript funktionieren:

if __name__ == '__main__':
    import sys
    hits = read_hits(sys.stdin)
    counts = count_hits(hits)
    scaled = scale_counts(counts)
    print_pgm_header(columns=31, rows=13)
    for row in range(13):
        print(format_row(scaled, row, columns=31))

Es sollte von der Shell aus so zu benutzen sein:

$ python3 secret.py <secret.dat >secret.pgm