-
Notifications
You must be signed in to change notification settings - Fork 3
chapter 3 and 4 changes done #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,24 +46,24 @@ The basic idea behind the solution is as follows: | |
| - The outer for loop goes through each element in the sequence $2, 3, ..., n$. `i` is the loop variable for this sequence. | ||
| - We begin with the guess that `i` is prime. In code, we do this by setting `flag` to be `True`. | ||
| - Now, we go through all potential divisors of `i`. This is represented by the sequence $2, 3, ..., i - 1$. Variable `j` is the loop variable for this sequence. Notice how the sequence for the inner loop is dependent on `i`, the loop variable for the outer loop. | ||
| - If `j` divides `i`, then `i` cannot be a prime. We correct our initial assumption by updating `flag` to `False` whenever this happens. As we know that `i` is not prime, there is no use of continuing with the inner-loop, so we break out of it. | ||
| - If `j` divides `i` at some point, then `i` cannot be a prime. We correct our initial assumption by updating `flag` to `False` whenever this happens. As we know that `i` is not prime, there is no use of continuing with the inner-loop, so we break out of it. | ||
| - If `j` doesn't divide `i` for any `j` in this sequence, then `i` is a prime. In such a situation, our initial assumption is right, and `flag` stays `True`. | ||
| - Once we are outside the inner-loop, we check if `flag` is `True`. if that is the case, then we increment count as we have hit upon a prime number. | ||
| - Once we are outside the inner-loop, we check if `flag` is `True`. If this is the case, then we increment count as we have hit upon a prime number. | ||
|
|
||
| Some important points regarding nested loops: | ||
|
|
||
| - Nesting is not restricted to `#!py for` loops. Any one of the following combinations is possible: | ||
| - `#!py for` inside `#!py for` | ||
| - `#!py for` inside `#!py while` | ||
| - `#!py while` inside `#!py while` | ||
| - `#!py while` inside `#!py for` | ||
| - `#!py for` inside `#!py for` | ||
| - `#!py for` inside `#!py while` | ||
| - `#!py while` inside `#!py while` | ||
| - `#!py while` inside `#!py for` | ||
| - Multiple levels of nesting is possible. | ||
|
|
||
|
|
||
|
|
||
| ## `#!py while` versus `#!py for` | ||
|
|
||
| `#!py for` loops are typically used in situations where the number of iterations can be quantified, whereas `#!py while` loops are used in situations where the number of iterations cannot be quantified exactly. This doesn't mean that the number of iterations in a `#!py for` loop is always constant. For example: | ||
| `#!py for` loops are typically used in situations where the number of iterations can be quantified and is known in advance, whereas `#!py while` loops are used in situations where the number of iterations cannot be quantified exactly. This doesn't mean that the number of iterations in a `#!py for` loop is always constant. For example: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it is necessary to know the number of iterations in advance to use a for loop. For example, for i in range(int(input())):
print(i)I think the entire paragraph doesn't really apply to python but rather to some other language like C or Java. In python, for loops are used to iterate over sequences such as lists, sets, generators, strings, etc., whereas while loops are used to execute a block of code while a condition is true.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually what I believe is being implied in this paragraph is that in
Many programming tutorials I've seen also introduce the use of |
||
|
|
||
| ```python linenums="1" | ||
| n = int(input()) | ||
|
|
@@ -83,7 +83,7 @@ The number of iterations in the above code can be determined only after it termi | |
|
|
||
|
|
||
|
|
||
| ## print: `end`, `sep` | ||
| ## `#!py print:` `end`,`sep` | ||
|
|
||
| ### `end` | ||
|
|
||
|
|
@@ -98,17 +98,17 @@ For a given value of `n`, say `n` = 9, we want the output to be: | |
| 1,2,3,4,5,6,7,8,9 | ||
| ``` | ||
|
|
||
| The following solution won't work: | ||
| Here's an attempt at solving this using the concepts learnt so far | ||
|
|
||
| ```python linenums="1" | ||
| n = int(input()) | ||
| for i in range(1, n + 1): | ||
| print(i, ',') | ||
| ``` | ||
|
|
||
| For `n` = 9, this will give the following output: | ||
| For `n` = 9, this will give the following output, certainly not what we need: | ||
|
|
||
| ``` linenums="1" | ||
| ``` | ||
| 1 , | ||
| 2 , | ||
| 3 , | ||
|
|
@@ -135,7 +135,9 @@ For `n` = 9, this will give the required output: | |
| 1,2,3,4,5,6,7,8,9 | ||
| ``` | ||
|
|
||
| Whenever we use the `#!py print()` function, it prints the expression passed to it and immediately follows it up by printing a newline. This is the default behaviour of `#!py print()`. It can be altered by using a special argument called `end`. The default value of `end` is set to the newline character. So, whenever the end argument is not explicitly specified in the print function, a newline is appended to the input expression by default. In the code given above, by setting `end` to be a comma, we are forcing the `#!py print()` function to insert a comma instead of a newline at the end of the expression passed to it. It is called `end` because it is added at the end. To get a better picture, consider the following code: | ||
| Whenever we use the `#!py print()` function, it prints the expression passed to it and immediately follows it up by printing a newline. This is the default behaviour of `#!py print()`. It can be altered by using a special argument called `end`. The default value of `end` is set to the newline character `#!py \n`[^1]. So, whenever the end argument is not explicitly specified in the print function, a newline is appended to the input expression by default. In the code given above, by setting `end` to be a comma, we are forcing the `#!py print()` function to insert a comma instead of a newline at the end of the expression passed to it. It is called `end` because it is added at the end. To get a better picture, consider the following code: | ||
|
aravinds-arv marked this conversation as resolved.
|
||
|
|
||
| [^1]: Remember [escape characters](../chapter-1/lesson-1.5.md/#escape-characters) from chapter 1? | ||
|
|
||
| ```python linenums="1" | ||
| print() | ||
|
|
@@ -148,13 +150,13 @@ print(3, end = ',') | |
|
|
||
| This output is: | ||
|
|
||
| ``` linenums="1" | ||
|
|
||
| ``` | ||
| ⠀ | ||
| ,1 | ||
| 1,2,3, | ||
| ``` | ||
|
|
||
| Even though nothing is being passed to the print function in the first line of code, the first line in the output is a newline because the default value of `end` is a newline character (`'\n'`). No expression is passed as input to print in the second line of code as well, but `end` is set to `,`. So, only a comma is printed. Notice that line 3 of the code is printed in line 2 of the output. This is because `end` was set to `,` instead of the newline character in line 2 of the code. | ||
| Even though nothing is being passed to the print function in the first line of code, the first line in the output is a newline because the default value of `end` is the newline character `\n`. No expression is passed as input to print in the second line of code either, but `end` is set to `,`. So, only a comma is printed. Notice that line 3 of the code is printed in line 2 of the output. This is because `end` was set to `,` instead of the newline character in line 2 of the code. | ||
|
|
||
|
|
||
|
|
||
|
|
@@ -172,7 +174,7 @@ The output is: | |
| this is cool | ||
| ``` | ||
|
|
||
| What if we do not want the space or if want some other separator? This can be done using `sep`: | ||
| What if we don't want the space or if want some other separator? This can be done using the `sep` arguement: | ||
|
|
||
| ```python | ||
| print('this', 'is', 'cool', sep = ',') | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| # Lesson-3.5 | ||
|
|
||
| ## Library | ||
| ## Library (Continued) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey, can you tell me why you added "continued" in parantheses?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a library lesson in some earlier chapter too where some other library was introduced.. so I thought we had to convey to the readers that this isn't the same lesson. Should I get rid of it 🫤? Or maybe we could do something like:
|
||
|
|
||
| We will look at two more libraries — `math` and `random` — and use them to solve some fascinating problems in mathematics. | ||
|
|
||
|
|
@@ -24,7 +24,7 @@ for n in range(1, 6): | |
|
|
||
| If we execute the above code, we get the following output: | ||
|
|
||
| ``` linenums="1" | ||
| ``` | ||
| n = 1, x_n = 1.414 | ||
| n = 2, x_n = 1.848 | ||
| n = 3, x_n = 1.962 | ||
|
|
@@ -54,7 +54,7 @@ for n in range(1, 20): | |
| print(x) | ||
| ``` | ||
|
|
||
| After just 20 iterations, the value is so close to two: `#!py 1.9999999999910236`. But we have used trial and error to decide when to terminate the iteration. A better way to do this is to define a tolerance: if the difference between the previous value and the current value in the sequence is less than some predefined value (tolerance), then we terminate the iteration. | ||
| After just 20 iterations, the value is so close to two: `#!py 1.9999999999910236`. But we have used trial and error to decide when to terminate the iteration. A better way to do this is to define a _tolerance_: if the difference between the previous value and the current value in the sequence is less than some predefined value (tolerance), then we terminate the iteration. | ||
|
|
||
| ```python linenums="1" | ||
| import math | ||
|
|
@@ -64,11 +64,16 @@ while abs(x_curr - x_prev) >= tol: | |
| x_prev = x_curr | ||
| x_curr = math.sqrt(2 + x_prev) | ||
| count += 1 | ||
| print(f'Value of x at {tol} tolerance is {x_curr}') | ||
| print(f'Value of x at {tol:.5f} tolerance is {x_curr}') | ||
| print(f'It took {count} iterations') | ||
| ``` | ||
|
|
||
| The output of the above code would be: | ||
|
|
||
| ``` | ||
| Value of x at 0.00001 tolerance is 1.9999976469034038 | ||
| It took 9 iterations | ||
| ``` | ||
|
|
||
| ### `random` | ||
|
|
||
|
|
@@ -79,11 +84,13 @@ import random | |
| print(random.choice('HT')) | ||
| ``` | ||
|
|
||
| That is all there is to it! `random` is a library and `#!py choice()` is a function defined in it. It accepts any sequence as input and returns an element chosen at random from this sequence. In this case, the input is a string, which is nothing but a sequence of characters. | ||
| That is all there is to it! `random` is a library and `#!py choice()` is a function defined in it. It accepts any sequence as input and returns an element chosen at random from this sequence. In this case, the input is a string, which is nothing but a sequence of characters and each time the code is run we get either of these characters, `H` or `T`. | ||
|
|
||
| We know that the probability of obtaining a head on a coin toss is 0.5. This is the theory. Is there a way to see this rule in action? Can we computationally verify if this is indeed the case? For that, we have to set up the following experiment. Toss a coin $n$ times and count the number of heads. Dividing the total number of heads by $n$ will give the empirical probability. As $n$ becomes large, this probability must approach 0.5. | ||
| We know that the probability of obtaining a head on a coin toss is 0.5. Atleast that's what theory says. Is there a way to see this rule in action? Can we computationally verify if this is indeed the case? For this, we need to set up an experiment: toss a coin $n$ times and count the number of heads. Dividing the total number of heads by $n$ will give the _empirical probability[^1]_. As $n$ becomes larger and larger, this probability must approach 0.5. | ||
|
|
||
| ```python | ||
| [^1]: Simply put [empirical probability](https://en.wikipedia.org/wiki/Empirical_probability) gives the likelihood of an event to occur based on past or historical data. | ||
|
|
||
| ```python linenums="1" | ||
| import random | ||
| n = int(input()) | ||
| heads = 0 | ||
|
|
@@ -107,12 +114,12 @@ Let us run the above code for different values of $n$ and tabulate our results: | |
| | 1,000,000 | 0.499983 | | ||
| </div> | ||
|
|
||
| The value is approaching `#!py 0.5` as expected! `random` is quite versatile. | ||
| The value is indeed approaching `#!py 0.5` as expected! | ||
|
|
||
| <!-- Replace this code block with a repl --> | ||
|
|
||
| !!! question "Exercise" | ||
| Let us now roll a dice! `randint(a, b)` returns a random integer $N$ such that $a \leq N \leq b$. | ||
| !!! question "Practice Problem" | ||
| Let us now try to simulate a die roll! `random.randint(a, b)` returns a random integer $N$ such that $a \leq N \leq b$. | ||
|
|
||
| ```python | ||
| import random | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.