## Preoblikovanje tabel

Tabele imajo metodo `reshape`: podamo ji terko z novo obliko tabele, pa vrnejo matriko v tej, novi obliki. Nova oblika mora imeti enako število elementov kot stara. (Obe tabeli si v resnici delita isti pomnilnik, le različen pogled imata nanj).

    import numpy as np

    a = np.arange(12)

    a

    array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

    a.reshape(4, 3)

    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11]])

    a.reshape(2, 3, 2)

    array([[[ 0,  1],
            [ 2,  3],
            [ 4,  5]],

           [[ 6,  7],
            [ 8,  9],
            [10, 11]]])

    a.reshape((6, 2))

    array([[ 0,  1],
           [ 2,  3],
           [ 4,  5],
           [ 6,  7],
           [ 8,  9],
           [10, 11]])

Seveda lahko preoblikujemo tudi tabele, ki niso enodimenzionalne.

    a = np.array([[5, 4, 1, 8],
                  [3, 0, 7, 0],
                  [9, 6, 3, 4]])

    a.reshape((4, 3))

    array([[5, 4, 1],
           [8, 3, 0],
           [7, 0, 9],
           [6, 3, 4]])

Eno dimenzijo lahko `numpy` izračuna sam. Katero, povemo tako, da na onem mestu podamo `-1`.

    b = a.reshape((2, -1, 2))
    b

    array([[[5, 4],
            [1, 8],
            [3, 0]],

           [[7, 0],
            [9, 6],
            [3, 4]]])

    b.shape

    (2, 3, 2)

To je posebej uporabno, kadar za matriko ne vemo vnaprej, kako velika bo. Če vemo, da bo imela štiri stolpce in bi radi združili ničtega in drugega v en stolpec, prvega in tretjega pa v drugi stolpec, napišemo

    a.reshape((-1, 2))

    array([[5, 4],
           [1, 8],
           [3, 0],
           [7, 0],
           [9, 6],
           [3, 4]])

Primerjajte to z `a`, ki ima v ničtem in drugem stolpcu (slučajno) soda, v prvem in tretjem pa liha števila.

    a

    array([[5, 4, 1, 8],
           [3, 0, 7, 0],
           [9, 6, 3, 4]])

Mimogrede in malenkost povezano s tem: število elementov matrike izvemo s

    a.size

    12

Seveda je `a.size` enak

    np.prod(a.shape)

    12

## Naloga

Naloga bode naloga 5, Hydrothermal Venture.

Prijetno lahka je. Da bo res tako, vam podarjam funkcijo `anyrange`.

    def anyrange(a, b):
        return np.arange(a, b + 1) if b >= a else np.arange(a, b - 1, -1)

Podobna je funkciji `range`, vendar vključuje obe meji in ji je vseeno, katera je večja.

    anyrange(5, 10)

    array([ 5,  6,  7,  8,  9, 10])

    anyrange(10, 5)

    array([10,  9,  8,  7,  6,  5])

Tule je še branje datoteke.

    import re

    lines = np.array([[int(x) for x in re.findall(r"\d+", v)]
                      for v in open("example.txt")])

Kdor pozna regularne izraze, to itak zna; kdor jih ne, naj mu bo tole prihranjeno.

Zdaj pa uživajte v preprosti nalogi. Edina zanka, ki jo še napišete, naj gre čez `lines`. Vse ostalo bodo učinkovito uporabljeni indeksi (ne pozabite na funkcijo `anyrange`!), seštevanje in vsote.

Kako dobimo elemente večje od 1? Ne pozabite, da je `True` isto kot `1` in `False` isto kot `0`.

Da ne bo koga zmedlo: `reshape` v resnici skoraj ne potrebujemo. Samo jagoda na vrhu kupe je.