import%20marimo%0A%0A__generated_with%20%3D%20%220.25.0%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22%2C%20app_title%3D%22Python%20Basics%20%E2%80%94%20Getting%20Started%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Python%20basics%0A%20%20%20%20%23%23%20A%20from-scratch%20guide%20to%20the%20Python%20used%20in%20this%20course%0A%0A%20%20%20%20**MATH4120%20%E2%80%94%20Mathematical%20Modelling%20and%20Programming**%20Lancaster%20University%2C%202026%E2%80%9327%0A%0A%20%20%20%20---%0A%0A%20%20%20%20This%20course%20assumes%20no%20prior%20programming%20experience.%20Every%20piece%20of%20Python%20that%20appears%20anywhere%20in%20a%20MATH4120%20lecture%20or%20lab%20%E2%80%94%20variables%2C%20loops%2C%20functions%2C%20NumPy%20arrays%2C%20plots%20%E2%80%94%20is%20explained%20here%20from%20scratch%2C%20roughly%20in%20the%20order%20you'll%20first%20meet%20it.%20Nothing%20here%20is%20invented%20for%20its%20own%20sake%3A%20everything%20below%20is%20something%20a%20MATH4120%20notebook%20genuinely%20uses%2C%20and%20nothing%20genuinely%20used%20is%20left%20out.%0A%0A%20%20%20%20This%20is%20itself%20a%20live%20Marimo%20notebook%20%E2%80%94%20see%20the%20%5BWorking%20with%20Marimo%5D(..%2Fgetting-started%2Fmarimo.html)%20guide%20for%20how%20the%20%22View%22%20%2F%20%22Run%22%20buttons%20work.%20Every%20example%20below%20is%20real%2C%20runnable%20Python%3A%20read%20the%20explanation%2C%20look%20at%20the%20code%2C%20look%20at%20what%20it%20prints%20out.%20If%20you're%20on%20the%20%22Run%22%20version%2C%20try%20changing%20a%20number%20in%20a%20cell%20and%20re-running%20it%20%E2%80%94%20that's%20the%20fastest%20way%20any%20of%20this%20actually%20sticks.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%0A%20%20%20%20return%20np%2C%20plt%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%201.%20Cells%2C%20code%2C%20and%20output%0A%0A%20%20%20%20A%20notebook%20is%20a%20sequence%20of%20**cells**.%20Each%20cell%20holds%20a%20small%20piece%20of%20Python%3B%20you%20run%20it%20and%20see%20its%20result%20immediately%20underneath%2C%20rather%20than%20running%20an%20entire%20program%20from%20top%20to%20bottom%20at%20once.%20This%20is%20what%20%22interactive%22%20means%20here%3A%20write%20a%20line%2C%20see%20what%20it%20does%2C%20adjust%2C%20repeat.%0A%0A%20%20%20%20Whatever%20the%20*last*%20line%20of%20a%20cell%20evaluates%20to%20gets%20displayed%20automatically%20as%20that%20cell's%20output%20%E2%80%94%20you%20don't%20need%20to%20ask%20for%20it%20explicitly.%20A%20line%20starting%20with%20%60%23%60%20is%20a%20**comment**%3A%20Python%20ignores%20it%20completely%3A%20it's%20a%20note%20to%20whoever%20reads%20the%20code%20(including%20you%2C%20later).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20%23%20This%20is%20a%20comment%20%E2%80%94%20Python%20skips%20this%20line%20entirely.%0A%20%20%20%203%20%2B%204%20%20%20%23%20the%20last%20line%20of%20a%20cell%20is%20displayed%20as%20its%20output%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%202.%20Variables%20and%20arithmetic%0A%0A%20%20%20%20A%20**variable**%20is%20a%20name%20that%20points%20to%20a%20value.%20%60%3D%60%20means%20%22assign%22%3A%20it%20does%20*not*%20mean%20mathematical%20equality%20(that's%20%60%3D%3D%60%2C%20coming%20up%20in%20Section%204).%20Once%20a%20variable%20holds%20a%20value%2C%20you%20can%20use%20it%20in%20later%20expressions%20just%20like%20a%20number.%0A%0A%20%20%20%20The%20arithmetic%20operators%20are%20%60%2B%20-%20*%20%2F%60%20as%20expected%2C%20%60**%60%20for%20%22to%20the%20power%20of%22%20(there%20is%20no%20%60%5E%60%20for%20this%20in%20Python)%2C%20and%20%60%2F%2F%60%20for%20integer%20(whole-number%2C%20rounded-down)%20division.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_N0%20%3D%20100%20%20%20%20%20%20%20%20%23%20initial%20population%0A%20%20%20%20_r%20%3D%200.15%20%20%20%20%20%20%20%20%23%20growth%20rate%0A%20%20%20%20_t%20%3D%204%20%20%20%20%20%20%20%20%20%20%20%20%23%20time%20elapsed%0A%0A%20%20%20%20_N0%20*%20(1%20%2B%20_r)%20**%20_t%20%20%20%23%20**%20means%20%22to%20the%20power%20of%22%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%2017%20%2F%2F%205%2C%2017%20%25%205%20%20%20%23%20%2F%2F%20%3D%20whole%20number%20division%2C%20%25%20%3D%20remainder%20(%22modulo%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%203.%20Strings%20and%20f-strings%0A%0A%20%20%20%20Text%20is%20written%20as%20a%20**string**%2C%20in%20single%20or%20double%20quotes%20%E2%80%94%20%60'hello'%60%20and%20%60%22hello%22%60%20mean%20exactly%20the%20same%20thing.%20The%20really%20useful%20form%20is%20an%20**f-string**%3A%20put%20an%20%60f%60%20right%20before%20the%20opening%20quote%2C%20and%20anything%20inside%20%60%7Bcurly%20braces%7D%60%20gets%20evaluated%20and%20dropped%20into%20the%20text.%20A%20colon%20inside%20the%20braces%20controls%20the%20number%20format%2C%20e.g.%20%60%3A.2f%60%20means%20%222%20decimal%20places%22.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_r%20%3D%200.15%0A%20%20%20%20_N%20%3D%20174.9%0A%0A%20%20%20%20f%22With%20growth%20rate%20r%20%3D%20%7B_r%7D%2C%20the%20population%20reached%20N%20%3D%20%7B_N%3A.1f%7D%22%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%204.%20Comparisons%20and%20booleans%0A%0A%20%20%20%20Comparing%20two%20values%20with%20%60%3C%20%3E%20%3C%3D%20%3E%3D%20%3D%3D%20%20!%3D%60%20gives%20you%20a%20**boolean**%3A%20%60True%60%20or%20%60False%60.%20Note%20%60%3D%3D%60%20(equality%20test)%20is%20different%20from%20%60%3D%60%20(assignment)%20%E2%80%94%20mixing%20these%20up%20is%20one%20of%20the%20most%20common%20early%20mistakes%2C%20and%20Python%20won't%20stop%20you%20from%20writing%20%60%3D%60%20where%20you%20meant%20%60%3D%3D%60%2C%20so%20it's%20worth%20double-checking.%20Combine%20booleans%20with%20%60and%60%2C%20%60or%60%2C%20and%20%60not%60.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_N%20%3D%20174.9%0A%20%20%20%20_capacity%20%3D%20200.0%0A%0A%20%20%20%20_N%20%3C%20_capacity%2C%20_N%20%3D%3D%20174.9%2C%20_N%20%3E%20100%20and%20_N%20%3C%20_capacity%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%205.%20%60if%60%20%2F%20%60elif%60%20%2F%20%60else%60%0A%0A%20%20%20%20An%20%60if%60%20statement%20runs%20a%20block%20of%20code%20only%20when%20a%20condition%20is%20%60True%60.%20%60elif%60%20(%22else%20if%22)%20checks%20another%20condition%20if%20the%20first%20one%20was%20%60False%60%2C%20and%20%60else%60%20catches%20everything%20else.%20Python%20uses%20**indentation**%20(consistent%20spaces%20at%20the%20start%20of%20a%20line)%20to%20mark%20which%20lines%20belong%20inside%20the%20%60if%60%20%E2%80%94%20there%20are%20no%20curly%20braces%20%60%7B%7D%60%20for%20this%2C%20unlike%20many%20other%20languages.%0A%0A%20%20%20%20A%20compact%20one-line%20version%2C%20the%20**ternary%20expression**%2C%20is%20also%20common%3A%20%60value_if_true%20if%20condition%20else%20value_if_false%60.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_N%20%3D%20174.9%0A%20%20%20%20_capacity%20%3D%20200.0%0A%0A%20%20%20%20if%20_N%20%3C%200.5%20*%20_capacity%3A%0A%20%20%20%20%20%20%20%20_status%20%3D%20%22growing%20freely%22%0A%20%20%20%20elif%20_N%20%3C%20_capacity%3A%0A%20%20%20%20%20%20%20%20_status%20%3D%20%22approaching%20capacity%22%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20_status%20%3D%20%22at%20or%20above%20capacity%22%0A%0A%20%20%20%20_status%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_T%20%3D%2015%0A%20%20%20%20%22warm%22%20if%20_T%20%3E%2018%20else%20%22cool%22%20%20%20%23%20the%20one-line%20%22ternary%22%20form%20of%20if%2Felse%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%206.%20Lists%0A%0A%20%20%20%20A%20**list**%20is%20an%20ordered%20collection%20of%20values%2C%20written%20with%20square%20brackets%3A%20%60%5B10%2C%2020%2C%2030%5D%60.%20Access%20an%20element%20with%20%60list%5Bindex%5D%60%20%E2%80%94%20Python%20counts%20positions%20**from%200**%2C%20so%20%60%5B0%5D%60%20is%20the%20first%20element%2C%20and%20%60%5B-1%5D%60%20is%20a%20shortcut%20for%20%22the%20last%20one%22%20(very%20heavily%20used%20throughout%20this%20course%2C%20e.g.%20to%20grab%20%22the%20most%20recent%20value%22%20in%20a%20step-by-step%20calculation).%20A%20**slice**%20%60list%5Bstart%3Astop%5D%60%20pulls%20out%20a%20sub-range%3B%20leaving%20%60start%60%20or%20%60stop%60%20blank%20means%20%22from%20the%20beginning%22%20%2F%20%22to%20the%20end%22.%20%60len(list)%60%20gives%20the%20number%20of%20elements%2C%20and%20%60.append(x)%60%20adds%20%60x%60%20to%20the%20end.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_temperatures%20%3D%20%5B21.0%2C%2019.5%2C%2018.2%2C%2017.0%2C%2016.1%5D%0A%0A%20%20%20%20_temperatures%5B0%5D%2C%20_temperatures%5B-1%5D%2C%20len(_temperatures)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_temperatures%20%3D%20%5B21.0%2C%2019.5%2C%2018.2%2C%2017.0%2C%2016.1%5D%0A%20%20%20%20_temperatures.append(15.4)%20%20%20%23%20add%20a%20new%20value%20onto%20the%20end%0A%0A%20%20%20%20_temperatures%5B1%3A4%5D%2C%20_temperatures%20%20%20%23%20a%20slice%2C%20then%20the%20whole%20(now%20longer)%20list%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%207.%20Tuples%20and%20multiple%20assignment%0A%0A%20%20%20%20A%20**tuple**%20is%20an%20ordered%20collection%20like%20a%20list%2C%20but%20written%20with%20parentheses%20%60(a%2C%20b)%60%20(or%20often%20no%20brackets%20at%20all)%20and%20not%20meant%20to%20be%20changed%20after%20it's%20created.%20Tuples%20show%20up%20constantly%20for%20**multiple%20assignment**%20%E2%80%94%20unpacking%20several%20values%20out%20of%20one%20expression%20in%20a%20single%20line%20%E2%80%94%20and%20for%20functions%20that%20need%20to%20hand%20back%20more%20than%20one%20result%20at%20once%20(Section%2012).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_t0%2C%20_T%20%3D%200.0%2C%205.0%20%20%20%20%20%23%20assign%20two%20variables%20in%20one%20line%0A%20%20%20%20_point%20%3D%20(1.0%2C%203.0)%20%20%20%20%20%23%20an%20explicit%20tuple%3A%20an%20(x%2C%20y)%20pair%0A%20%20%20%20_x%2C%20_y%20%3D%20_point%20%20%20%20%20%20%20%20%20%20%23%20unpack%20it%20into%20two%20separate%20variables%0A%0A%20%20%20%20_t0%2C%20_T%2C%20_x%2C%20_y%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%208.%20Dictionaries%0A%0A%20%20%20%20A%20**dictionary**%20maps%20keys%20to%20values%20%E2%80%94%20a%20lookup%20table.%20Write%20it%20as%20%60%7Bkey%3A%20value%2C%20...%7D%60%2C%20and%20look%20something%20up%20with%20%60d%5Bkey%5D%60.%20This%20course%20uses%20dictionaries%20only%20occasionally%20(mostly%20for%20small%2C%20named%20lookup%20tables%2C%20like%20a%20planet's%20name%20mapped%20to%20its%20surface%20gravity)%2C%20but%20it's%20worth%20recognising%20the%20syntax%20when%20you%20see%20it.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_planet_gravity%20%3D%20%7B%22Earth%22%3A%209.81%2C%20%22Moon%22%3A%201.62%2C%20%22Mars%22%3A%203.71%7D%0A%0A%20%20%20%20_planet_gravity%5B%22Mars%22%5D%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_planet_gravity%20%3D%20%7B%22Earth%22%3A%209.81%2C%20%22Moon%22%3A%201.62%2C%20%22Mars%22%3A%203.71%7D%0A%0A%20%20%20%20%5Bf%22%7B_name%7D%3A%20%7B_g%7D%20m%2Fs%C2%B2%22%20for%20_name%2C%20_g%20in%20_planet_gravity.items()%5D%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%209.%20%60for%60%20loops%0A%0A%20%20%20%20A%20%60for%60%20loop%20repeats%20a%20block%20of%20code%20once%20per%20item%20in%20a%20collection%3A%20%60for%20item%20in%20some_list%3A%60.%20%60range(n)%60%20gives%20the%20whole%20numbers%20from%20%600%60%20up%20to%20(not%20including)%20%60n%60%2C%20and%20is%20the%20standard%20way%20to%20%22do%20something%20%60n%60%20times%22.%20%60enumerate(some_list)%60%20gives%20you%20both%20the%20position%20and%20the%20value%20as%20you%20go%3B%20%60zip(list_a%2C%20list_b)%60%20walks%20through%20two%20lists%20side%20by%20side%2C%20pairing%20them%20up.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_rates%20%3D%20%5B0.05%2C%200.10%2C%200.15%5D%0A%0A%20%20%20%20for%20_r%20in%20_rates%3A%0A%20%20%20%20%20%20%20%20print(f%22rate%20%7B_r%7D%20-%3E%20after%201%20step%3A%20%7B100%20*%20(1%20%2B%20_r)%3A.1f%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_rates%20%3D%20%5B0.05%2C%200.10%2C%200.15%5D%0A%20%20%20%20_labels%20%3D%20%5B%22slow%22%2C%20%22medium%22%2C%20%22fast%22%5D%0A%0A%20%20%20%20for%20_i%2C%20_r%20in%20enumerate(_rates)%3A%0A%20%20%20%20%20%20%20%20print(f%22scenario%20%7B_i%7D%3A%20rate%20%7B_r%7D%22)%0A%0A%20%20%20%20for%20_label%2C%20_r%20in%20zip(_labels%2C%20_rates)%3A%0A%20%20%20%20%20%20%20%20print(f%22%7B_label%7D%3A%20rate%20%7B_r%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2010.%20%60while%60%20loops%0A%0A%20%20%20%20A%20%60while%60%20loop%20keeps%20repeating%20as%20long%20as%20a%20condition%20stays%20%60True%60%2C%20rather%20than%20a%20fixed%20number%20of%20times.%20This%20is%20exactly%20how%20every%20step-by-step%20ODE%20solver%20in%20this%20course%20is%20built%20from%20Week%207%20onwards%3A%20keep%20taking%20a%20small%20time%20step%20*while%20the%20current%20time%20is%20still%20less%20than%20the%20end%20time*.%20%60list%5B-1%5D%60%20(Section%206)%20is%20what%20lets%20the%20loop%20always%20grab%20%22the%20most%20recent%20value%22%20to%20build%20the%20next%20one%20from.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_ts%20%3D%20%5B0.0%5D%0A%20%20%20%20_ys%20%3D%20%5B1.0%5D%0A%20%20%20%20_dt%20%3D%200.5%0A%0A%20%20%20%20while%20_ts%5B-1%5D%20%3C%202.0%3A%0A%20%20%20%20%20%20%20%20_ys.append(_ys%5B-1%5D%20*%201.1)%20%20%20%20%20%23%20next%20value%2C%20built%20from%20the%20previous%20one%0A%20%20%20%20%20%20%20%20_ts.append(_ts%5B-1%5D%20%2B%20_dt)%0A%0A%20%20%20%20_ts%2C%20_ys%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2011.%20List%20comprehensions%0A%0A%20%20%20%20A%20**list%20comprehension**%20builds%20a%20new%20list%20from%20an%20existing%20one%20in%20a%20single%20line%3A%20%60%5Bexpression%20for%20item%20in%20list%5D%60%2C%20optionally%20with%20an%20%60if%60%20at%20the%20end%20to%20filter.%20It's%20just%20a%20compact%20%60for%60%20loop%20that%20collects%20results%20into%20a%20list%20%E2%80%94%20the%20same%20computation%20as%20writing%20the%20loop%20out%20longhand%20and%20calling%20%60.append()%60%20each%20time%2C%20but%20far%20more%20common%20in%20practice%20once%20it%20feels%20natural.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_n1_values%20%3D%20range(1%2C%206)%0A%0A%20%20%20%20%5B3%20*%20_n1%20%2B%201%20for%20_n1%20in%20_n1_values%5D%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_values%20%3D%20%5B4%2C%2015%2C%208%2C%2023%2C%2016%2C%2042%5D%0A%0A%20%20%20%20%5B_v%20for%20_v%20in%20_values%20if%20_v%20%3E%2010%5D%20%20%20%23%20keep%20only%20values%20above%2010%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2012.%20Writing%20your%20own%20functions%0A%0A%20%20%20%20A%20**function**%20packages%20up%20a%20calculation%20you%20want%20to%20reuse%3A%20%60def%20name(inputs)%3A%60%20followed%20by%20an%20indented%20body%2C%20ending%20in%20%60return%20result%60.%20Arguments%20can%20have%20a%20**default%20value**%20(%60def%20f(x%2C%20y%3D1)%3A%60)%2C%20used%20whenever%20the%20caller%20doesn't%20supply%20that%20argument.%20%60return%20a%2C%20b%60%20hands%20back%20a%20tuple%20of%20several%20values%20at%20once%20%E2%80%94%20exactly%20the%20multiple-assignment%20pattern%20from%20Section%207%2C%20now%20coming%20*out*%20of%20a%20function%20instead%20of%20a%20literal.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20def%20_double(_x)%3A%0A%20%20%20%20%20%20%20%20return%202%20*%20_x%0A%0A%20%20%20%20_double(21)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20def%20_greet(_name%2C%20_greeting%3D%22Hello%22)%3A%0A%20%20%20%20%20%20%20%20return%20f%22%7B_greeting%7D%2C%20%7B_name%7D!%22%0A%0A%20%20%20%20_greet(%22Ada%22)%2C%20_greet(%22Ada%22%2C%20%22Good%20morning%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20def%20_min_and_max(_values)%3A%0A%20%20%20%20%20%20%20%20return%20min(_values)%2C%20max(_values)%0A%0A%20%20%20%20_lo%2C%20_hi%20%3D%20_min_and_max(%5B3.0%2C%207.0%2C%202.0%2C%209.0%2C%204.0%5D)%0A%20%20%20%20_lo%2C%20_hi%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2013.%20NumPy%3A%20arrays%20and%20vectorised%20arithmetic%0A%0A%20%20%20%20A%20plain%20Python%20list%20is%20flexible%20but%20slow%20for%20maths%20on%20lots%20of%20numbers%20at%20once.%20**NumPy**%20(imported%20once%2C%20right%20at%20the%20top%2C%20as%20%60np%60)%20provides%20the%20**array**%20instead%3A%20%60np.array(%5B...%5D)%60%20from%20a%20list%2C%20%60np.linspace(start%2C%20stop%2C%20n)%60%20for%20%60n%60%20evenly-spaced%20points%2C%20%60np.arange(start%2C%20stop%2C%20step)%60%20for%20a%20fixed%20step%20size%2C%20and%20%60np.zeros(n)%60%20for%20an%20array%20of%20%60n%60%20zeros%20to%20fill%20in%20later.%0A%0A%20%20%20%20The%20single%20most%20important%20thing%20about%20arrays%3A%20arithmetic%20applies%20to%20*every%20element%20at%20once*%2C%20with%20no%20loop%20needed.%20%60array%20*%202%60%20doubles%20every%20entry%3B%20%60array1%20%2B%20array2%60%20adds%20them%20elementwise.%20This%20is%20called%20**vectorisation**%2C%20and%20it's%20why%20every%20ODE%20solution%2C%20every%20dataset%2C%20and%20every%20plotted%20curve%20in%20this%20course%20is%20built%20from%20arrays%20rather%20than%20lists.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_n%20%3D%20np.arange(0%2C%205)%20%20%20%20%20%20%20%20%20%23%20array(%5B0%2C%201%2C%202%2C%203%2C%204%5D)%0A%20%20%20%20_N0%2C%20_R%20%3D%20100.0%2C%201.2%0A%0A%20%20%20%20_N0%20*%20_R%20**%20_n%20%20%20%23%20one%20line%2C%20no%20loop%3A%20computes%20all%205%20values%20at%20once%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_t%20%3D%20np.linspace(0%2C%201%2C%205)%20%20%20%23%205%20evenly-spaced%20points%20from%200%20to%201%0A%20%20%20%20_t%2C%20np.exp(-_t)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20elementwise%3A%20e%5E(-t)%20for%20every%20t%20at%20once%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2014.%20NumPy%3A%20indexing%20and%20slicing%0A%0A%20%20%20%20Arrays%20support%20the%20same%20%60%5Bindex%5D%60%20and%20%60%5Bstart%3Astop%5D%60%20slicing%20as%20lists%20(Section%206)%2C%20plus%20one%20extra%20trick%20used%20constantly%20in%20this%20course%3A%20**boolean%20masking**.%20Writing%20a%20comparison%20on%20an%20array%20(%60arr%20%3E%203%60)%20gives%20back%20an%20array%20of%20%60True%60%2F%60False%60%20values%3B%20using%20*that*%20as%20an%20index%2C%20%60arr%5Barr%20%3E%203%5D%60%2C%20keeps%20only%20the%20entries%20where%20the%20condition%20holds.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_arr%20%3D%20np.array(%5B2.0%2C%208.0%2C%201.0%2C%209.0%2C%204.0%2C%207.0%5D)%0A%0A%20%20%20%20_arr%5B0%5D%2C%20_arr%5B-1%5D%2C%20_arr%5B1%3A4%5D%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_arr%20%3D%20np.array(%5B2.0%2C%208.0%2C%201.0%2C%209.0%2C%204.0%2C%207.0%5D)%0A%0A%20%20%20%20_arr%20%3E%205%2C%20_arr%5B_arr%20%3E%205%5D%20%20%20%23%20a%20boolean%20mask%2C%20then%20using%20it%20to%20filter%20the%20array%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2015.%20NumPy%3A%20useful%20functions%0A%0A%20%20%20%20A%20short%20reference%20for%20the%20NumPy%20functions%20you'll%20see%20repeatedly.%20All%20of%20these%20work%20elementwise%20on%20a%20whole%20array%20at%20once%2C%20just%20like%20the%20arithmetic%20in%20Section%2013.%0A%0A%20%20%20%20%7C%20Function%20%7C%20What%20it%20does%20%7C%0A%20%20%20%20%7C---%7C---%7C%0A%20%20%20%20%7C%20%60np.exp(x)%60%2C%20%60np.log(x)%60%2C%20%60np.sqrt(x)%60%20%7C%20exponential%2C%20natural%20log%2C%20square%20root%20%7C%0A%20%20%20%20%7C%20%60np.abs(x)%60%20%7C%20absolute%20value%20%7C%0A%20%20%20%20%7C%20%60np.sum(x)%60%2C%20%60np.mean(x)%60%20%7C%20total%2C%20and%20average%2C%20of%20all%20elements%20%7C%0A%20%20%20%20%7C%20%60np.max(x)%60%2C%20%60np.min(x)%60%20(or%20%60x.max()%60%2C%20%60x.min()%60)%20%7C%20largest%20%2F%20smallest%20element%20%7C%0A%20%20%20%20%7C%20%60np.round(x%2C%202)%60%20%7C%20round%20every%20element%20to%202%20decimal%20places%20%7C%0A%20%20%20%20%7C%20%60np.sort(x)%60%20%7C%20a%20new%20array%20with%20elements%20in%20increasing%20order%20%7C%0A%20%20%20%20%7C%20%60np.where(cond%2C%20a%2C%20b)%60%20%7C%20elementwise%20%22if%20cond%20then%20a%20else%20b%22%20%7C%0A%20%20%20%20%7C%20%60np.clip(x%2C%20lo%2C%20hi)%60%20%7C%20squash%20every%20element%20into%20the%20range%20%60%5Blo%2C%20hi%5D%60%20%7C%0A%0A%20%20%20%20%60np.where%60%20is%20the%20array%20version%20of%20the%20ternary%20expression%20from%20Section%205%20%E2%80%94%20it%20works%20on%20every%20element%20at%20once%20instead%20of%20one%20value%20at%20a%20time.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_x%20%3D%20np.array(%5B-2.0%2C%20-0.5%2C%200.3%2C%201.5%2C%203.0%5D)%0A%0A%20%20%20%20np.where(_x%20%3E%200%2C%201.0%2C%20-1.0)%20%20%20%23%20%2B1%20where%20x%20is%20positive%2C%20-1%20where%20it%20isn't%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_x%20%3D%20np.array(%5B-2.0%2C%20-0.5%2C%200.3%2C%201.5%2C%203.0%5D)%0A%0A%20%20%20%20np.clip(_x%2C%200.0%2C%202.0)%20%20%20%23%20anything%20below%200%20becomes%200%2C%20anything%20above%202%20becomes%202%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2016.%20NumPy%3A%20randomness%0A%0A%20%20%20%20Every%20%22noisy%20data%22%20example%20in%20this%20course%20starts%20the%20same%20way%3A%20%60np.random.default_rng(seed)%60%20creates%20a%20**random%20number%20generator**.%20The%20%60seed%60%20(any%20whole%20number%20you%20choose)%20makes%20the%20randomness%20**reproducible**%20%E2%80%94%20the%20same%20seed%20always%20produces%20exactly%20the%20same%20sequence%20of%20%22random%22%20numbers%2C%20which%20is%20essential%20for%20a%20worked%20example%20everyone%20can%20check%20against%20the%20same%20answer.%20From%20that%20generator%2C%20%60.uniform(low%2C%20high%2C%20size%3Dn)%60%20draws%20%60n%60%20values%20evenly%20spread%20between%20%60low%60%20and%20%60high%60%2C%20%60.normal(loc%2C%20scale%2C%20size%3Dn)%60%20draws%20from%20a%20bell-curve%20(mean%20%60loc%60%2C%20spread%20%60scale%60)%2C%20and%20%60.choice(options%2C%20size%3Dn)%60%20picks%20%60n%60%20random%20entries%20out%20of%20a%20list.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_rng%20%3D%20np.random.default_rng(42)%20%20%20%23%2042%20is%20just%20a%20fixed%20choice%20%E2%80%94%20any%20number%20works%0A%0A%20%20%20%20_rng.uniform(0%2C%2010%2C%20size%3D5)%20%20%20%23%205%20random%20values%20between%200%20and%2010%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_rng%20%3D%20np.random.default_rng(42)%0A%20%20%20%20_true_values%20%3D%20np.array(%5B5.0%2C%205.0%2C%205.0%2C%205.0%2C%205.0%5D)%0A%20%20%20%20_noisy%20%3D%20_true_values%20%2B%20_rng.normal(loc%3D0.0%2C%20scale%3D0.5%2C%20size%3D5)%20%20%20%23%20add%20random%20%22measurement%20noise%22%0A%0A%20%20%20%20_noisy%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2017.%20NumPy%3A%20matrices%2C%20%60%40%60%2C%20and%20%60.T%60%0A%0A%20%20%20%20An%20array%20can%20have%20more%20than%20one%20dimension%20%E2%80%94%20a%202D%20array%20behaves%20like%20a%20matrix.%20%60%40%60%20is%20matrix%20multiplication%20(distinct%20from%20%60*%60%2C%20which%20multiplies%20elementwise)%2C%20and%20%60.T%60%20transposes%20a%20matrix%20(flips%20rows%20and%20columns).%20You'll%20meet%20this%20in%20two%20places%3A%20the%20Buckingham%20%CE%A0-theorem's%20dimension%20matrix%20(Week%203)%2C%20and%20every%20neural%20network%20from%20Week%209%20onwards%2C%20where%20a%20layer's%20output%20is%20computed%20as%20%60inputs%20%40%20weights%60.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_weights%20%3D%20np.array(%5B0.5%2C%20-1.0%5D)%0A%20%20%20%20_inputs%20%3D%20np.array(%5B2.0%2C%201.0%5D)%0A%0A%20%20%20%20_weights%20%40%20_inputs%20%20%20%23%20matrix%2Fvector%20multiplication%3A%20(0.5)(2)%20%2B%20(-1.0)(1)%20%3D%200.0%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_M%20%3D%20np.array(%5B%5B1.0%2C%202.0%5D%2C%20%5B3.0%2C%204.0%5D%5D)%0A%0A%20%20%20%20_M.T%20%20%20%23%20transpose%3A%20rows%20become%20columns%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2018.%20SciPy%3A%20black-box%20tools%0A%0A%20%20%20%20**SciPy**%20builds%20on%20NumPy%20with%20ready-made%20numerical%20routines.%20You%20are%20never%20asked%20to%20write%20these%20yourself%20%E2%80%94%20the%20point%20is%20knowing%20what%20to%20hand%20them%20and%20what%20comes%20back.%0A%0A%20%20%20%20-%20**%60solve_ivp(f%2C%20t_span%2C%20y0)%60**%20(%60scipy.integrate%60)%20%E2%80%94%20numerically%20solves%20an%20ODE%20%24y'%20%3D%20f(t%2C%20y)%24%20from%20initial%20condition%20%60y0%60%20over%20the%20time%20range%20%60t_span%20%3D%20(t0%2C%20T)%60.%20The%20result%20has%20%60.t%60%20(the%20time%20points)%20and%20%60.y%60%20(the%20solution%20at%20each%20of%20them).%0A%20%20%20%20-%20**%60curve_fit(model%2C%20x_data%2C%20y_data)%60**%20(%60scipy.optimize%60)%20%E2%80%94%20finds%20the%20parameters%20of%20%60model%60%20that%20best%20match%20some%20noisy%20data%2C%20by%20least%20squares.%0A%20%20%20%20-%20**%60least_squares(residuals%2C%20params0)%60**%20(%60scipy.optimize%60)%20%E2%80%94%20the%20more%20general%20version%20behind%20%60curve_fit%60%3A%20give%20it%20a%20function%20that%20returns%20the%20*errors*%20for%20a%20guess%20at%20the%20parameters%2C%20and%20it%20searches%20for%20the%20guess%20that%20makes%20those%20errors%20smallest.%0A%20%20%20%20-%20**%60null_space(A)%60**%20(%60scipy.linalg%60)%20%E2%80%94%20finds%20vectors%20%24x%24%20solving%20%24Ax%20%3D%200%24%3B%20used%20in%20Week%203%20to%20find%20dimensionless%20%CE%A0-groups%20from%20the%20dimension%20matrix.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20from%20scipy.integrate%20import%20solve_ivp%0A%0A%20%20%20%20def%20_decay(_t%2C%20_y)%3A%0A%20%20%20%20%20%20%20%20return%20-0.5%20*%20_y%20%20%20%23%20the%20ODE%20y'%20%3D%20-0.5%20y%0A%0A%20%20%20%20_sol%20%3D%20solve_ivp(_decay%2C%20(0.0%2C%205.0)%2C%20%5B10.0%5D%2C%20t_eval%3Dnp.linspace(0%2C%205%2C%206))%0A%20%20%20%20_sol.t%2C%20_sol.y%5B0%5D%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2019.%20Matplotlib%3A%20making%20a%20plot%0A%0A%20%20%20%20**Matplotlib**%20draws%20every%20figure%20in%20this%20course.%20The%20standard%20pattern%20is%20always%20the%20same%3A%20%60fig%2C%20ax%20%3D%20plt.subplots()%60%20creates%20a%20blank%20figure%20and%20a%20set%20of%20axes%20to%20draw%20on%2C%20%60ax.plot(x%2C%20y)%60%20draws%20a%20line%20through%20the%20points%2C%20then%20%60ax.set_xlabel(...)%60%2C%20%60ax.set_title(...)%60%2C%20%60ax.legend()%60%2C%20and%20%60ax.grid(True)%60%20label%20and%20tidy%20it%20up.%20%60fig.tight_layout()%60%20fixes%20up%20the%20spacing%2C%20and%20the%20bare%20%60fig%60%20at%20the%20end%20displays%20it%20(Section%201's%20%22last%20line%20is%20the%20output%22%2C%20applied%20to%20a%20figure).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt)%3A%0A%20%20%20%20_t%20%3D%20np.linspace(0%2C%205%2C%20100)%0A%20%20%20%20_y%20%3D%20np.exp(-_t)%0A%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(6%2C%204))%0A%20%20%20%20_ax.plot(_t%2C%20_y%2C%20label%3Dr%22%24e%5E%7B-t%7D%24%22)%0A%20%20%20%20_ax.set_xlabel(%22%24t%24%22)%0A%20%20%20%20_ax.set_ylabel(%22%24y%24%22)%0A%20%20%20%20_ax.set_title(%22A%20basic%20Matplotlib%20plot%22)%0A%20%20%20%20_ax.legend()%0A%20%20%20%20_ax.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20_fig%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2020.%20Matplotlib%3A%20a%20quick%20reference%0A%0A%20%20%20%20Beyond%20%60ax.plot%60%2C%20a%20handful%20of%20other%20plot%20types%20and%20helpers%20show%20up%20repeatedly%3A%0A%0A%20%20%20%20%7C%20Call%20%7C%20What%20it%20draws%20%7C%0A%20%20%20%20%7C---%7C---%7C%0A%20%20%20%20%7C%20%60ax.scatter(x%2C%20y)%60%20%7C%20individual%20points%2C%20not%20joined%20by%20a%20line%20%7C%0A%20%20%20%20%7C%20%60ax.step(x%2C%20y)%60%20%7C%20a%20staircase%20%E2%80%94%20used%20for%20Euler's%20method's%20discrete%20steps%20%7C%0A%20%20%20%20%7C%20%60ax.contour(X%2C%20Y%2C%20Z)%60%20%2F%20%60ax.contourf(...)%60%20%7C%20level%20curves%20%2F%20filled%20regions%20of%20a%202D%20function%20%7C%0A%20%20%20%20%7C%20%60ax.axhline(y0)%60%20%2F%20%60ax.axvline(x0)%60%20%7C%20a%20horizontal%20%2F%20vertical%20reference%20line%20%7C%0A%20%20%20%20%7C%20%60ax.errorbar(x%2C%20y%2C%20yerr%3D...)%60%20%7C%20points%20with%20error%20bars%20%7C%0A%0A%20%20%20%20A%20label%20written%20as%20%60r%22%24%5Ctheta%24%22%60%20(a%20*raw%20string*%2C%20%60r%22...%22%60%2C%20containing%20LaTeX)%20renders%20as%20a%20proper%20mathematical%20symbol%20rather%20than%20plain%20text%20%E2%80%94%20this%20is%20how%20every%20Greek%20letter%20and%20equation%20on%20every%20plot%20in%20this%20course%20is%20produced.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt)%3A%0A%20%20%20%20_t_data%20%3D%20np.array(%5B0.5%2C%201.2%2C%202.1%2C%203.0%2C%203.8%5D)%0A%20%20%20%20_y_data%20%3D%20np.array(%5B9.1%2C%207.8%2C%205.9%2C%204.2%2C%203.3%5D)%0A%20%20%20%20_t_line%20%3D%20np.linspace(0%2C%204%2C%2050)%0A%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(6%2C%204))%0A%20%20%20%20_ax.scatter(_t_data%2C%20_y_data%2C%20color%3D%22%231a5276%22%2C%20label%3D%22data%22)%0A%20%20%20%20_ax.plot(_t_line%2C%2010%20*%20np.exp(-0.3%20*%20_t_line)%2C%20%22k--%22%2C%20label%3D%22model%22)%0A%20%20%20%20_ax.set_xlabel(%22%24t%24%22)%0A%20%20%20%20_ax.set_ylabel(r%22%24%5Ctheta%24%22)%0A%20%20%20%20_ax.legend()%0A%20%20%20%20_ax.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20_fig%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%2021.%20Two%20things%20you'll%20notice%20in%20every%20notebook%0A%0A%20%20%20%20Two%20conventions%20appear%20throughout%20every%20MATH4120%20notebook%20that%20aren't%20standard%20Python%20knowledge%20%E2%80%94%20they're%20specific%20to%20how%20these%20particular%20files%20are%20packaged%2C%20so%20it's%20worth%20knowing%20what%20they%20are%20even%20though%20you'll%20never%20need%20to%20write%20them%20yourself.%0A%0A%20%20%20%20**Every%20variable%20name%20starting%20with%20an%20underscore%2C%20like%20%60_x%60%20or%20%60_fig%60.**%20Marimo%20(the%20notebook%20tool%20everything%20is%20written%20in)%20requires%20every%20*ordinary*%20variable%20name%20to%20be%20unique%20across%20an%20entire%20notebook%20%E2%80%94%20reuse%20%60x%60%20in%20two%20different%20cells%20and%20it%20refuses%20to%20run%2C%20since%20it%20can't%20tell%20which%20one%20you%20meant.%20A%20leading%20underscore%20marks%20a%20variable%20as%20private%20scratch%20space%20for%20that%20one%20cell%20only%2C%20exempt%20from%20that%20rule.%20Every%20example%20in%20this%20guide%20uses%20underscore-prefixed%20names%20for%20exactly%20this%20reason%20%E2%80%94%20feel%20free%20to%20ignore%20the%20underscore%20and%20just%20read%20%60_x%60%20as%20%60x%60.%0A%0A%20%20%20%20**Every%20cell%20in%20the%20raw%20%60.py%60%20source%20looks%20like%20%60def%20_(...)%3A%20...%20return%20(...)%60.**%20If%20you%20ever%20open%20a%20notebook's%20source%20file%20directly%2C%20each%20cell%20is%20written%20as%20a%20small%20function%2C%20and%20the%20names%20it%20takes%20as%20arguments%20are%20exactly%20the%20variables%20it%20needs%20from%20other%20cells.%20This%20is%20Marimo's%20own%20bookkeeping%20for%20figuring%20out%20which%20cells%20depend%20on%20which%20%E2%80%94%20it's%20what%20makes%20the%20notebook%20reactive%20(drag%20a%20slider%2C%20and%20every%20cell%20that%20depends%20on%20it%20re-runs%20automatically%2C%20like%20a%20spreadsheet).%20You%20never%20write%20this%20structure%20yourself%3B%20Marimo%20generates%20it%20for%20you%20as%20you%20type%20into%20cells%20in%20its%20own%20editor.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Summary%0A%0A%20%20%20%20-%20**Core%20Python%3A**%20variables%20(%60%3D%60)%2C%20arithmetic%20(%60%2B%20-%20*%20%2F%20**%20%2F%2F%60)%2C%20comparisons%20(%60%3D%3D%20%3C%20%3E%20%3C%3D%20%3E%3D%60)%2C%20%60if%60%2F%60elif%60%2F%60else%60%2C%20%60for%60%20and%20%60while%60%20loops%2C%20functions%20(%60def%60%20...%20%60return%60).%0A%20%20%20%20-%20**Collections%3A**%20lists%20(%60%5B...%5D%60%2C%20indexing%2C%20slicing%2C%20%60.append()%60)%2C%20tuples%20(multiple%20assignment)%2C%20dictionaries%20(%60%7Bkey%3A%20value%7D%60)%2C%20list%20comprehensions.%0A%20%20%20%20-%20**NumPy%20(%60np%60)%3A**%20arrays%20instead%20of%20lists%2C%20vectorised%20arithmetic%20with%20no%20loop%20needed%2C%20indexing%2Fslicing%2Fboolean%20masking%2C%20a%20toolbox%20of%20elementwise%20functions%2C%20reproducible%20randomness%20via%20%60default_rng(seed)%60%2C%20%60%40%60%20and%20%60.T%60%20for%20matrices.%0A%20%20%20%20-%20**SciPy%3A**%20ready-made%20numerical%20routines%20%E2%80%94%20%60solve_ivp%60%20for%20ODEs%2C%20%60curve_fit%60%2F%60least_squares%60%20for%20fitting%2C%20%60null_space%60%20for%20linear%20algebra%20%E2%80%94%20used%20as%20tools%2C%20not%20built%20from%20scratch.%0A%20%20%20%20-%20**Matplotlib%20(%60plt%60)%3A**%20%60fig%2C%20ax%20%3D%20plt.subplots()%60%2C%20then%20%60ax.plot%60%2F%60.scatter%60%2F%60.step%60%2F...%20plus%20labels%2C%20a%20legend%2C%20and%20a%20grid.%0A%0A%20%20%20%20From%20here%2C%20every%20computing%20lecture%20and%20lab%20notebook%20in%20the%20course%20should%20read%20as%20a%20combination%20of%20exactly%20these%20pieces%20%E2%80%94%20nothing%20more%20exotic%20ever%20shows%20up.%20See%20%5BWorking%20with%20Marimo%5D(..%2Fgetting-started%2Fmarimo.html)%20for%20how%20to%20actually%20run%20those%20notebooks%2C%20and%20%5BWorking%20with%20Jupyter%5D(..%2Fgetting-started%2Fjupyter.html)%20for%20saving%20and%20submitting%20your%20own%20work.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
3552bbfd29b4971c1c9914f76fd66b6d