# Khan Academy - Python
[https://www.khanacademy.org/computing/intro-to-python-fundamentals/x5279a44ae0ab15d6:computational-thinking-with-variables/x5279a44ae0ab15d6:arithmetic-expressions/pc/coupon-codes](https://)
In this course, you’ll use programming as a tool to design recommendation engines, simulate natural selection, invent game levels, and more. Through lessons designed with beginner programmers in mind, you'll learn how to read and write Python programs - no prior computer science experience required!
What you'll learn:
This course covers programming fundamentals in Python, including:
* Data types, expressions, and variables
* User input
* Boolean logic and conditionals
* Loops
* Module imports and random numbers
* Functions
## Challenge: Platform Tour
In a Challenge, there are three main panels: one for the instructions, one for the code editor where you write your program, and one for the console where your program output appears - but only after you **press the Run button!**
You should run your code frequently to test your changes and to spot any errors early.
Press the Run button.
On each run, the platform also evaluates your program to see if you correctly completed the instructions for the current step and are ready to move on to the next. Sometimes, it may even give you a free tip to help you along!
```
names= "Paggie's"
course_1= "Khan Academy Python"
print(f"\nThe is {names} the first {course_1} notes session")
```
## For loop session
```
lists = []
for i in range(2, 65, 2):
lists.append(i)
print(lists)
```
Changes made:
Initialized an empty list called lists.
Utilized a for loop with range(2, 65, 2) to generate even numbers from 2 to 64 (the range function increments by 2).
Used lists.append(i) to add each even number to the lists list.
Finally, printed the lists containing all the even numbers.
This will correctly generate a list containing even numbers from 2 to 64.
## Math Session
```
print("2" + "7")
print(2 + 7)
```
## Challenge: Pair programming
When Keisha runs her program, she gets an error. She forgot to test her code as she went, so there might be several different bugs hiding. She suggests you pair program to fix them together!
Run the program and examine the error message in the console.
Use the error message and linter to identify and fix the bug.
Repeat, until the program runs without any errors.
Pay attention to the line of code that the error message points to. Be sure to keep the intent of the program the same - Keisha won’t be satisfied if you just delete lines of code!
```
print("Evaluating string expressions...")
# What does each string expression evaluate to?
print("python" + "3") # This will concatenate strings: "python3"
print("computer" + " " + "programming") # This will concatenate strings with a space in between: "computer programming"
print("\n\n\n") # This will print three empty lines
# Display a divider surrounded by blank lines.
print()
print("----------")
print()
print("Evaluating integer and float expressions...")
# What does each numeric expression evaluate to?
print(4 + 3.1 + 5.8) # This will perform numeric addition: 12.9
print()
print("----------")
print()
print(40 + 7) # This will add two integers: 47
print(1.5 + 1.5) # This will add two floats: 3.0
print(float("2.00000")) # This will convert the string to a float: 2.0
print(-1 + 0.66) # This will add a negative integer and a float: -0.34
```
```
drink1 = "tea"
drink2 = "juice"
drink1 = drink2
print(drink1)
drink2 = drink1
print(drink2)
```
juice
juice
## Challenge: URL paths
Sofia wants to help users navigate around the Khan Academy site by constructing **URLs to different pages.**
The site offers content in several languages, indicated in the URL by a language code like **es or pt**. Sofia often uses the Portuguese site at pt, but she wants her program to show the Spanish site by default.
Modify the first assignment statement to assign the value **"es"** to the variable language_code.
You’ll need to replace the value **"pt"** with the value **"es"**. When the program accesses language_code to construct the url, it should contain the value "es".
```
# Language codes include "pt" for Portuguese and "es" for Spanish.
language_code = "es"
# Subjects can be math, science, computing, or humanities.
subject = "computing"
url = "https://" + language_code + ".khanacademy.org/" + subject
print("Navigate to the page below!")
print(url)
```
## Questions.
Instead of always pointing to the computing page, Sofia wants to let the user to choose their subject. Subjects include math, science, computing, and humanities, where the names are in all lowercase letters.
Add a new input() prompt that asks the user to enter a lowercase subject name.
Modify the program to print the URL for the subject the user entered.
You’ll need to assign the result of the input() call to the variable subject. When the program accesses subject to construct the url, it should contain the value the user entered.
```
# Language codes include "pt" for Portuguese and "es" for Spanish.
language_code = "es"
# Subjects can be math, science, computing, or humanities.
subject = input( "Enter the subject:" )
print(f"The subject select is {subject}")
url = "https://" + language_code + ".khanacademy.org/" + subject
print("Navigate to the page below!")
print(url)
```
## Evaluate arithmetic expressions
```
message= 3
print(str(message)+" in the message inbox")
print( f"{message} in the message inbox")
```
Above two answers have the same results
### Function
min(b, c) Returns the smaller number out of b and c.
### Challenge: Coupon codes
Travis saved up to buy a new pair of cleats. He wants to make sure he gets the best price, so he built a browser extension to help him compare coupon codes.
The cleats currently cost $99.99, but when Travis runs the program and enters 99.99 at the prompt, he gets a TypeError.
Identify and add the two missing type conversions such that the program runs without any errors.
Recall that you can convert between data types with the str(), int(), and float() functions. The format of the program output should not change.
```
base_price = float(input("Enter cart total: "))
# Available coupon codes include 15% off and $12 off.
percent_discount = base_price - base_price * .15
fixed_discount = base_price - 12
# Pick the coupon that offers the best discount.
final_price = min(fixed_discount, percent_discount)
print("Your best price is $" + str(final_price))
```
Check the **int(), str(), and float()**
when computing and print it out
### Questions.
One more cleanup! Travis notices that the final price often has many decimal places, like 84.9915. He wants to round to the nearest cent.
Round the final price to two decimal places.
Recall that the round() function takes two arguments - the number to round followed by the number of decimal places to round to. For example, round(3.141592, 4) evaluates to 3.1416.
```
def binary_search(arr, target):
low, high = 0, len(arr) - 1
while low <= high:
mid = (low + high) // 2
mid_val = arr[mid]
if mid_val == target:
return mid # Target found
elif mid_val < target:
low = mid + 1
else:
high = mid - 1
return -1 # Target not found
# Example usage
prime_numbers = [2, 3, 5, 7, 11, 13, ..., 307, 311] # Your sorted array of prime numbers
target_number = 52
index = binary_search(prime_numbers, target_number)
if index != -1:
print(f"{target_number} is prime, found at index {index}.")
else:
print(f"{target_number} is not prime.")
```
Binary search is an efficient algorithm for finding a specific value in a sorted array. The number of items examined by binary search can be calculated using the formula
⌈log2(n)], where n is the number of items in the array. In this case, � =64
n=64, so the number of items examined would be
⌈log2(64)]=6
So, binary search would have to examine about 6 items in the array to conclude that 52 is not present.
> ### DIFFERENCES !!!!!!
> (low + high) // 2 **(Integer Division)**:
> (low + high) / 2 **(Floating-Point Division)**:
Result: The result of this expression is an integer.
Example: If low is 3 and high is 7, then (low + high) // 2 would result in 5 (floor of the average).
(low + high) / 2 (Floating-Point Division):
Result: The result of this expression is a floating-point number.
Example: Using the same example, if low is 3 and high is 7, then (low + high) / 2 would result in 5.0 (exact average).
### Questions.
In 2013, there were 193 member states in the United Nations. If the names of these states were sorted alphabetically in an array, about how many names would binary search examine to locate a particular name in the array, in the worst case?
**Ansewer**
NO MORE THAN 8
= log2(193) = 7..
### Questions.
The 2014 "Catalogue of Life" contains about 1580000 names of species. If these names were sorted in an array, in the worst case, how long would it take to use binary search to find the name of a particular species in the array?
**Answer**
At most, it would look at 21 names.
## Asymptotic notation
So far, we analyzed linear search and binary search by counting the maximum number of guesses we need to make. But what we really want to know is how long these algorithms take. We're interested in time, not just guesses. The running times of linear search and binary search include the time needed to make and check guesses, but there's more to these algorithms.
The running time of an algorithm depends on how long it takes a computer to run the lines of code of the algorithm—and that depends on the speed of the computer, the programming language, and the compiler that translates the program from the programming language into code that runs directly on the computer, among other factors.
Let's think about the running time of an algorithm more carefully. We can use a combination of two ideas. First, we need to determine how long the algorithm takes, in terms of the size of its input. This idea makes intuitive sense, doesn't it? We've already seen that the maximum number of guesses in linear search and binary search increases as the length of the array increases. Or think about a GPS. If it knew about only the interstate highway system, and not about every little road, it should be able to find routes more quickly, right? So we think about the running time of the algorithm as a function of the size of its input.
The second idea is that we must focus on how fast a function grows with the input size. We call this the rate of growth of the running time. To keep things manageable, we need to simplify the function to distill the most important part and cast aside the less important parts. For example, suppose that an algorithm, running on an input of size
\[ n \],
arge enough, 20 in this case. Here's a chart showing values of
\[ 6n^2 \] and
\[ 100n + 300 \] for values of
\[ n \] from 0 to 100:

We would say that the running time of this algorithm grows as
\[ n^2 \], dropping the coefficient 6 and the remaining terms
\[ 100n + 300 \]. It doesn't really matter what coefficients we use; as long as the running time is
\[ an^2 + bn + c \], for some numbers
\[ a > 0 \],
\[ b \], and
\[ c \], there will always be a value of
\[ n \] for which
\[ an^2 \] is greater than
\[ bn + c \], and this difference increases as
\[ n \] increases. For example, here's a chart showing values of
\[ 0.6n^2 \] and
\[ 1000n + 3000 \] so that we've reduced the coefficient of
\[ n^2 \] by a factor of 10 and increased the other two constants by a factor of 10:

The value of
\[ n \] at which
\[ 0.6n^2 \] becomes greater than
\[ 1000n + 3000 \] has increased, but there will always be such a crossover point, no matter what the constants.
By dropping the less significant terms and the constant coefficients, we can focus on the important part of an algorithm's running time—its rate of growth—without getting mired in details that complicate our understanding. When we drop the constant coefficients and the less significant terms, we use asymptotic notation. We'll see three forms of it: big-
\[ \Theta \] notation, big-O notation, and big-
\[ \Omega \] notation.
## Big-θ (Big-Theta) notation
Let's look at a simple implementation of linear search:
```
var doLinearSearch = function(array, targetValue) {
for (var guess = 0; guess < array.length; guess++) {
if (array[guess] === targetValue) {
return guess; // found it!
}
}
return -1; // didn't find it
};
```
```
def linear_search(array, target_value):
for guess in range(len(array)):
if array[guess] == target_value:
return guess # found it!
return -1 # didn't find it
```
Let's denote the size of the array (array.length) by
\[ n \]. The maximum number of times that the for-loop can run is
\[ n \], and this worst case occurs when the value being searched for is not present in the array.
Each time the for-loop iterates, it has to do several things:
compare guess with array.length
compare array[guess] with targetValue
possibly return the value of guess
increment guess.
Each of these little computations takes a constant amount of time each time it executes. If the for-loop iterates
\[ n \] times, then the time for all
\[ n \] iterations is
\[ c_1 \cdot n \], where
\[ c_1 \] is the sum of the times for the computations in one loop iteration. Now, we cannot say here what the value of
\[ c_1 \] is, because it depends on the speed of the computer, the programming language used, the compiler or interpreter that translates the source program into runnable code, and other factors.
This code has a little bit of extra overhead, for setting up the for-loop (including initializing guess to 0) and possibly returning -1 at the end. Let's call the time for this overhead
\[ c_2 \], which is also a constant. Therefore, the total time for linear search in the worst case is
\[ c_1 \cdot n + c_2 \].
As we've argued, the constant factor
\[ c_1 \] and the low-order term
\[ c_2 \] don't tell us about the rate of growth of the running time. What's significant is that the worst-case running time of linear search grows like the array size
\[ n \]. The notation we use for this running time is
\[ \Theta(n) \]. That's the Greek letter "theta," and we say "big-Theta of
\[ n \]" or just "Theta of
\[ n \]."
When we say that a particular running time is
\[ \Theta(n) \], we're saying that once
\[ n \] gets large enough, the running time is at least
\[ k_1 \cdot n \] and at most
\[ k_2 \cdot n \] for some constants
\[ k_1 \] and
\[ k_2 \]. Here's how to think of
\[ \Theta(n) \]:

For small values of
\[ n \], we don't care how the running time compares with
\[ k_1 \cdot n \] or
\[ k_2 \cdot n \]. But once
\[ n \] gets large enough—on or to the right of the dashed line—the running time must be sandwiched between
\[ k_1 \cdot n \] and
\[ k_2 \cdot n \]. As long as these constants
\[ k_1 \] and
\[ k_2 \] exist, we say that the running time is
\[ \Theta(n) \].
We are not restricted to just
\[ n \] in big-Θ notation. We can use any function, such as
\[ n^2 \],
\[ n \log_2 n \], or any other function of
\[ n \]. Here's how to think of a running time that is
\[ \Theta(f(n)) \] for some function
\[ f(n) \]:

Once
\[ n \] gets large enough, the running time is between
\[ k_1 \cdot f(n) \] and
\[ k_2 \cdot f(n) \].
In practice, we just drop constant factors and low-order terms. Another advantage of using big-Θ notation is that we don't have to worry about which time units we're using. For example, suppose that you calculate that a running time is
\[ 6n^2 + 100n + 300 \] microseconds. Or maybe it's milliseconds. When you use big-Θ notation, you don't say. You also drop the factor 6 and the low-order terms
\[ 100n + 300 \], and you just say that the running time is
\[ \Theta(n^2) \].
When we use big-Θ notation, we're saying that we have an asymptotically tight bound on the running time. "Asymptotically" because it matters for only large values of
\[ n \]. "Tight bound" because we've nailed the running time to within a constant factor above and below.
## Questions -- Python
One more cleanup! Travis notices that the final price often has many decimal places, like 84.9915. He wants to round to the nearest cent.
Round the final price to two decimal places.
Recall that the round() function takes two arguments - the number to round followed by the number of decimal places to round to. For example, round(3.141592, 4) evaluates to 3.1416.
```
base_price = float(input("Enter cart total: "))
# Available coupon codes include 15% off and $12 off.
percent_discount = base_price - base_price * .15
fixed_discount = base_price - 12
# Pick the coupon that offers the best discount.
final_price = round(min(fixed_discount, percent_discount),2)
print("Your best price is $" + str(final_price))
```
round(m,n)
m= number, n= decimal to how many
## Questions.
Travis can’t find the cleats at a local store, so he wants to include the shipping cost in the final price. Shipping costs can vary, so he decides to let the user enter the shipping cost themselves.
Add a new input() prompt that asks the user to enter a shipping cost.
Add the entered shipping cost to the final price.
You’ll need to store the result of the input() call in a new variable. Remember that the shipping cost may include cents, like 7.99.
```
```