0% found this document useful (0 votes)
4 views

Computer Science with Applications - Condensed Study Guide

This comprehensive study guide covers foundational concepts in computer science, including computational thinking, programming basics, control flow statements, functions, and data structures. It provides examples in Python, demonstrating variable usage, data types, error handling, and the implementation of stacks and queues. The guide emphasizes best practices in code organization and documentation, making it a valuable resource for learners in the field.

Uploaded by

hansonxia2024
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

Computer Science with Applications - Condensed Study Guide

This comprehensive study guide covers foundational concepts in computer science, including computational thinking, programming basics, control flow statements, functions, and data structures. It provides examples in Python, demonstrating variable usage, data types, error handling, and the implementation of stacks and queues. The guide emphasizes best practices in code organization and documentation, making it a valuable resource for learners in the field.

Uploaded by

hansonxia2024
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 29

Computer Science with Applications - Comprehensive Study

Guide
1. Getting Started
1.1 Computational Thinking
Core Principles:
Problem Decomposition: Break large problems into smaller, manageable pieces
Pattern Recognition: Identify similarities and recurring themes
Abstraction: Focus on essential features while hiding unnecessary details
Algorithm Design: Create step-by-step solutions
Example: Planning a dinner party
Decomposition: Guest list, menu planning, shopping, cooking, setup
Pattern recognition: Similar tasks for different courses
Abstraction: Focus on "prepare food" rather than every cooking detail
Algorithm: Specific sequence of tasks with timing
1.2 Programming Basics
Variables and Assignment:
python

# Variables store data


age = 25
name = "Alice"
height = 5.8
is_student = True

# Variables can be reassigned


age = age + 1 # or age += 1

Data Types:
Integers: Whole numbers ( 42 , -17 )
Floats: Decimal numbers ( 3.14 , -2.7 )
Strings: Text ( "Hello" , 'Python' )
Booleans: True/False values
Operators:
python

# Arithmetic
10 + 3 # 13 (addition)
10 - 3 # 7 (subtraction)
10 * 3 # 30 (multiplication)
10 / 3 # 3.333... (division)
10 // 3 # 3 (floor division)
10 % 3 # 1 (modulo - remainder)
10 ** 3 # 1000 (exponentiation)

# Comparison
x == y # Equal
x != y # Not equal
x < y # Less than
x <= y # Less than or equal
x > y # Greater than
x >= y # Greater than or equal

# Logical
True and False # False
True or False # True
not True # False

Input/Output:
python

name = input("Enter your name: ")


age = int(input("Enter your age: ")) # Convert string to int
print(f"Hello {name}, you are {age} years old")

1.3 Control Flow Statements


Conditional Statements:
python

temperature = 75

if temperature > 80:


print("It's hot!")
elif temperature > 60:
print("It's pleasant")
elif temperature > 40:
print("It's cool")
else:
print("It's cold!")

# Ternary operator (shorthand)


status = "hot" if temperature > 80 else "not hot"

For Loops:
python

# Iterate over a sequence


fruits = ["apple", "banana", "orange"]
for fruit in fruits:
print(f"I like {fruit}")

# Iterate with index


for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")

# Iterate over range


for i in range(5): # 0, 1, 2, 3, 4
print(i)

for i in range(2, 8): # 2, 3, 4, 5, 6, 7


print(i)

for i in range(0, 10, 2): # 0, 2, 4, 6, 8


print(i)

While Loops:
python

count = 0
while count < 5:
print(f"Count: {count}")
count += 1

# Be careful of infinite loops!


# Always ensure the condition eventually becomes False

Loop Control:
python

for i in range(10):
if i == 3:
continue # Skip rest of this iteration
if i == 7:
break # Exit the loop entirely
print(i) # Prints: 0, 1, 2, 4, 5, 6

1.4 Introduction to Functions


Function Basics:
python

def greet(name, greeting="Hello"):


"""
Greet a person with a custom message.

Args:
name (str): The person's name
greeting (str): The greeting message (default: "Hello")

Returns:
str: The complete greeting
"""
return f"{greeting}, {name}!"

# Function calls
message = greet("Alice") # "Hello, Alice!"
message = greet("Bob", "Hi") # "Hi, Bob!"
message = greet(greeting="Hey", name="Charlie") # Keyword arguments
Variable Scope:
python

global_var = "I'm global"

def example_function():
local_var = "I'm local"
print(global_var) # Can access global variables
print(local_var) # Can access local variables

example_function()
print(global_var) # Can access global variables
# print(local_var) # ERROR: local_var not accessible here

Multiple Return Values:


python

def calculate_stats(numbers):
total = sum(numbers)
count = len(numbers)
average = total / count if count > 0 else 0
return total, count, average

total, count, avg = calculate_stats([1, 2, 3, 4, 5])

The Call Stack Concept: When functions call other functions, Python keeps track using a "call stack":
python

def function_a():
print("In function A")
function_b()
print("Back in function A")

def function_b():
print("In function B")
function_c()
print("Back in function B")

def function_c():
print("In function C")

function_a()
# Output:
# In function A
# In function B
# In function C
# Back in function B
# Back in function A

1.5 Code Organization


Modules and Imports:
python

# Import entire module


import math
result = math.sqrt(16)

# Import specific functions


from math import sqrt, pi
result = sqrt(16)

# Import with alias


import numpy as np
array = np.array([1, 2, 3])

# Your own modules (if you create file utils.py)


from utils import my_function
Documentation Best Practices:
python

def calculate_compound_interest(principal, rate, time, compounds_per_year=1):


"""
Calculate compound interest.

Formula: A = P(1 + r/n)^(nt)

Args:
principal (float): Initial investment amount
rate (float): Annual interest rate (as decimal, e.g., 0.05 for 5%)
time (float): Time in years
compounds_per_year (int): Number of times interest compounds per year

Returns:
float: Final amount after compound interest

Example:
>>> calculate_compound_interest(1000, 0.05, 10, 12)
1643.6194649423633
"""
return principal * (1 + rate/compounds_per_year) ** (compounds_per_year * time)

1.6 Understanding Errors and Catching Exceptions


Common Error Types:
python

# SyntaxError - Code structure is wrong


# if x = 5: # Should use == for comparison

# NameError - Variable not defined


# print(undefined_variable)

# TypeError - Wrong data type


# "hello" + 5 # Can't add string and int

# ValueError - Right type, wrong value


# int("hello") # Can't convert "hello" to integer

# IndexError - List index out of range


# my_list = [1, 2, 3]
# print(my_list[5]) # Index 5 doesn't exist

# KeyError - Dictionary key doesn't exist


# my_dict = {"a": 1}
# print(my_dict["b"]) # Key "b" doesn't exist

Exception Handling:
python

def safe_divide(a, b):


try:
result = a / b
return result
except ZeroDivisionError:
print("Error: Cannot divide by zero!")
return None
except TypeError:
print("Error: Please provide numbers only!")
return None
finally:
print("Division operation completed")

# Usage
print(safe_divide(10, 2)) # 5.0
print(safe_divide(10, 0)) # Error message, returns None
print(safe_divide("10", 2)) # Error message, returns None
Advanced Exception Handling:
python

def process_file(filename):
try:
with open(filename, 'r') as file:
data = file.read()
# Process data here
return data
except FileNotFoundError:
print(f"File {filename} not found")
except PermissionError:
print(f"Permission denied to read {filename}")
except Exception as e:
print(f"Unexpected error: {e}")
finally:
print("File processing attempt completed")

2. Data Structures
2.1 Lists, Tuples, and Strings
Lists - Mutable Sequences:
python

# Creating lists
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]
empty = []

# Accessing elements
print(numbers[0]) # 1 (first element)
print(numbers[-1]) # 5 (last element)
print(numbers[1:4]) # [2, 3, 4] (slicing)
print(numbers[:3]) # [1, 2, 3] (first 3)
print(numbers[2:]) # [3, 4, 5] (from index 2)

# Modifying lists
numbers.append(6) # Add to end: [1, 2, 3, 4, 5, 6]
numbers.insert(0, 0) # Insert at index 0: [0, 1, 2, 3, 4, 5, 6]
numbers.remove(3) # Remove first occurrence of 3
popped = numbers.pop() # Remove and return last element
popped_at_index = numbers.pop(1) # Remove and return element at index 1

# List operations
len(numbers) # Length
3 in numbers # Check membership (True/False)
numbers.count(2) # Count occurrences
numbers.index(4) # Find index of first occurrence
numbers.sort() # Sort in place
sorted_copy = sorted(numbers) # Return sorted copy
numbers.reverse() # Reverse in place

List Comprehensions:
python

# Traditional way
squares = []
for x in range(10):
squares.append(x**2)

# List comprehension way


squares = [x**2 for x in range(10)]

# With condition
even_squares = [x**2 for x in range(10) if x % 2 == 0]

# More complex example


words = ["hello", "world", "python", "programming"]
long_words = [word.upper() for word in words if len(word) > 5]
# Result: ['PYTHON', 'PROGRAMMING']

Memory and References:


python

# Important concept: Lists are objects in memory


list1 = [1, 2, 3]
list2 = list1 # list2 points to same object as list1
list2.append(4) # Modifies the shared object
print(list1) # [1, 2, 3, 4] - list1 is also changed!

# To create a copy:
list3 = list1.copy() # Shallow copy
list4 = list1[:] # Another way to shallow copy
list5 = list(list1) # Another way to shallow copy

# Deep copy for nested structures


import copy
nested_list = [[1, 2], [3, 4]]
deep_copied = copy.deepcopy(nested_list)

Tuples - Immutable Sequences:


python

# Creating tuples
coordinates = (3, 5)
single_item = (42,) # Note the comma for single-item tuple
empty_tuple = ()

# Tuple unpacking
x, y = coordinates # x = 3, y = 5

# Tuples are immutable


# coordinates[0] = 10 # This would cause an error

# When to use tuples:


# - Fixed collections (coordinates, RGB colors)
# - Dictionary keys (must be immutable)
# - Returning multiple values from functions

Strings - Immutable Text Sequences:


python

text = "Hello, World!"

# String methods
print(text.lower()) # "hello, world!"
print(text.upper()) # "HELLO, WORLD!"
print(text.strip()) # Remove whitespace from ends
print(text.replace("World", "Python")) # "Hello, Python!"
print(text.split(", ")) # ["Hello", "World!"]

# String formatting
name = "Alice"
age = 30
print(f"My name is {name} and I am {age} years old") # f-string (preferred)
print("My name is {} and I am {} years old".format(name, age)) # .format()
print("My name is %s and I am %d years old" % (name, age)) # % formatting (old)

# String operations
"apple" in "pineapple" # True
"hello" + " " + "world" # "hello world"
"ha" * 3 # "hahaha"
2.2 Dictionaries and Sets
Dictionaries - Key-Value Pairs:
python

# Creating dictionaries
student = {
"name": "Alice",
"age": 20,
"major": "Computer Science",
"gpa": 3.8
}

empty_dict = {}
dict_from_pairs = dict([("a", 1), ("b", 2)])

# Accessing and modifying


print(student["name"]) # "Alice"
print(student.get("age")) # 20
print(student.get("height", "N/A")) # "N/A" (default if key doesn't exist)

student["age"] = 21 # Update existing key


student["year"] = "Junior" # Add new key
del student["gpa"] # Remove key-value pair
removed_value = student.pop("major", "Unknown") # Remove and return value

# Dictionary methods
print(student.keys()) # dict_keys(['name', 'age', 'year'])
print(student.values()) # dict_values(['Alice', 21, 'Junior'])
print(student.items()) # dict_items([('name', 'Alice'), ('age', 21), ('year', 'Jun

# Iterating over dictionaries


for key in student:
print(f"{key}: {student[key]}")

for key, value in student.items():


print(f"{key}: {value}")

Dictionary Comprehensions:
python

# Create dictionary from lists


keys = ["a", "b", "c"]
values = [1, 2, 3]
my_dict = {k: v for k, v in zip(keys, values)}

# Square numbers
squares = {x: x**2 for x in range(1, 6)} # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# Conditional dictionary comprehension


even_squares = {x: x**2 for x in range(1, 11) if x % 2 == 0}

Sets - Unique Elements:


python

# Creating sets
numbers = {1, 2, 3, 4, 5}
empty_set = set() # Note: {} creates an empty dict, not set
from_list = set([1, 2, 2, 3, 3, 4]) # {1, 2, 3, 4} - duplicates removed

# Set operations
numbers.add(6) # Add element
numbers.remove(3) # Remove element (raises error if not found)
numbers.discard(10) # Remove element (no error if not found)

# Mathematical set operations


set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

union = set1 | set2 # {1, 2, 3, 4, 5, 6}


intersection = set1 & set2 # {3, 4}
difference = set1 - set2 # {1, 2}
symmetric_diff = set1 ^ set2 # {1, 2, 5, 6}

# Set membership and comparisons


3 in set1 # True
set1.issubset({1, 2, 3, 4, 5}) # True
{1, 2}.issubset(set1) # True

2.3 Implementing Data Structures: Stacks and Queues


Stacks (LIFO - Last In, First Out):
python

class Stack:
def __init__(self):
self.items = []

def push(self, item):


"""Add item to top of stack"""
self.items.append(item)

def pop(self):
"""Remove and return top item"""
if self.is_empty():
raise IndexError("Stack is empty")
return self.items.pop()

def peek(self):
"""Return top item without removing it"""
if self.is_empty():
raise IndexError("Stack is empty")
return self.items[-1]

def is_empty(self):
return len(self.items) == 0

def size(self):
return len(self.items)

# Usage example
stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.pop()) # 3
print(stack.peek()) # 2

Stack Applications:
python

def is_balanced_parentheses(expression):
"""Check if parentheses are balanced using a stack"""
stack = []
pairs = {'(': ')', '[': ']', '{': '}'}

for char in expression:


if char in pairs: # Opening bracket
stack.append(char)
elif char in pairs.values(): # Closing bracket
if not stack:
return False
if pairs[stack.pop()] != char:
return False

return len(stack) == 0

print(is_balanced_parentheses("((()))")) # True
print(is_balanced_parentheses("([{}])")) # True
print(is_balanced_parentheses("((()]")) # False

Queues (FIFO - First In, First Out):


python

from collections import deque

class Queue:
def __init__(self):
self.items = deque()

def enqueue(self, item):


"""Add item to back of queue"""
self.items.append(item)

def dequeue(self):
"""Remove and return front item"""
if self.is_empty():
raise IndexError("Queue is empty")
return self.items.popleft()

def front(self):
"""Return front item without removing it"""
if self.is_empty():
raise IndexError("Queue is empty")
return self.items[0]

def is_empty(self):
return len(self.items) == 0

def size(self):
return len(self.items)

# Usage example
queue = Queue()
queue.enqueue("first")
queue.enqueue("second")
queue.enqueue("third")
print(queue.dequeue()) # "first"
print(queue.front()) # "second"

2.4 Classes and Objects


Basic Class Definition:
python
class BankAccount:
# Class variable (shared by all instances)
bank_name = "Python Bank"

def __init__(self, account_holder, initial_balance=0):


"""Constructor - called when creating new instance"""
# Instance variables (unique to each instance)
self.account_holder = account_holder
self.balance = initial_balance
self.transaction_history = []

def deposit(self, amount):


"""Add money to account"""
if amount > 0:
self.balance += amount
self.transaction_history.append(f"Deposited ${amount}")
return True
return False

def withdraw(self, amount):


"""Remove money from account"""
if 0 < amount <= self.balance:
self.balance -= amount
self.transaction_history.append(f"Withdrew ${amount}")
return True
return False

def get_balance(self):
"""Return current balance"""
return self.balance

def __str__(self):
"""String representation of the object"""
return f"Account({self.account_holder}, ${self.balance})"

def __repr__(self):
"""Developer-friendly representation"""
return f"BankAccount('{self.account_holder}', {self.balance})"

# Creating and using objects


account1 = BankAccount("Alice", 1000)
account2 = BankAccount("Bob")
account1.deposit(500)
account1.withdraw(200)
print(account1.get_balance()) # 1300
print(account1) # Account(Alice, $1300)

Inheritance:
python

class SavingsAccount(BankAccount):
def __init__(self, account_holder, initial_balance=0, interest_rate=0.02):
super().__init__(account_holder, initial_balance) # Call parent constructor
self.interest_rate = interest_rate

def apply_interest(self):
"""Add interest to the account"""
interest = self.balance * self.interest_rate
self.balance += interest
self.transaction_history.append(f"Interest added: ${interest:.2f}")

def withdraw(self, amount):


"""Override parent method with additional fee"""
if super().withdraw(amount): # Call parent method
# Add withdrawal fee for savings accounts
fee = 2
self.balance -= fee
self.transaction_history.append(f"Withdrawal fee: ${fee}")
return True
return False

# Usage
savings = SavingsAccount("Charlie", 1000, 0.05)
savings.apply_interest()
print(savings.get_balance()) # 1050.0

Encapsulation with Properties:


python

class Temperature:
def __init__(self, celsius=0):
self._celsius = celsius # Private variable (by convention)

@property
def celsius(self):
return self._celsius

@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("Temperature cannot be below absolute zero")
self._celsius = value

@property
def fahrenheit(self):
return (self._celsius * 9/5) + 32

@fahrenheit.setter
def fahrenheit(self, value):
self.celsius = (value - 32) * 5/9

# Usage
temp = Temperature(25)
print(temp.celsius) # 25
print(temp.fahrenheit) # 77.0
temp.fahrenheit = 86
print(temp.celsius) # 30.0

3. Functional Programming and Recursion


3.1 Functional Programming
Higher-Order Functions: Functions that take other functions as arguments or return functions:
python

def apply_operation(numbers, operation):


"""Apply an operation to each number in the list"""
return [operation(num) for num in numbers]

def square(x):
return x ** 2

def cube(x):
return x ** 3

numbers = [1, 2, 3, 4, 5]
squared = apply_operation(numbers, square) # [1, 4, 9, 16, 25]
cubed = apply_operation(numbers, cube) # [1, 8, 27, 64, 125]

Anonymous Functions (Lambda):


python

# Lambda functions are short, one-line functions


square = lambda x: x ** 2
add = lambda x, y: x + y
is_even = lambda x: x % 2 == 0

# Often used with built-in functions


numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
squared = list(map(lambda x: x**2, numbers))
evens = list(filter(lambda x: x % 2 == 0, numbers))

Built-in Functional Programming Tools:


Map - Apply function to each element:
python

numbers = [1, 2, 3, 4, 5]

# Traditional approach
squared = []
for num in numbers:
squared.append(num ** 2)

# Using map
squared = list(map(lambda x: x**2, numbers)) # [1, 4, 9, 16, 25]

# Map with multiple iterables


nums1 = [1, 2, 3]
nums2 = [4, 5, 6]
sums = list(map(lambda x, y: x + y, nums1, nums2)) # [5, 7, 9]

Filter - Keep elements that meet a condition:


python

numbers = range(1, 11) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Traditional approach
evens = []
for num in numbers:
if num % 2 == 0:
evens.append(num)

# Using filter
evens = list(filter(lambda x: x % 2 == 0, numbers)) # [2, 4, 6, 8, 10]

# Filter with more complex condition


words = ["hello", "world", "python", "programming", "code"]
long_words = list(filter(lambda word: len(word) > 5, words)) # ['python', 'programming

Reduce - Combine elements into single value:


python

from functools import reduce

numbers = [1, 2, 3, 4, 5]

# Traditional approach to find product


product = 1
for num in numbers:
product *= num

# Using reduce
product = reduce(lambda x, y: x * y, numbers) # 120

# Find maximum
maximum = reduce(lambda x, y: x if x > y else y, numbers) # 5

# More practical example: flatten nested lists


nested = [[1, 2], [3, 4], [5, 6]]
flattened = reduce(lambda x, y: x + y, nested) # [1, 2, 3, 4, 5, 6]

Function Composition and Returning Functions:


python

def make_multiplier(n):
"""Return a function that multiplies by n"""
def multiplier(x):
return x * n
return multiplier

double = make_multiplier(2)
triple = make_multiplier(3)

print(double(5)) # 10
print(triple(4)) # 12

# More complex example: function decorator


def timer_decorator(func):
"""Decorator to time function execution"""
import time
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} took {end_time - start_time:.4f} seconds")
return result
return wrapper

@timer_decorator
def slow_function():
import time
time.sleep(1)
return "Done!"

slow_function() # Prints timing information

Practical Functional Programming Example:


python

# Data processing pipeline using functional programming


sales_data = [
{"product": "laptop", "price": 1000, "quantity": 2},
{"product": "mouse", "price": 25, "quantity": 10},
{"product": "keyboard", "price": 75, "quantity": 5},
{"product": "monitor", "price": 300, "quantity": 3},
]

# Calculate total revenue using functional approach


total_revenue = sum(map(lambda item: item["price"] * item["quantity"], sales_data))

# Find expensive items (>$100 total value)


expensive_items = list(filter(lambda item: item["price"] * item["quantity"] > 100, sale

# Transform data: add total_value field


enhanced_data = list(map(lambda item: {**item, "total_value": item["price"] * item["qua

3.2 Recursion
Understanding Recursion: Recursion is when a function calls itself. Every recursive function needs:
1. Base case: Condition where recursion stops
2. Recursive case: Function calls itself with simpler input
Classic Example - Factorial:
python

def factorial(n):
"""Calculate n! = n × (n-1) × (n-2) × ... × 1"""
# Base case
if n <= 1:
return 1

# Recursive case
return n * factorial(n - 1)

# Trace of factorial(4):
# factorial(4) = 4 * factorial(3)
# factorial(3) = 3 * factorial(2)
# factorial(2) = 2 * factorial(1)
# factorial(1) = 1 <- base case
# Working backwards:
# factorial(2) = 2 * 1 = 2
# factorial(3) = 3 * 2 = 6
# factorial(4) = 4 * 6 = 24

print(factorial(5)) # 120

Fibonacci Sequence:
python

def fibonacci(n):
"""Return the nth Fibonacci number"""
# Base cases
if n <= 1:
return n

# Recursive case
return fibonacci(n - 1) + fibonacci(n - 2)

# Generate first 10 Fibonacci numbers


fib_sequence = [fibonacci(i) for i in range(10)]
print(fib_sequence) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Optimized Fibonacci with Memoization:


python

def fibonacci_memo(n, memo={}):


"""Fibonacci with memoization to avoid recalculating values"""
if n in memo:
return memo[n]

if n <= 1:
return n

memo[n] = fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo)


return memo[n]

# Much faster for large values


print(fibonacci_memo(50)) # Calculates quickly

Binary Search - Recursive Implementation:


python

def binary_search(arr, target, left=0, right=None):


"""
Search for target in sorted array using binary search
Returns index if found, -1 if not found
"""
if right is None:
right = len(arr) - 1

# Base case: not found


if left > right:
return -1

# Find middle point


mid = (left + right) // 2

# Base case: found


if arr[mid] == target:
return mid

# Recursive cases
if target < arr[mid]:
return binary_search(arr, target, left, mid - 1)
else:
return binary_search(arr, target, mid + 1, right)

# Usage
sorted_list = [1, 3, 5, 7, 9, 11, 13, 15]
index = binary_search(sorted_list, 7)

You might also like