From 77683721eb99135542e4e8f554a900f11cbb00c7 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Mon, 17 Aug 2026 12:11:51 +1000 Subject: [PATCH] Seed ml translation: functions (calibration round 2, v0.3 rules) Regenerated under the round-1 rules rather than reopening the stale 2026-08-03 seed: engine QuantEcon/action-translation@8625221 (post-#272, glossary v0.3.0 + 18-rule set), model claude-sonnet-5, source lecture-python-programming@81d9734 (carries the #604 source-side fixes), init --localize none. Machine gates: headings 17/17 identical, zero transliterations, below-deixis and calque signatures clean; the one pinned-term FAIL is the documented returns verb-homograph false positive, see QuantEcon/action-translation#240. Co-Authored-By: Claude Fable 5 --- lectures/functions.md | 704 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 704 insertions(+) create mode 100644 lectures/functions.md diff --git a/lectures/functions.md b/lectures/functions.md new file mode 100644 index 0000000..e9839d6 --- /dev/null +++ b/lectures/functions.md @@ -0,0 +1,704 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst +kernelspec: + display_name: Python 3 + language: python + name: python3 +translation: + title: Functions + headings: + Overview: Overview + Function Basics: Function Basics + Function Basics::Built-In Functions: Built-In Functions + Function Basics::Third Party Functions: Third Party Functions + Defining Functions: Defining Functions + Defining Functions::Basic Syntax: Basic Syntax + Defining Functions::Keyword Arguments: Keyword Arguments + Defining Functions::The Flexibility of Python Functions: The Flexibility of Python Functions + 'Defining Functions::One-Line Functions: `lambda`': 'One-Line Functions: `lambda`' + Defining Functions::Why Write Functions?: Why Write Functions? + Applications: Applications + Applications::Random Draws: Random Draws + Applications::Adding Conditions: Adding Conditions + Recursive Function Calls (Advanced): Recursive Function Calls (Advanced) + Exercises: Exercises + Advanced Exercises: Advanced Exercises +--- + +(functions)= +```{raw} jupyter + +``` + +# Functions + +```{index} single: Python; User-defined functions +``` + +## Overview + +മിക്കവാറും എല്ലാ programming-ഉം നൽകുന്ന അതിയായി ഉപയോഗപ്രദമായ ഒരു construct ആണ് functions. + +നമ്മൾ ഇതിനകം പല functions-ഉം കണ്ടുകഴിഞ്ഞു, ഉദാഹരണത്തിന് + +* NumPy-യിലെ `sqrt()` function-ഉം +* built-in ആയ `print()` function-ഉം + +ഈ lecture-ൽ നമ്മൾ + +1. functions-നെ systematic ആയി treat ചെയ്യുകയും syntax-ഉം use-cases-ഉം cover ചെയ്യുകയും ചെയ്യും, ഒപ്പം +2. നമ്മുടെ സ്വന്തം user-defined functions എങ്ങനെ build ചെയ്യാമെന്ന് പഠിക്കും. + +താഴെ കാണുന്ന imports നമ്മൾ ഉപയോഗിക്കും. + +```{code-cell} ipython +import numpy as np +import matplotlib.pyplot as plt +``` + +## Function Basics + +ഒരു പ്രത്യേക task implement ചെയ്യുന്ന, പേരുള്ള ഒരു program-ന്റെ section ആണ് function. + +ഇതിനകം ധാരാളം functions നിലവിലുണ്ട്, അവയെ അതേപടി ഉപയോഗിക്കാം. + +ആദ്യം നമ്മൾ ഈ functions review ചെയ്യാം, എന്നിട്ട് നമ്മുടെ സ്വന്തം functions എങ്ങനെ build ചെയ്യാമെന്ന് discuss ചെയ്യാം. + +### Built-In Functions + +`import` ഇല്ലാതെ ലഭ്യമായ കുറേ **built-in** functions Python-ൽ ഉണ്ട്. + +ഇവയിൽ ചിലത് നമ്മൾ ഇതിനകം കണ്ടുകഴിഞ്ഞു + +```{code-cell} python3 +max(19, 20) +``` + +```{code-cell} python3 +print('foobar') +``` + +```{code-cell} python3 +str(22) +``` + +```{code-cell} python3 +type(22) +``` + +Python built-ins-ന്റെ പൂർണ്ണമായ list [ഇവിടെ](https://docs.python.org/3/library/functions.html) കാണാം. + + +### Third Party Functions + +built-in functions നമുക്ക് വേണ്ടത് cover ചെയ്യുന്നില്ലെങ്കിൽ, നമുക്ക് ഒന്നുകിൽ functions import ചെയ്യേണ്ടിവരും, അല്ലെങ്കിൽ സ്വന്തമായി create ചെയ്യേണ്ടിവരും. + +functions import ചെയ്ത് ഉപയോഗിക്കുന്നതിന്റെ ഉദാഹരണങ്ങൾ {doc}`previous lecture `-ൽ കൊടുത്തിരുന്നു. + +ഒരു നൽകിയ വർഷം leap year ആണോ എന്ന് test ചെയ്യുന്ന മറ്റൊരു ഉദാഹരണം താഴെ കാണാം: + +```{code-cell} python3 +import calendar +calendar.isleap(2024) +``` + +## Defining Functions + +പല അവസരങ്ങളിലും നമ്മുടെ സ്വന്തം functions define ചെയ്യാൻ കഴിയുന്നത് ഉപയോഗപ്രദമാണ്. + +അത് എങ്ങനെ ചെയ്യാമെന്ന് discuss ചെയ്തുകൊണ്ട് തുടങ്ങാം. + +### Basic Syntax + +$f(x) = 2 x + 1$ എന്ന mathematical function implement ചെയ്യുന്ന വളരെ simple ആയ ഒരു Python function താഴെ കാണാം + +```{code-cell} python3 +def f(x): + return 2 * x + 1 +``` + +ഇപ്പോൾ നമ്മൾ ഈ function define ചെയ്തുകഴിഞ്ഞു, ഇനി അതിനെ *call* ചെയ്ത് അത് നമ്മൾ പ്രതീക്ഷിക്കുന്നത് ചെയ്യുന്നുണ്ടോ എന്ന് check ചെയ്യാം: + +```{code-cell} python3 +f(1) +``` + +```{code-cell} python3 +f(10) +``` + +നൽകിയ ഒരു number-ന്റെ absolute value compute ചെയ്യുന്ന, കുറച്ചുകൂടെ നീളമുള്ള ഒരു function താഴെ കാണാം. + +(ഇത്തരമൊരു function built-in ആയി ഇതിനകം നിലവിലുണ്ട്, പക്ഷേ exercise-ന് വേണ്ടി നമുക്ക് സ്വന്തമായി ഒന്ന് എഴുതാം.) + +```{code-cell} python3 +def new_abs_function(x): + if x < 0: + abs_value = -x + else: + abs_value = x + return abs_value +``` + +ഇവിടെയുള്ള syntax review ചെയ്യാം. + +* function definitions തുടങ്ങാൻ ഉപയോഗിക്കുന്ന Python keyword ആണ് `def`. +* `def new_abs_function(x):` എന്നത് indicate ചെയ്യുന്നത് function-ന്റെ പേര് `new_abs_function` എന്നാണെന്നും, അതിന് `x` എന്ന ഒരു argument ഉണ്ടെന്നുമാണ്. +* indent ചെയ്ത code, *function body* എന്ന് വിളിക്കുന്ന ഒരു code block ആണ്. +* calling code-ലേക്ക് return ചെയ്യേണ്ട object `abs_value` ആണെന്ന് `return` keyword indicate ചെയ്യുന്നു. + +ഈ function definition മുഴുവനും Python interpreter വായിച്ച് memory-യിൽ store ചെയ്യുന്നു. + +ഇത് പ്രവർത്തിക്കുന്നുണ്ടോ എന്ന് check ചെയ്യാൻ അതിനെ call ചെയ്യാം: + +```{code-cell} python3 +print(new_abs_function(3)) +print(new_abs_function(-3)) +``` + + +ഒരു function-ന് അനിയന്ത്രിതമായി എത്ര `return` statements വേണമെങ്കിലും (പൂജ്യം ഉൾപ്പെടെ) ഉണ്ടാകാം എന്നത് ശ്രദ്ധിക്കുക. + +ആദ്യത്തെ return hit ചെയ്യുമ്പോൾ function-ന്റെ execution അവസാനിക്കുന്നു, ഇത് താഴെ കാണുന്ന ഉദാഹരണം പോലുള്ള code സാധ്യമാക്കുന്നു + +```{code-cell} python3 +def f(x): + if x < 0: + return 'negative' + return 'nonnegative' +``` + +(multiple return statements ഉള്ള functions എഴുതുന്നത് സാധാരണയായി discourage ചെയ്യപ്പെടുന്നു, കാരണം അത് logic follow ചെയ്യാൻ ബുദ്ധിമുട്ടാക്കും.) + +return statement ഇല്ലാത്ത functions സ്വയമേവ പ്രത്യേക Python object ആയ `None` return ചെയ്യുന്നു. + +(pos_args)= +### Keyword Arguments + +```{index} single: Python; keyword arguments +``` + +ഒരു {ref}`previous lecture `-ൽ, നിങ്ങൾ ഈ statement കണ്ടിരുന്നു + +```{code-block} python3 +:class: no-execute + +plt.plot(x, 'b-', label="white noise") +``` + +Matplotlib-ന്റെ `plot` function-ലേക്കുള്ള ഈ call-ൽ, അവസാനത്തെ argument `name=argument` syntax-ൽ pass ചെയ്യുന്നത് ശ്രദ്ധിക്കുക. + +ഇതിനെ *keyword argument* എന്ന് വിളിക്കുന്നു, `label` ആണ് ഇവിടെ keyword. + +order അനുസരിച്ച് അർത്ഥം നിശ്ചയിക്കപ്പെടുന്നതിനാൽ, non-keyword arguments-നെ *positional arguments* എന്ന് വിളിക്കുന്നു + +* `plot(x, 'b-')`, `plot('b-', x)`-ൽ നിന്നും വ്യത്യസ്തമാണ് + +ഒരു function-ന് ധാരാളം arguments ഉള്ളപ്പോൾ keyword arguments പ്രത്യേകിച്ചും ഉപയോഗപ്രദമാണ്, കാരണം അപ്പോൾ ശരിയായ order ഓർത്തിരിക്കാൻ ബുദ്ധിമുട്ടാണ്. + +user-defined functions-ൽ keyword arguments ഒരു ബുദ്ധിമുട്ടും കൂടാതെ നിങ്ങൾക്ക് adopt ചെയ്യാം. + +അടുത്ത ഉദാഹരണം syntax illustrate ചെയ്യുന്നു + +```{code-cell} python3 +def f(x, a=1, b=1): + return a + b * x +``` + +`f`-ന്റെ definition-ൽ നമ്മൾ നൽകിയ keyword argument values, default values ആയി മാറുന്നു + +```{code-cell} python3 +f(2) +``` + +താഴെ കാണുന്ന രീതിയിൽ അവയെ modify ചെയ്യാം + +```{code-cell} python3 +f(2, a=4, b=5) +``` + +### The Flexibility of Python Functions + +{ref}`previous lecture `-ൽ നമ്മൾ discuss ചെയ്തതുപോലെ, Python functions വളരെ flexible ആണ്. + +പ്രത്യേകിച്ചും + +* ഒരു നൽകിയ file-ൽ എത്ര functions വേണമെങ്കിലും define ചെയ്യാം. +* Functions മറ്റ് functions-ന് ഉള്ളിൽ define ചെയ്യാൻ കഴിയും (ഇത് പലപ്പോഴും ചെയ്യാറുമുണ്ട്). +* മറ്റ് functions ഉൾപ്പെടെ ഏത് object-നെയും ഒരു function-ലേക്ക് argument ആയി pass ചെയ്യാം. +* Functions ഉൾപ്പെടെ ഏത് തരം object-ഉം ഒരു function-ന് return ചെയ്യാൻ കഴിയും. + +ഒരു function-ലേക്ക് ഒരു function pass ചെയ്യുന്നത് എത്ര straightforward ആണെന്നതിന്റെ ഉദാഹരണങ്ങൾ താഴെയുള്ള sections-ൽ നമ്മൾ നൽകും. + +### One-Line Functions: `lambda` + +```{index} single: Python; lambda functions +``` + +ഒരു line-ൽ simple functions create ചെയ്യാൻ `lambda` keyword ഉപയോഗിക്കുന്നു. + +ഉദാഹരണത്തിന്, ഈ definitions + +```{code-cell} python3 +def f(x): + return x**3 +``` + +ഒപ്പം + +```{code-cell} python3 +f = lambda x: x**3 +``` + +എന്നിവ പൂർണ്ണമായും equivalent ആണ്. + +`lambda` എന്തുകൊണ്ട് ഉപയോഗപ്രദമാണെന്ന് കാണാൻ, നമുക്ക് $\int_0^2 x^3 dx$ calculate ചെയ്യണമെന്ന് കരുതുക (നമ്മുടെ high-school calculus മറന്നുപോയി എന്നും കരുതുക). + +SciPy library-ൽ ഈ calculation നമുക്ക് വേണ്ടി ചെയ്യുന്ന `quad` എന്നൊരു function ഉണ്ട്. + +`quad` function-ന്റെ syntax `quad(f, a, b)` ആണ്, ഇവിടെ `f` ഒരു function ആണ്, `a`-ഉം `b`-ഉം numbers ആണ്. + +$f(x) = x^3$ എന്ന function create ചെയ്യാൻ നമുക്ക് `lambda` താഴെ കാണുന്ന രീതിയിൽ ഉപയോഗിക്കാം + +```{code-cell} python3 +from scipy.integrate import quad + +quad(lambda x: x**3, 0, 2) +``` + +ഇവിടെ `lambda` സൃഷ്ടിച്ച function-ന് ഒരു പേരും നൽകാത്തതിനാൽ അതിനെ *anonymous* എന്ന് പറയുന്നു. + + +### Why Write Functions? + +നിങ്ങളുടെ code-ന്റെ clarity മെച്ചപ്പെടുത്താൻ user-defined functions പ്രധാനമാണ്, കാരണം അവ + +* വ്യത്യസ്ത logic strands-നെ separate ചെയ്യുന്നു +* code reuse facilitate ചെയ്യുന്നു + +(ഒരേ കാര്യം രണ്ട് തവണ എഴുതുന്നത് [മിക്ക സമയത്തും ഒരു മോശം ആശയമാണ്](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)) + +ഇതിനെക്കുറിച്ച് {doc}`later ` നമ്മൾ കൂടുതൽ പറയും. + +## Applications + +### Random Draws + +{doc}`previous lecture `-ലെ ഈ code വീണ്ടും കണക്കിലെടുക്കാം + +```{code-cell} python3 +rng = np.random.default_rng() + +ts_length = 100 +ϵ_values = [] # empty list + +for i in range(ts_length): + e = rng.standard_normal() + ϵ_values.append(e) + +plt.plot(ϵ_values) +plt.show() +``` + +ഈ program-നെ നമ്മൾ രണ്ട് ഭാഗങ്ങളായി break down ചെയ്ത്: + +1. random variables-ന്റെ ഒരു list generate ചെയ്യുന്ന user-defined function. +1. program-ന്റെ പ്രധാന ഭാഗം, അത് + 1. data ലഭിക്കാൻ ഈ function call ചെയ്യുന്നു + 1. data plot ചെയ്യുന്നു + +ഇത് അടുത്ത program-ൽ accomplish ചെയ്യപ്പെടുന്നു + +(funcloopprog)= +```{code-cell} python3 +def generate_data(n): + ϵ_values = [] + for i in range(n): + e = rng.standard_normal() + ϵ_values.append(e) + return ϵ_values + +data = generate_data(100) +plt.plot(data) +plt.show() +``` + +interpreter `generate_data(100)` എന്ന expression-ൽ എത്തുമ്പോൾ, `n`, 100-ന് equal ആയി set ചെയ്ത് function body execute ചെയ്യുന്നു. + +ഇതിന്റെ net result, `data` എന്ന പേര് function return ചെയ്ത `ϵ_values` എന്ന list-ലേക്ക് *bind* ചെയ്യപ്പെടും എന്നതാണ്. + +### Adding Conditions + +```{index} single: Python; Conditions +``` + +നമ്മുടെ `generate_data()` function കുറച്ചൊക്കെ limited ആണ്. + +ആവശ്യമുള്ളപ്പോൾ $(0, 1)$-ൽ standard normals-ഓ uniform random variables-ഓ return ചെയ്യാനുള്ള കഴിവ് നൽകി, ഇതിനെ കുറച്ചുകൂടെ ഉപയോഗപ്രദമാക്കാം. + +താഴെയുള്ള code piece-ൽ ഇത് achieve ചെയ്യപ്പെടുന്നു. + +(funcloopprog2)= +```{code-cell} python3 +def generate_data(n, generator_type): + ϵ_values = [] + for i in range(n): + if generator_type == 'U': + e = rng.uniform(0, 1) + else: + e = rng.standard_normal() + ϵ_values.append(e) + return ϵ_values + +data = generate_data(100, 'U') +plt.plot(data) +plt.show() +``` + +if/else clause-ന്റെ syntax self-explanatory ആണെന്ന് പ്രതീക്ഷിക്കുന്നു, code blocks-ന്റെ extent വീണ്ടും indentation delimit ചെയ്യുന്നു. + +Notes + +* `U` എന്ന argument ഒരു string ആയാണ് നമ്മൾ pass ചെയ്യുന്നത്, അതുകൊണ്ടാണ് നമ്മൾ അതിനെ `'U'` എന്ന് എഴുതുന്നത്. +* equality test ചെയ്യുന്നത് `==` syntax ഉപയോഗിച്ചാണ്, `=` അല്ല എന്നത് ശ്രദ്ധിക്കുക. + * ഉദാഹരണത്തിന്, `a = 10` എന്ന statement `a` എന്ന പേരിനെ `10` എന്ന value-യിലേക്ക് assign ചെയ്യുന്നു. + * `a == 10` എന്ന expression, `a`-യുടെ value അനുസരിച്ച് `True`-ഓ `False`-ഓ ആയി evaluate ചെയ്യപ്പെടും. + +ഇനി, മുകളിലുള്ള code simplify ചെയ്യാൻ പല വഴികളും ഉണ്ട്. + +ഉദാഹരണത്തിന്, ആവശ്യമുള്ള generator type-നെ ഒരു function, method, അല്ലെങ്കിൽ മറ്റേതെങ്കിലും [callable](https://typing.python.org/en/latest/spec/callables.html) object ആയി pass ചെയ്തുകൊണ്ട് conditionals എല്ലാം ഒഴിവാക്കാം. + +ഇത് മനസ്സിലാക്കാൻ, താഴെയുള്ള version കണക്കിലെടുക്കുക. + +(test_program_6)= +```{code-cell} python3 +def generate_data(n, generator_type): + ϵ_values = [] + for i in range(n): + e = generator_type() + ϵ_values.append(e) + return ϵ_values + +data = generate_data(100, rng.uniform) +plt.plot(data) +plt.show() +``` + +ഇനി, `generate_data()` function call ചെയ്യുമ്പോൾ, രണ്ടാമത്തെ argument ആയി നമ്മൾ `rng.uniform` pass ചെയ്യുന്നു. + +ഈ object ഒരു *callable* ആണ് — അതായത്, parentheses ഉപയോഗിച്ച് call ചെയ്യാൻ കഴിയുന്ന object. + +`generate_data(100, rng.uniform)` എന്ന function call execute ചെയ്യുമ്പോൾ, `n`, 100-ന് equal ആയും `generator_type` എന്ന പേര് `rng.uniform` എന്ന callable-ലേക്ക് "bound" ആയും വച്ചുകൊണ്ട് Python function code block run ചെയ്യുന്നു. + +* ഈ lines execute ചെയ്യുന്ന സമയത്ത്, `generator_type`-ഉം `rng.uniform`-ഉം "synonyms" ആണ്, അവ ഒരേപോലെ ഉപയോഗിക്കാം. + +ഈ principle കൂടുതൽ generally-യിലും പ്രവർത്തിക്കുന്നു --- ഉദാഹരണത്തിന്, താഴെയുള്ള code piece കണക്കിലെടുക്കുക + +```{code-cell} python3 +max(7, 2, 4) # max() is a built-in Python function +``` + +```{code-cell} python3 +m = max +m(7, 2, 4) +``` + +ഇവിടെ built-in function ആയ `max()`-ന് നമ്മൾ മറ്റൊരു പേര് create ചെയ്തു, അത് ഒരേപോലെ ഉപയോഗിക്കാൻ കഴിയും. + +നമ്മുടെ program-ന്റെ context-ൽ, functions-ലേക്ക്, അല്ലെങ്കിൽ more generally callable objects-ലേക്ക്, പേരുകൾ bind ചെയ്യാനുള്ള ഈ കഴിവ് അർത്ഥമാക്കുന്നത്, മുകളിൽ `rng.uniform`-ഉം ചെയ്തതുപോലെ, ഒരു callable object-നെ മറ്റൊരു callable-ലേക്ക് argument ആയി pass ചെയ്യുന്നതിൽ ഒരു പ്രശ്നവുമില്ല എന്നാണ്. + + +(recursive_functions)= +## Recursive Function Calls (Advanced) + +```{index} single: Python; Recursion +``` + +ഇത് ഒരു advanced topic ആണ്, ഇത് skip ചെയ്യാൻ നിങ്ങൾക്ക് സ്വാതന്ത്ര്യമുണ്ട്. + +അതേസമയം, ഇത് ഒരു neat ആശയമാണ്, നിങ്ങളുടെ programming career-ന്റെ ഏതെങ്കിലും ഘട്ടത്തിൽ ഇത് പഠിക്കണം. + +അടിസ്ഥാനപരമായി, ഒരു recursive function എന്നത് സ്വയം call ചെയ്യുന്ന ഒരു function ആണ്. + +ഉദാഹരണത്തിന്, ഏതെങ്കിലും t-ന് $x_t$ compute ചെയ്യുന്ന problem കണക്കിലെടുക്കുക, ഇവിടെ + +```{math} +:label: xseqdoub + +x_{t+1} = 2 x_t, \quad x_0 = 1 +``` + +വ്യക്തമായും ഉത്തരം $2^t$ ആണ്. + +ഒരു loop ഉപയോഗിച്ച് നമുക്ക് ഇത് എളുപ്പത്തിൽ compute ചെയ്യാം + +```{code-cell} python3 +def x_loop(t): + x = 1 + for i in range(t): + x = 2 * x + return x +``` + +താഴെ കാണുന്ന രീതിയിൽ ഒരു recursive solution-ഉം നമുക്ക് ഉപയോഗിക്കാം + +```{code-cell} python3 +def x(t): + if t == 0: + return 1 + else: + return 2 * x(t-1) +``` + +ഇവിടെ സംഭവിക്കുന്നത്, ഓരോ തുടർച്ചയായ call-ഉം *stack*-ൽ അതിന്റേതായ *frame* ഉപയോഗിക്കുന്നു എന്നതാണ് + +* ഒരു നൽകിയ function call-ന്റെ local variables സൂക്ഷിക്കുന്ന സ്ഥലമാണ് frame +* function calls process ചെയ്യാൻ ഉപയോഗിക്കുന്ന memory ആണ് stack + * ഒരു last-in, first-out (LIFO) data structure + +ഈ ഉദാഹരണം കുറച്ച് contrived ആണ്, കാരണം സാധാരണയായി ആദ്യത്തെ (iterative) solution ആണ് recursive solution-നേക്കാൾ preferred ആയിരിക്കുക. + +recursion-ന്റെ കുറച്ചുകൂടെ contrived അല്ലാത്ത applications നമ്മൾ പിന്നീട് കാണും. + + +(factorial_exercise)= +## Exercises + +```{exercise-start} +:label: func_ex1 +``` + +$n!$ എന്നത് "$n$ factorial" എന്ന് വായിക്കപ്പെടുന്നു എന്നും, $n! = n \times (n - 1) \times \cdots \times 2 \times 1$ എന്ന് define ചെയ്യപ്പെടുന്നു എന്നും ഓർക്കുക. + +ഇവിടെ $n$-നെ ഒരു positive integer ആയി മാത്രമേ നമ്മൾ കണക്കിലെടുക്കൂ. + +വ്യത്യസ്ത modules-ൽ ഇത് compute ചെയ്യാൻ functions ഉണ്ട്, പക്ഷേ ഒരു exercise ആയി നമുക്ക് സ്വന്തം version എഴുതാം. + +പ്രത്യേകിച്ചും, ഏതെങ്കിലും positive integer $n$-ന്, `factorial(n)`, $n!$ return ചെയ്യുന്ന വിധത്തിൽ `factorial` എന്നൊരു function എഴുതുക. + +```{exercise-end} +``` + + +```{solution-start} func_ex1 +:class: dropdown +``` + +Here's one solution: + +```{code-cell} python3 +def factorial(n): + k = 1 + for i in range(n): + k = k * (i + 1) + return k + +factorial(4) +``` + + +```{solution-end} +``` + + +```{exercise-start} +:label: func_ex2 +``` + +[Binomial random variable](https://en.wikipedia.org/wiki/Binomial_distribution) $Y \sim Bin(n, p)$, $n$ binary trials-ൽ ഉള്ള successes-ന്റെ എണ്ണത്തെ represent ചെയ്യുന്നു, ഇവിടെ ഓരോ trial-ഉം $p$ probability-യിൽ succeed ചെയ്യുന്നു. + +`rng = np.random.default_rng()` ഉപയോഗിച്ച്, `binomial_rv(n, p)`, $Y$-യുടെ ഒരു draw generate ചെയ്യുന്ന വിധത്തിൽ `binomial_rv` എന്നൊരു function എഴുതുക. + +```{hint} +:class: dropdown + +If $U$ is uniform on $(0, 1)$ and $p \in (0,1)$, then the expression `U < p` evaluates to `True` with probability $p$. +``` + +```{exercise-end} +``` + + +```{solution-start} func_ex2 +:class: dropdown +``` + +Here is one solution: + +```{code-cell} python3 +rng = np.random.default_rng() + +def binomial_rv(n, p): + count = 0 + for i in range(n): + U = rng.uniform() + if U < p: + count = count + 1 # Or count += 1 + return count + +binomial_rv(10, 0.5) +``` + +```{solution-end} +``` + + +```{exercise-start} +:label: func_ex3 +``` + +ആദ്യം, താഴെയുള്ള random device-ന്റെ ഒരു realization return ചെയ്യുന്ന ഒരു function എഴുതുക + +1. ഒരു unbiased coin 10 തവണ flip ചെയ്യുക. +1. ഈ sequence-ൽ head, `k` തവണയോ അതിലധികമോ consecutively ഒരു തവണയെങ്കിലും വന്നാൽ, ഒരു dollar pay ചെയ്യുക. +1. ഇല്ലെങ്കിൽ, ഒന്നും pay ചെയ്യരുത്. + +രണ്ടാമതായി, മുകളിലുള്ള random device-ന്റെ രണ്ടാമത്തെ rule താഴെപ്പറയുന്ന വിധത്തിൽ ആകുന്നത് ഒഴികെ, ഇതേ task ചെയ്യുന്ന മറ്റൊരു function എഴുതുക + +- ഈ sequence-ൽ head `k` തവണയോ അതിലധികമോ വന്നാൽ, ഒരു dollar pay ചെയ്യുക. + +random numbers generate ചെയ്യാൻ `rng = np.random.default_rng()` ഉപയോഗിക്കുക. + +```{exercise-end} +``` + +```{solution-start} func_ex3 +:class: dropdown +``` + +ആദ്യത്തെ random device-ന് ഒരു function താഴെ കാണാം. + + + + +```{code-cell} python3 +rng = np.random.default_rng() + +def draw(k): # pays if k consecutive successes in a sequence + + payoff = 0 + count = 0 + + for i in range(10): + U = rng.uniform() + count = count + 1 if U < 0.5 else 0 + print(count) # print counts for clarity + if count == k: + payoff = 1 + + return payoff + +draw(3) +``` + +രണ്ടാമത്തെ random device-ന് വേണ്ടിയുള്ള മറ്റൊരു function താഴെ കാണാം. + +```{code-cell} python3 +def draw_new(k): # pays if k successes in a sequence + + payoff = 0 + count = 0 + + for i in range(10): + U = rng.uniform() + count = count + ( 1 if U < 0.5 else 0 ) + print(count) + if count == k: + payoff = 1 + + return payoff + +draw_new(3) +``` + +```{solution-end} +``` + + +## Advanced Exercises + +താഴെയുള്ള exercises-ൽ, നമ്മൾ ഒരുമിച്ച് recursive functions എഴുതും. + + +```{exercise-start} +:label: func_ex4 +``` + +The Fibonacci numbers are defined by + +```{math} +:label: fib + +x_{t+1} = x_t + x_{t-1}, \quad x_0 = 0, \; x_1 = 1 +``` + +The first few numbers in the sequence are $0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55$. + +Write a function to recursively compute the $t$-th Fibonacci number for any $t$. + +```{exercise-end} +``` + +```{solution-start} func_ex4 +:class: dropdown +``` + +Here's the standard solution + +```{code-cell} python3 +def x(t): + if t == 0: + return 0 + if t == 1: + return 1 + else: + return x(t-1) + x(t-2) +``` + +Let's test it + +```{code-cell} python3 +print([x(i) for i in range(10)]) +``` + +```{solution-end} +``` + +```{exercise-start} +:label: func_ex5 +``` + +[Exercise 1](factorial_exercise)-ലെ `factorial()` function-നെ recursion ഉപയോഗിച്ച് വീണ്ടും എഴുതുക. + +```{exercise-end} +``` + +```{solution-start} func_ex5 +:class: dropdown +``` + +Here's the standard solution + +```{code-cell} python3 +def recursion_factorial(n): + if n == 1: + return n + else: + return n * recursion_factorial(n-1) +``` + +Let's test it + +```{code-cell} python3 +print([recursion_factorial(i) for i in range(1, 10)]) +``` + +```{solution-end} +```