# ---
# jupyter:
# jupytext:
# formats: ipynb,py:percent
# text_representation:
# extension: .py
# format_name: percent
# format_version: '1.3'
# jupytext_version: 1.14.0
# kernelspec:
# display_name: Python 3 (ipykernel)
# language: python
# name: python3
# ---
# %% [markdown] toc=true slideshow={"slide_type": "notes"}
#
Table of Contents
#
# %% [markdown] slideshow={"slide_type": "slide"}
# # Fondamenti di Programmazione
#
#
# **Andrea Sterbini**
#
# lezione 20 - 15 dicembre 2022
# %% [markdown] slideshow={"slide_type": "slide"}
# # RECAP:
# - albero di gioco del **Tris/Filetto**
# - rappresentazione
# - generazione
# - configurazioni equivalenti
# - strategie
# - rappresentazione di **espressioni algebriche**
# - calcolo
# - semplificazione
# - parsing
# %% [markdown] slideshow={"slide_type": "slide"}
# # Rotazione ricorsiva di immagini
# %%% Rotazione di una immagine quadrata di lato 2^n ricorsivamente [markdown] slideshow={"slide_type": "fragment"}
# ```| 1 |``` **resta com'è**
#
# ```
# 1 | 2
# --|--
# 3 | 4
# ```
# **diventa**
# ```
# 2 | 4
# --|--
# 1 | 3
# ```
# %%% Rotazione di una immagine quadrata di lato 2^n ricorsivamente [markdown] slideshow={"slide_type": "slide"}
# ```
# 0 1 | 2 3
# 4 5 | 6 7
# ----|----
# 8 9 | A B
# C D | E F
# ```
# **diventa**
# ```
# 3 7 | B F
# 2 6 | A E
# ----|----
# 1 5 | 9 D
# 0 4 | 8 C
# ```
# %%% Rotazione di una immagine quadrata di lato 2^n ricorsivamente [markdown] slideshow={"slide_type": "slide"}
# ## Suddivisione e rotazione ricorsiva NxN
# - se N==1: la matrice resta così (**caso base**)
# - se N>1:
# - divido in 4 sottomatrici (**riduzione**)
# - le ruoto di 90° (**chiamata ricorsiva**)
# - le scambio
# - le fondo in una matrice più grande (**composizione**)
# - a forza di dividere per 2 arrivo sempre a 1 (**convergenza**)
# %%% Rotazione di una immagine quadrata di lato 2^n ricorsivamente slideshow={"slide_type": "slide"}
# A B
# C D
def dividiP2(matrice):
"divido la matrice nei suoi 4 quadranti"
# NOTA: la matrice deve avere dimensione potenza di 2
L = len(matrice)
assert L>1 and L%2==0 # FIXME: dovrei controllare 2^n==L
metà = L//2
fascia_superiore = matrice[:metà]
fascia_inferiore = matrice[metà:]
A = [ riga[:metà] for riga in fascia_superiore ]
B = [ riga[metà:] for riga in fascia_superiore ]
C = [ riga[:metà] for riga in fascia_inferiore ]
D = [ riga[metà:] for riga in fascia_inferiore ]
return A, B, C, D
# %% slideshow={"slide_type": "slide"}
# vediamo se funziona
M = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]]
N = [[1,2],[3,4]]
##print(*dividiP2(M),sep='\n\n')
# %%% Rotazione di una immagine quadrata di lato 2^n ricorsivamente slideshow={"slide_type": "slide"}
# A B
# C D
def fondiP2(A, B, C, D):
"fondo 4 matrici in una sola"
AB = [ rigaA+rigaB for rigaA,rigaB in zip(A,B) ]
CD = [ rigaC+rigaD for rigaC,rigaD in zip(C,D) ]
return AB + CD
# %% slideshow={"slide_type": "slide"}
# test
A = [[1,2],[5,6]]
B = [[3,4],[7,8]]
C = [[9,10],[13,14]]
D = [[11,12],[15,16]]
print(*fondiP2(A,B,C,D), sep='\n')
# %%% Rotazione di una immagine quadrata di lato 2^n ricorsivamente slideshow={"slide_type": "slide"}
# A B
# C D
# B D
# A C
def ruotaP2(M):
"ruoto una matrice che ha lato 2^L"
# se N==1 la ritorno tal quale
if len(M) == 1:
return M
# la divido in 4
A, B, C, D = dividiP2(M)
# le ruoto tutte e 4
Aruotata = ruotaP2(A)
Bruotata = ruotaP2(B)
Cruotata = ruotaP2(C)
Druotata = ruotaP2(D)
# le scambio e le fondo
return fondiP2(Bruotata, Druotata, Aruotata, Cruotata)
# %% slideshow={"slide_type": "slide"}
M = [['1', '2', '3', '4'],
['5', '6', '7', '8'],
['9', 'A', 'B', 'C'],
['D', 'E', 'F', 'G']]
print(*ruotaP2(M), sep='\n')
# %%% Rotazione di una immagine quadrata di lato 2^n ricorsivamente slideshow={"slide_type": "slide"}
def ruota(M):
"generico ruota applicabile a matrici != da potenza di 2"
# allargo la matrice alla prossima potenza di 2 nelle due direzioni
W = len(M[0])
H = len(M)
i = 0
while 2**i < W:
i +=1
larghezza = 2**i
i = 0
while 2**i < H:
i +=1
altezza = 2**i
for riga in M:
riga += [(0,0,0)] * (larghezza-W)
M += [ [(0,0,0)] * larghezza for i in range(altezza-H) ]
# ruoto la matrice
ruotata = ruotaP2(M)
# elimino le righe/colonne aggiunte
ruotata = ruotata[larghezza-W:]
return [ riga[:H] for riga in ruotata ]
# %%% Esempi slideshow={"slide_type": "slide"}
# 3 7 B F
# 2 6 A E
# 1 5 9 D
# 0 4 8 C
M = [ ['0', '1', '2', ],
['4', '5', '6', ],
['8', '9', 'A', ]]
print(*ruota(M), sep='\n')
# %%% Rotazione di immagini slideshow={"slide_type": "slide"}
import images
img = images.load('scarabocchio.png')
ruotata = ruota(img)
images.save(ruotata, 'scarabocchio-90°.png')
images.visd(img), images.visd(ruotata)
# %%% Rotazione di immagini slideshow={"slide_type": "slide"}
# %%%
lenna = images.load('Lenna.png')
ruotata = ruota(lenna)
images.save(ruotata, 'Lenna-ruotata.png')
images.visd(lenna), images.visd(ruotata)
# %% BYE BYE [markdown] slideshow={"slide_type": "slide"}
# # Esercizi d'esame