Ziua 1 - Introducere
Autor: Miruna Zăvelcă, AI Summer School for Beginners, Bucharest Cram School 2025
Despre acest curs
Acest curs este destinat elevilor care au deja cunoștințe de bază în programare (C++, C, sau alte limbaje) și doresc să învețe Python și conceptele fundamentale ale Inteligenței Artificiale. Vom explora împreună cum se traduc conceptele pe care le cunoașteți deja (variabile, structuri de control, funcții) în sintaxa Python.
Ce vom învăța astăzi:
- Prezentare (cine sunt, cum lucrăm, ce vom face în următoarele zile)
- Sintaxa Python
- Clase și obiecte
- Prima problemă de AI: căutarea în spațiul stărilor
Introducere în Python
Variabile
Toate variabilele în Python sunt obiecte. Asta înseamnă că le puteți atribui orice valoare fără a preciza tipul de date, și chiar să actualizați valoarea unei variabile cu un tip de date diferit fără probleme:
x = 3
y = 2.15
print(x, y)
x = "abc"
print(x)
Output:
3 2.15
abc
Tipuri de date
Putem considera fiecare variabila o cutie. Cutia are un nume (x, y etc.) si un element inauntru (23, "doi" etc.). Putem vedea tipul de date folosind functia type:
x = 23
type(x)
Output: int
y = 6.3
type(y)
Output: float
z = "doi"
type(z)
Output: str
Cele mai simple tipuri de date sunt cele de mai sus: - int (integer) = numar intreg (fara virgula) - float (floating point) = numar cu virgula - char (character) = orice caracter de pe tastatura. In Python nu exista explicit, dar il avem in alte limbaje de programare - str (string) = sir de caractere. Un cuvant, un paragraf etc.
Tipul de date boolean
print(3 == 4, 3 != 4)
Output: False True
type(True)
Output: bool
| a | b | a and b | a or b |
|---|---|---|---|
| True | True | True | True |
| True | False | False | True |
| False | True | False | True |
| False | False | False | False |
Structura de decizie
if True:
print("Adevărat")
Output: Adevărat
if 4 == 4:
print("egale")
else:
print("diferite")
Output: egale
a = 9
b = 3
if a > b:
print("mai mare")
elif a < b:
print("mai mic")
else:
print("egale")
Output: mai mare
Structuri repetitive
for i in range(1, 3):
print("Happy Birthday!")
Output:
Happy Birthday!
Happy Birthday!
for i in range(1, 10, 1):
print(i, end=' ')
Output: 1 2 3 4 5 6 7 8 9
for i in range(1, 10, 2):
print(i, end=' ')
Output: 1 3 5 7 9
for i in range(10, 0, -1):
print(i, end=' ')
Output: 10 9 8 7 6 5 4 3 2 1
Liste
Listele sunt seturi ordonate de elemente și se enumeră între paranteze pătrate.
Dacă adunăm două liste obținem concatenarea lor:
[1,2] + [3,4]
Output: [1, 2, 3, 4]
Dacă înmulțim o listă cu un număr n, obținem o listă nouă în care se repetă șirul inițial de n ori:
[1,2] * 4
Output: [1, 2, 1, 2, 1, 2, 1, 2]
Crearea unei liste
Se enumeră elementele între paranteze drepte, sau se folosește constructorul list care primește un obiect prin care se poate itera (precum un sir de caractere)
l1 = [1,2,3]
l2 = list("abc")
print(l1)
print(l2)
Output:
[1, 2, 3]
['a', 'b', 'c']
Parcurgerea unei liste
Putem parcurge o listă în mai multe moduri.
Operatorul in permite iterarea prin fiecare element al listei fără a cunoaște indicele elementului:
for elem in l:
print(elem)
Output:
10
5
1
Dacă ne interesează indicele elementului putem parcurge lista folosindu-ne de accesul direct al elementului prin indice:
for i in range(len(l)):
print(l[i])
Output:
10
5
1
Putem itera printr-o listă folosind enumerate(lista) care este un generator prin care obținem pe rând tupluri de forma (indice, lista[indice]) - indicele din listă și elementul corespunzător acestuia:
for i, elem in enumerate(l):
print(i, elem)
Output:
0 3
1 4
2 5
Funcții
Funcțiile se definesc cu ajutorul cuvântului def. Pot avea oricât de mulți parametri și pot returna oricât de multe valori:
def f(a):
return a + 1
x = f(4)
print(x)
Output: 5
def f(a, b):
return a + b
x = f(3, 4)
print(x)
Output: 7
def f(a):
return a, a + 2
x = f(3)
print(x)
Output: (3, 5)
Parametrii pot avea valori implicite. Valorile implicite se află mereu la finalul listei de parametri:
def f(a, b = 3, c = 4):
return a, b + 2, c
f(2)
Output: (2, 5, 4)
Putem alege să le dăm valori explicite doar anumitor parametri cu valoare default din listă:
def f(a = 1, b = 3, c = 4):
return a, b + 2, c
f(b = 2)
Output: (1, 4, 4)
Clase
Intuiție clase: Colab
Clasele se definesc cu ajutorul cuvântului cheie class. Ca în orice limbaj, avem variabile statice pe care le putem apela fie la nivel de clasă, fie la nivel de instanță a clasei:
class Clasa:
x = 10
Clasa.x
Output: 10
instanta = Clasa()
instanta.x
Output: 10
Cu ce seamănă clasele din ce ați mai făcut până acum?
Răspuns aici
Funcțiile din clase încep mereu cu operatorul self - referință către clasa respectivă. Referința poate avea orice denumire, self este doar o convenție:
class Clasa:
x = 3
def f(self, x):
return self.x, x
instanta = Clasa()
instanta.f(7)
Output: (3, 7)
Observă cum x și self.x sunt variabile complet separate. În Python, parametrii funcțiilor mereu sunt considerați independenți de mediul exterior, în timp ce elementele care încep cu self. sunt specifici instanței clasei respective.
Pe lângă funcțiile normale avem și o serie de funcții implicite:
__init__-> inițializarea clasei (constructor)__str__-> transformarea clasei în instanță string__lt__-> definiția operatorului <__le__-> definiția operatorului <=__gt__-> definiția operatorului >
Funcțiile pot fi apelate cu denumirea lor, dar și direct, folosind simbolul respectiv.
class Clasa:
def __init__(self, x):
self.x = x
def __str__(self):
return "Valoarea clasei: " + str(self.x)
instanta = Clasa(5)
print(instanta)
Output: Valoarea clasei: 5
Exercițiu
Creează o clasă cu minim 2 elemente. Creează 2 instanțe pentru noua clasă și afișeaz-o pe cea mai mare în urma comparației dintre ele.
# Rezolvă aici
Proiect:
Gândește-te la un obiect / concept / ființă etc. cu care interacționezi des și creează o clasă în care să salvezi informații despre acesta. Adaugă 2-3 funcții care se bazează pe datele respective. Puncte bonus dacă o clasa de tipul acesta ar putea fi utilă în viața ta de zi cu zi!
# Rezolvă aici
Probleme de căutare
Lupul, Capra și Varza
În Colab: Lupul, Capra și Varza
Țăranul Grigore nu are prea multe, dar printre bunurile lui se numără un lup, o capră și o varză.
Aceste 3 bunuri sunt mai speciale decât celelalte. Lupul dacă rămâne singur cu capra (fără țăran) o va mânca, la fel capra dacă rămâne singură va încerca să mănânce varza.
Grigore vrea să le ducă pe toate 3 azi la un festival să le prezinte celorlalți țărani. Din păcate, drumul lui spre festival trece peste un râu fără pod. Niciunul dintre cei 4 nu știe să înoate. Grigore de obicei trecea râul cu bărcuța pe care și-a făcut-o acum mai mulți ani, dar bărcuța e foarte mică, putem spune că are doar 2 locuri: cât să încapă el (singurul care știe să vâslească) și unul din bunurile lui.
Care e cel mai scurt mod de a trimite pe toată lumea pe celalată parte a râului?
Rezolvați pe hârtie
Exercițiu
Formalizează problema. Creează o clasă LCV cu toate informațiile relevante unei stări a jocului. Aceasta va avea funcțiile:
def __init__(self, stare), unde stare va fi un string cu 'L' (lup), 'C' (capră), 'V' (varză), sau 'T' (țăran) reprezentând lista de ființe care se află pe partea stângă a râuluidef __str__(self), returnează un string reprezentând poziția acestora și a bărcii. De exemplu, pentru starea 'LC' (barca este cu țăranul pe partea dreaptă) vom afișa:LC | <> | TVdef succesori(self), returnează lista de stări valide în care pot ajunge după o plimbare cu barca
Alternativ starea poate fi un tuplu de forma: (T, L, C, V), cu valorile 0 -> dacă e pe partea stângă, 1 -> dacă e pe partea dreaptă
Implementați următoarele funcții ajutătoare:
drumRadacina()- care va returna o listă cu toate nodurile ca obiecte (nu informația nodurilor) de la rădăcină până la nodul curent;vizitat()- returnează True dacă nodul curent (self) a fost deja vizitat pe drumul de la rădăcină până la părintele lui, False altfelsuccesori()- generează lista de stări succesoare valide
# Rezolvă aici
CLTV|<> |
LV| <>|CT
CLTV|<> |
Exercițiu
Găsește cel mai scurt drum pentru a transporta toți oamenii pe malul drept folosind algoritmul BFS
# Rezolvă aici