Ein del problemstillingar kan vera ganske vanskelege å løysa ved rekning. Simulering kan hjelpa til å gjera denne type oppgåver mykje lettare å løysa. I dag ser me på ei oppgåve henta frå eksempelsettet til skriftleg eksamen etter ny læreplan i S2.
Ta gjerne ein kikk på dette innlegget om du treng oppfrisking i grunnleggande simulering med NumPy. Ellers er dokumentasjonen til NumPy ein fin stad å vera…
Oppgåva
På ein skule er det 323 jenter og 301 gutar. La \(X\) vera høgda til ei tilfeldig vald jente og \(Y\) vera høgda til ein tilfeldig vald gut. Me går ut frå at \(X\) og \(Y\) er normalfordelt med \(\mu_x=168 cm\), \(\mu_y=180 cm\), \(\sigma_x = 6 cm\) og \(\sigma_y = 8 cm\).
Lag eit program som du kan bruka til å simulera sannsynet for at ein tilfeldig vald elev er høgare enn 175 cm. Bestem dette sannsynet.
(UDIR - Eksempelsett eksamen S2-V23 oppgåve 6, del 2)
🧐 Me må altså både bestemma om det er gut eller jente me har trekt i tillegg til å finna høgda på eleven. Krevande for hand/analytisk men ikkje så aller verst å finna ut av ved simulering!
🔀 Ulike framgangsmåtar
Ser på tre ulike framgangsmåtar her 1️⃣ “rett fram” med løkker (treg måte 🐢) 2️⃣ fancy versjon av 1️⃣ (men enno tregare 🐌) 3️⃣ ingen løkker, kun arrays 👑 (rask måte ⚡)
💡 Om du er fan av eleganse og fart kan du hoppa rett til 3️⃣
1️⃣ Løkker
Tanken her er å trekka ein elev N gongar. Trekk eit tal mellom 0 og 323+301, og seier at dei 323 første (fom. 0 tom. 322) er jenter, og dei siste (resten) er gutar. Simulerer høgda til kvar elev etter det. Tel til slutt opp kor mange som er over 175 cm.
import numpy as nprng = np.random.default_rng()# tal simuleringarN =10000000# N elevar (tal mellom 0 og 323+301)elevar = rng.integers(0, (323+301), size=N)# tom liste til høgdenehøgdar = []# Finn høgda til kvar elevfor elev in elevar:if elev<323: # 0 til 322 er jenter høgdar.append(rng.normal(168, 6))else: # 323 til 323+301 er gutar høgdar.append(rng.normal(180, 8))# tel opp elevar høgare enn 175 cmgunstige =sum(np.array(høgdar)>175)sannsyn = gunstige / Nprint(f"Sannsynet for at ein tilfeldig elev er høgare enn 175 cm er {sannsyn:.4f}")
Sannsynet for at ein tilfeldig elev er høgare enn 175 cm er 0.4172
⏳ Her brukte maskina mi ca. 17 sek. på 10 000 000 simuleringar.
2️⃣ funksjonar…
Her gjer me 1️⃣ litt meir fancy. Mykje lik tankegang.
import numpy as nprng = np.random.default_rng()# tal simuleringarN =10000000# finn sannsyn jente og sannsyn guttp = np.array([323, 301]) / (323+301)# lagar funksjon som trekk ein elevdef trekk_elev(p): høgde =0# trekk kjønn: kjønn = rng.choice(['j', 'g'], p=p)# trekk høgde (ut frå trekt kjønn)if kjønn =='j': høgde = rng.normal(168, 6, 1)else: høgde = rng.normal(180, 8, 1)return høgde[0]# tel opp talet elevar som er over 175 cmgunstig =0for i inrange(N): h = trekk_elev(p)if h>175: gunstig +=1# finn og skriv ut relativ frekvenssannsyn = gunstig/Nprint(f"Sannsynet for at ein tilfeldig elev er høgare enn 175 cm er {sannsyn:.4f}")
Sannsynet for at ein tilfeldig elev er høgare enn 175 cm er 0.4169
⏳ Her brukte maskina mi ca. 5 min. (!!!) på 10 000 000 simuleringar.
3️⃣ Alt i arrays 🚀
For å gjera programmet effektivt, raskt og lett leseleg droppar eg løkker og funksjonar.
import numpy as nprng = np.random.default_rng()# antall jenter, gutar og elevar på skulenj =323g =301n = j + g# tal simuleringarN =10000000# finn antall gutar (0) og jenter (1)kjønn = rng.choice([0,1], size=N, p=[g/n, j/n])jenter =sum(kjønn)gutar = N - jenter# finn høgder på jenter og gutar for segh_jenter = rng.normal(168, 6, size=jenter)h_gutar = rng.normal(180, 8, size=gutar)# høgder på alle dei trekte elevaneh_trekte = np.append(h_jenter, h_gutar)# reknar ut sannsynetgunstige =sum(h_trekte >175)sannsyn = gunstige / Nprint(f"Sannsynet for at ein tilfeldig elev er høgare enn 175 cm er {sannsyn:.4f}")
Sannsynet for at ein tilfeldig elev er høgare enn 175 cm er 0.4168
⚡ 3,4 sek. på 10 000 000 simuleringar! 😎
Oppsummert
Dette var eit lite innblikk i ulike måtar ei oppgåve som dette kan løysast på ved hjelp av simulering. Ville nok valgt den elegante og raske versjonen (3️⃣) sjølv.
Gje gjerne eit pip om du lurer på noko ⬇️ Plutseleg attende med nye innlegg ✌️