diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c816b349..f76cd5b3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,17 +3,13 @@ { "name": "Python 3", - // This is the default - // "image": "mcr.microsoft.com/devcontainers/universal:2", + "image": "mcr.microsoft.com/devcontainers/python:1-3.12-bookworm", - // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - //"image": "mcr.microsoft.com/devcontainers/python:1-${templateOption:imageVariant}", - //"image": "mcr.microsoft.com/devcontainers/python:1-3.12-bookworm", - "build": { - "dockerfile": "Dockerfile", - "context": ".." - }, + //"build": { + // "dockerfile": "Dockerfile", + // "context": ".." + //}, "containerEnv": { "SDL_VIDEO_WINDOW_POS": "0,0", // GUI Windows all the way in the upper left. @@ -21,12 +17,7 @@ }, // Features to add to the dev container. More info: https://containers.dev/features. - "features": { - "ghcr.io/devcontainers/features/desktop-lite:1": { - "password" : "code4life" - } - }, - + "features": {}, // Use 'forwardPorts' to make a list of ports inside the container available locally. @@ -43,13 +34,13 @@ // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "./.devcontainer/cs-setup.sh", + "postCreateCommand": "bash ./.devcontainer/setup.sh ${containerWorkspaceFolder}", + "customizations": { "codespaces": { "openFiles": [ - //"lessons/00_Turtles/01_Get_Started.ipynb" - "README.md" + "lessons/10_Turtles/10_Welcome/10_Welcome.ipynb" ] }, "vscode": { @@ -57,10 +48,12 @@ "ms-python.python", "ms-python.debugpy", "ms-python.isort", - "ms-toolsai.jupyter" + "ms-toolsai.jupyter", + "jointheleague.jtl-syllabus" ], "settings": { - + "python.defaultInterpreterPath": "/usr/local/bin/python", + "python.terminal.activateEnvironment": true } } } diff --git a/.vscode/settings.json b/.vscode/settings.json index 4367a83f..f1e278e2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,26 @@ { + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/.DS_Store": true, + "**/Thumbs.db": true, + "**/*.crswap": true, + ".git": true, + ".github": true, + "**/.gitignore": true, + ".gitattributes": true, + ".pylintrc": true, + ".vscode": true, + ".yarn": true, + ".devcontainer": true, + "**/node_modules": true, + "**/.ipynb_checkpoints": true, + ".venv": true, + ".lib": true, + "**/.jtl": true, + "requirements.txt": true, + ".lessons": true + } } \ No newline at end of file diff --git a/catchball.py b/catchball.py new file mode 100644 index 00000000..4bd3e374 --- /dev/null +++ b/catchball.py @@ -0,0 +1,82 @@ +import pygame +import random + +# Initialize Pygame +pygame.init() + +# Screen size +WIDTH, HEIGHT = 500, 600 +screen = pygame.display.set_mode((WIDTH, HEIGHT)) +pygame.display.set_caption("Catch the Ball") + +# Colors +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) +RED = (255, 0, 0) + +# Basket settings +basket_width = 100 +basket_height = 20 +basket_x = WIDTH // 2 - basket_width // 2 +basket_y = HEIGHT - basket_height - 10 +basket_speed = 7 + +# Ball settings +ball_radius = 15 +ball_x = random.randint(ball_radius, WIDTH - ball_radius) +ball_y = 0 +ball_speed = 5 + +# Score +score = 0 +font = pygame.font.SysFont(None, 36) + +# Game loop flag +running = True +clock = pygame.time.Clock() + +while running: + clock.tick(60) # 60 frames per second + screen.fill(WHITE) + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + + # Get keys pressed + keys = pygame.key.get_pressed() + if keys[pygame.K_LEFT] and basket_x > 0: + basket_x -= basket_speed + if keys[pygame.K_RIGHT] and basket_x < WIDTH - basket_width: + basket_x += basket_speed + + # Move the ball down + ball_y += ball_speed + + # Check if ball caught by basket + if (basket_y < ball_y + ball_radius < basket_y + basket_height) and (basket_x < ball_x < basket_x + basket_width): + score += 1 + ball_x = random.randint(ball_radius, WIDTH - ball_radius) + ball_y = 0 + + # If ball hits the bottom, reset ball and lose a point + if ball_y > HEIGHT: + score -= 1 + ball_x = random.randint(ball_radius, WIDTH - ball_radius) + ball_y = 0 + + # Draw basket + pygame.draw.rect(screen, BLACK, (basket_x, basket_y, basket_width, basket_height)) + + # Draw ball + pygame.draw.circle(screen, RED, (ball_x, ball_y), ball_radius) + + # Draw score + score_text = font.render(f"Score: {score}", True, BLACK) + screen.blit(score_text, (10, 10)) + + pygame.display.flip() + +pygame.quit() + + \ No newline at end of file diff --git a/flappybird.py b/flappybird.py new file mode 100644 index 00000000..be8cd98e --- /dev/null +++ b/flappybird.py @@ -0,0 +1,139 @@ +import pygame +import sys +import random + +# Initialize pygame +pygame.init() + +# Screen dimensions +WIDTH, HEIGHT = 400, 600 +screen = pygame.display.set_mode((WIDTH, HEIGHT)) +pygame.display.set_caption("Flappy Bird") + +# Colors +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) +BLUE = (0, 150, 255) +GREEN = (0, 255, 0) + +# Clock for controlling FPS +clock = pygame.time.Clock() +FPS = 60 + +# Bird properties +bird_x = 50 +bird_y = HEIGHT // 2 +bird_radius = 20 +bird_velocity = 0 +gravity = 0.25 # slower fall +jump_strength = -8 # gentler jump + +# Pipe properties +pipe_width = 70 +pipe_gap = 200 # bigger gap +pipe_velocity = 4 + +# Pipes: list of dictionaries with x position and height of the top pipe +pipes = [] +pipe_spawn_time = 0 # Timer to spawn pipes + +score = 0 +font = pygame.font.SysFont(None, 40) + +def draw_bird(y): + pygame.draw.circle(screen, BLUE, (bird_x, int(y)), bird_radius) + +def draw_pipe(x, height): + # Top pipe + pygame.draw.rect(screen, GREEN, (x, 0, pipe_width, height)) + # Bottom pipe + bottom_pipe_y = height + pipe_gap + bottom_pipe_height = HEIGHT - bottom_pipe_y + pygame.draw.rect(screen, GREEN, (x, bottom_pipe_y, pipe_width, bottom_pipe_height)) + +def check_collision(bird_y, pipes): + # Check if bird hits ground or ceiling + if bird_y - bird_radius < 0 or bird_y + bird_radius > HEIGHT: + return True + # Check collision with pipes + for pipe in pipes: + pipe_x = pipe['x'] + pipe_height = pipe['height'] + if bird_x + bird_radius > pipe_x and bird_x - bird_radius < pipe_x + pipe_width: + if bird_y - bird_radius < pipe_height or bird_y + bird_radius > pipe_height + pipe_gap: + return True + return False + +def display_score(score): + score_text = font.render(f"Score: {score}", True, BLACK) + screen.blit(score_text, (10, 10)) + +def game_over_screen(score): + screen.fill(WHITE) + game_over_text = font.render("Game Over!", True, BLACK) + score_text = font.render(f"Final Score: {score}", True, BLACK) + screen.blit(game_over_text, (WIDTH // 2 - game_over_text.get_width() // 2, HEIGHT // 2 - 50)) + screen.blit(score_text, (WIDTH // 2 - score_text.get_width() // 2, HEIGHT // 2)) + pygame.display.flip() + pygame.time.wait(3000) + +def main(): + global bird_y, bird_velocity, pipes, pipe_spawn_time, score + + running = True + while running: + clock.tick(FPS) + screen.fill(WHITE) + + # Event handling + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + pygame.quit() + sys.exit() + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_SPACE: + bird_velocity = jump_strength + + # Bird physics + bird_velocity += gravity + bird_y += bird_velocity + + # Pipe spawning + pipe_spawn_time += 1 + if pipe_spawn_time > 90: # Every 1.5 seconds (at 60 FPS) + pipe_height = random.randint(50, HEIGHT - pipe_gap - 50) + pipes.append({'x': WIDTH, 'height': pipe_height}) + pipe_spawn_time = 0 + + # Move pipes and remove off-screen ones + for pipe in pipes: + pipe['x'] -= pipe_velocity + pipes = [pipe for pipe in pipes if pipe['x'] + pipe_width > 0] + + # Check score (when bird passes pipe) + for pipe in pipes: + if pipe['x'] + pipe_width < bird_x and not pipe.get('passed', False): + score += 1 + pipe['passed'] = True + + # Draw everything + draw_bird(bird_y) + for pipe in pipes: + draw_pipe(pipe['x'], pipe['height']) + display_score(score) + + # Check collisions + if check_collision(bird_y, pipes): + game_over_screen(score) + # Reset game state + bird_y = HEIGHT // 2 + bird_velocity = 0 + pipes = [] + pipe_spawn_time = 0 + score = 0 + + pygame.display.flip() + +if __name__ == "__main__": + main() diff --git a/lessons/.jtl/.gitignore b/lessons/.jtl/.gitignore new file mode 100644 index 00000000..5dd7e55e --- /dev/null +++ b/lessons/.jtl/.gitignore @@ -0,0 +1 @@ +syllabus-completion.json \ No newline at end of file diff --git a/lessons/.jtl/syllabus-completion.json b/lessons/.jtl/syllabus-completion.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/lessons/.jtl/syllabus-completion.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/lessons/.jtl/syllabus.yaml b/lessons/.jtl/syllabus.yaml index 747605df..82a3655a 100644 --- a/lessons/.jtl/syllabus.yaml +++ b/lessons/.jtl/syllabus.yaml @@ -1,168 +1,210 @@ name: Python Apprentice -description: Introduction to programming -module_dir: ../ +module_dir: .. +uid: 283c41e4-8abe-49bd-9335-e19ba693277b modules: -- name: 00_Turtles - overview: 00_Turtles/README.md +- name: Turtles + uid: Io0hFJiW lessons: - - name: Get Started - exercise: 00_Turtles/01_Get_Started.ipynb - display: false - - name: Meet Tina - exercise: 00_Turtles/02_Meet_Tina.py - display: true - - name: Check In Your Code - exercise: 00_Turtles/03_Check_In_Your_Code.ipynb - display: false + - name: Welcome + uid: AZCeRx3O + lessons: + - name: Welcome + uid: RRTPqCQu + exercise: 10_Turtles/10_Welcome/10_Welcome.ipynb + - name: Open The Screen + uid: KmgIQbhr + exercise: 10_Turtles/10_Welcome/20_Open_The_Screen.ipynb + - name: Run Programs + uid: cNLK6qtR + exercise: 10_Turtles/10_Welcome/30_Run_Programs.ipynb + - name: Introducing Tina + uid: NtvhO8WR + lessons: + - name: Meet Tina + uid: tvO1dlwm + lesson: 10_Turtles/20_Introducing_Tina/10_Meet_Tina/README.md + exercise: 10_Turtles/20_Introducing_Tina/10_Meet_Tina/Meet_Tina.py + display: true + - name: What Can Tina Do + uid: 7tUP3zAZ + exercise: 10_Turtles/20_Introducing_Tina/20_What_Can_Tina_Do.ipynb + - name: Squares and Circles + uid: E7KlecQ3 + lesson: 10_Turtles/20_Introducing_Tina/30_Squares_and_Circles/README.md + exercise: 10_Turtles/20_Introducing_Tina/30_Squares_and_Circles/Squares_and_Circles.py + display: true + - name: Check In Your Code + uid: doD6P7fk + exercise: 10_Turtles/20_Introducing_Tina/40_Check_In_Your_Code.ipynb - name: Turtle Tricks + uid: c6l7hD7a lessons: - - name: Turtle Tricks A - exercise: 00_Turtles/04a_Turtle_Tricks.py + - name: Turtle Tricks + exercise: 10_Turtles/30_Turtle_Tricks/10_Turtle_Tricks.py display: true - - name: Turtle Tricks B - exercise: 00_Turtles/04b_Turtle_Tricks.py + - name: Turtle Tricks + exercise: 10_Turtles/30_Turtle_Tricks/20_Turtle_Tricks.py display: true - - name: Turtle Tricks C - exercise: 00_Turtles/04c_Turtle_Tricks.py + - name: Turtle Tricks + exercise: 10_Turtles/30_Turtle_Tricks/30_Turtle_Tricks.py display: true - name: Loops - exercise: 00_Turtles/05a_Loops.ipynb - display: false - - name: Loop with Turtle + uid: wVDXfv96 lessons: - - name: Loop with Turtle A - exercise: 00_Turtles/05b_Loop_with_Turtle.py + - name: Loops + uid: abX8sNwB + exercise: 10_Turtles/40_Loops/10_Loops.ipynb + - name: Loop with Turtle + exercise: 10_Turtles/40_Loops/20_Loop_with_Turtle.py display: true - - name: Loop with Turtle B - exercise: 00_Turtles/05c_Loop_with_Turtle.py + - name: Loop with Turtle + exercise: 10_Turtles/40_Loops/30_Loop_with_Turtle.py - name: Variables and Functions + uid: O1qsljMz lessons: - - name: Variables and Functions A - exercise: 00_Turtles/06a_Variables_and_Functions.ipynb - display: false - - name: Variables and Functions B - exercise: 00_Turtles/06b_Variables_and_Functions.ipynb - display: false - - name: Efficient Turtle - exercise: 00_Turtles/07_Efficient_Turtle.py - display: true + - name: Variables and Functions + uid: HOBo0wvj + exercise: 10_Turtles/50_Variables_and_Functions/10_Variables_and_Functions.ipynb + - name: Efficient Turtle + exercise: 10_Turtles/50_Variables_and_Functions/20_Efficient_Turtle.py + display: true - name: More Turtle Programs + uid: I4bCPbWz lessons: - name: More Turtle Programs - exercise: 00_Turtles/08a_More_Turtle_Programs.ipynb - display: false + uid: IloYptI2 + exercise: 10_Turtles/60_More_Turtle_Programs/10_More_Turtle_Programs.ipynb + - name: More Turtle programs + exercise: 10_Turtles/60_More_Turtle_Programs/20_More_Turtle_programs.py - name: More Turtle Programs - exercise: 00_Turtles/08c_More_Turtle_Programs.py - display: true + exercise: 10_Turtles/60_More_Turtle_Programs/30_More_Turtle_Programs.py - name: More Turtle Programs - exercise: 00_Turtles/08d_More_Turtle_Programs.py + exercise: 10_Turtles/60_More_Turtle_Programs/40_More_Turtle_Programs.py + - name: Projects + uid: eo3RVnyt + lessons: + - name: LeagueBot + exercise: 10_Turtles/70_Projects/10_LeagueBot.py display: true - - name: More Turtle programs - exercise: 00_Turtles/08b_More_Turtle_programs.py - display: true - - name: LeagueBot - exercise: 00_Turtles/09_LeagueBot.py - display: true - - name: Tash Me - exercise: 00_Turtles/10a_Tash_Me.py - display: true - - name: Tash Me Click - exercise: 00_Turtles/10b_Tash_Me_Click.py - - name: Tash Me Twirl - exercise: 00_Turtles/10c_Tash_Me_Twirl.py - - name: Lists - exercise: 00_Turtles/11_Lists.ipynb - display: false - - name: Color Lines - exercise: 00_Turtles/12_Color_Lines.py - display: true - - name: Flaming Ninja Star - exercise: 00_Turtles/13_Flaming_Ninja_Star.py - display: true - - name: Crazy Spiral - exercise: 00_Turtles/14_Crazy_Spiral.py - display: true - - name: Pentagon Crazy - exercise: 00_Turtles/15_Pentagon_Crazy.py - display: true - - name: Turtle Spiral - exercise: 00_Turtles/16_Turtle_Spiral.py - display: true -- name: 01_Types_and_Logic - overview: 01_Types_and_Logic/README.md + - name: Tash Me + exercise: 10_Turtles/70_Projects/20_Tash_Me.py + - name: Tash Me Click + exercise: 10_Turtles/70_Projects/30_Tash_Me_Click.py + - name: Tash Me Twirl + exercise: 10_Turtles/70_Projects/40_Tash_Me_Twirl.py + - name: Introducting Lists + uid: g4kLhJ2U + lessons: + - name: Lists + uid: 0KEhJUGe + exercise: 10_Turtles/80_Introducting_Lists/10_Lists.ipynb + - name: Color Lines + exercise: 10_Turtles/80_Introducting_Lists/20_Color_Lines.py + display: true + - name: Graphics Projects + uid: 3shr4ruR + lessons: + - name: Flaming Ninja Star + exercise: 10_Turtles/90_Graphics_Projects/10_Flaming_Ninja_Star.py + display: true + - name: Crazy Spiral + exercise: 10_Turtles/90_Graphics_Projects/20_Crazy_Spiral.py + - name: Pentagon Crazy + exercise: 10_Turtles/90_Graphics_Projects/30_Pentagon_Crazy.py + display: true + - name: Turtle Spiral + exercise: 10_Turtles/90_Graphics_Projects/40_Turtle_Spiral.py + display: true +- name: Types and Logic + uid: ryHvW6vk lessons: - name: Numbers and Strings - exercise: 01_Types_and_Logic/01_Numbers_and_Strings.ipynb + uid: HXQZ0Iui + exercise: 20_Types_and_Logic/10_Numbers_and_Strings.ipynb - name: Control Flow - exercise: 01_Types_and_Logic/02_Control_Flow.ipynb + uid: g6JPkFUs + exercise: 20_Types_and_Logic/20_Control_Flow.ipynb - name: My Ages - exercise: 01_Types_and_Logic/03_My_Ages.py + exercise: 20_Types_and_Logic/30_My_Ages.py display: true - name: Simple Adder - exercise: 01_Types_and_Logic/04_Simple_Adder.py + exercise: 20_Types_and_Logic/40_Simple_Adder.py - name: Infuriating Calculator - exercise: 01_Types_and_Logic/05_Infuriating_Calculator.py + exercise: 20_Types_and_Logic/50_Infuriating_Calculator.py - name: Code Challenges - exercise: 01_Types_and_Logic/07_Code_Challenges.ipynb - - - name: to random - exercise: 01_Types_and_Logic/intro_to_random.py -- name: 02_Loops - overview: 02_Loops/README.md + uid: jJI6aomB + exercise: 20_Types_and_Logic/60_Code_Challenges.ipynb +- name: Loops + uid: TzgRqJlw lessons: - name: Iteration - exercise: 02_Loops/01_Iteration.ipynb + uid: ITpqcvxv + exercise: 30_Loops/010_Iteration.ipynb - name: Loops with Range - exercise: 02_Loops/02_Loops_with_Range.ipynb + uid: WcGpR3Xg + exercise: 30_Loops/020_Loops_with_Range.ipynb - name: Lists - exercise: 02_Loops/03a_Lists.ipynb - display: false + uid: 7zsKa84X + exercise: 30_Loops/030_Lists.ipynb - name: Crazy Tina - exercise: 02_Loops/03b_Crazy_Tina.py + exercise: 30_Loops/040_Crazy_Tina.py display: true - name: Tuples - exercise: 02_Loops/03c_Tuples.ipynb + uid: 9zTQza2e + exercise: 30_Loops/050_Tuples.ipynb - name: Indexing and Slicing - exercise: 02_Loops/04a_Indexing_and_Slicing.ipynb + uid: P27f2L8k + exercise: 30_Loops/060_Indexing_and_Slicing.ipynb - name: List Story - exercise: 02_Loops/04b_List_Story.py + exercise: 30_Loops/070_List_Story.py - name: Strings - exercise: 02_Loops/05_Strings.ipynb + uid: Tmg4QRhJ + exercise: 30_Loops/080_Strings.ipynb - name: Fizz Buzz Badgers - exercise: 02_Loops/06_Fizz_Buzz_Badgers.py + exercise: 30_Loops/090_Fizz_Buzz_Badgers.py - name: For Loop Gauntlet - exercise: 02_Loops/07_For_Loop_Gauntlet.ipynb + uid: 8yGSkBgV + exercise: 30_Loops/100_For_Loop_Gauntlet.ipynb - name: FizzBuzz Gui Grid - exercise: 02_Loops/09_FizzBuzz_Gui_Grid.py + exercise: 30_Loops/110_FizzBuzz_Gui_Grid.py + display: true - name: More Iterables - exercise: 02_Loops/10_More_Iterables.ipynb - display: false + uid: PrKwTywv + exercise: 30_Loops/120_More_Iterables.ipynb - name: Iterable Turtle - exercise: 02_Loops/11_Iterable_Turtle.ipynb - display: false + uid: vTyp2WhX + exercise: 30_Loops/130_Iterable_Turtle.ipynb - name: More Loops - exercise: 02_Loops/12_More_Loops.ipynb + uid: RMSFNtMb + exercise: 30_Loops/140_More_Loops.ipynb - name: Number Guess - exercise: 02_Loops/13_Number_Guess.py + exercise: 30_Loops/150_Number_Guess.py - name: Extras - exercise: 02_Loops/99_Extras.ipynb -- name: 03_Data_Structures_Func - overview: 03_Data_Structures_Func/README.md + uid: VJSgvOr5 + exercise: 30_Loops/160_Extras.ipynb +- name: Data Structures Func + uid: fDPxSid0 lessons: - name: Functions - exercise: 03_Data_Structures_Func/01_Functions.ipynb + uid: 4LyScnS5 + exercise: 40_Data_Structures_Func/10_Functions.ipynb - name: Dicts Sets - exercise: 03_Data_Structures_Func/02_Dicts_Sets.ipynb + uid: VXQdZcqg + exercise: 40_Data_Structures_Func/20_Dicts_Sets.ipynb - name: Funny Words Db - exercise: 03_Data_Structures_Func/04_Funny_Words_Db.py + exercise: 40_Data_Structures_Func/30_Funny_Words_Db.py + display: true - name: Splat Comprehension - exercise: 03_Data_Structures_Func/05_Splat_Comprehension.ipynb + uid: mU94qia6 + exercise: 40_Data_Structures_Func/40_Splat_Comprehension.ipynb - name: Tic Tac Toe - exercise: 03_Data_Structures_Func/06_Tic_Tac_Toe.py -- name: 04_Projects + exercise: 40_Data_Structures_Func/50_Tic_Tac_Toe.py + display: true +- name: Projects + uid: rLq5eVeW lessons: - name: Hotel Management - lesson: 04_Projects/01_Hotel_Management.md + lesson: 50_Projects/10_Hotel_Management.md - name: Random Walk - exercise: 04_Projects/02_Random_Walk.py + exercise: 50_Projects/20_Random_Walk.py display: true diff --git a/lessons/00_Turtles/01_Get_Started.ipynb b/lessons/00_Turtles/01_Get_Started.ipynb index 5b0c5fee..87e09773 100644 --- a/lessons/00_Turtles/01_Get_Started.ipynb +++ b/lessons/00_Turtles/01_Get_Started.ipynb @@ -209,7 +209,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.11" } }, "nbformat": 4, diff --git a/lessons/00_Turtles/04a_Turtle_Tricks.py b/lessons/00_Turtles/04a_Turtle_Tricks.py index 0b03a4a1..71271c74 100644 --- a/lessons/00_Turtles/04a_Turtle_Tricks.py +++ b/lessons/00_Turtles/04a_Turtle_Tricks.py @@ -18,6 +18,16 @@ # Make each side of the triangle a different color with # tina.pencolor() -... # Your code here + +tina.pencolor('red') +tina.forward(500) +tina.left(120) +tina.pencolor('blue') +tina.forward(500) +tina.left(120) +tina.pencolor('green') +tina.forward(500) +) + turtle.exitonclick() # Close the window when we click on it diff --git a/lessons/00_Turtles/04b_Turtle_Tricks.py b/lessons/00_Turtles/04b_Turtle_Tricks.py index d8809f47..922a8f6e 100644 --- a/lessons/00_Turtles/04b_Turtle_Tricks.py +++ b/lessons/00_Turtles/04b_Turtle_Tricks.py @@ -16,7 +16,20 @@ # Use tina.forward() and tina.left() to draw a pentagon # Make each side of the pentagon a different color with # tina.pencolor() - +tina.pencolor('red') +tina.forward(100) +tina.left(72) +tina.pencolor('blue') +tina.forward(100) +tina.left(72) +tina.pencolor('green') +tina.forward(100) +tina.left(72) +tina.pencolor('purple') +tina.forward(100) +tina.left(72) +tina.pencolor('pink') +tina.forward(100) ... # Your code here diff --git a/lessons/00_Turtles/04c_Turtle_Tricks.py b/lessons/00_Turtles/04c_Turtle_Tricks.py index 2cf9ab33..926f50a8 100644 --- a/lessons/00_Turtles/04c_Turtle_Tricks.py +++ b/lessons/00_Turtles/04c_Turtle_Tricks.py @@ -17,6 +17,20 @@ # Use tina.circle() to draw a circle, and tina.goto() to move tina to a new location # Use tina.begin_fill(), tina.end_fill(), and tina.fillcolor() to fill in the shapes +tina.penup() +tina.goto(100,100) +tina.pendown() +tina.begin_fill() +tina.fillcolor('red') +tina.circle(101, steps = 50) +tina.end_fill() +tina.penup() +tina.goto(100,0) +tina.pendown() +tina.begin_fill() +tina.fillcolor('blue') +tina.circle(101, steps = 50) +tina.end_fill() ... # Your code here diff --git a/lessons/00_Turtles/05a_Loops.ipynb b/lessons/00_Turtles/05a_Loops.ipynb index f48d82ef..c9f5ad4e 100644 --- a/lessons/00_Turtles/05a_Loops.ipynb +++ b/lessons/00_Turtles/05a_Loops.ipynb @@ -67,6 +67,13 @@ " print('Loop Iteration', i)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "metadata": {}, @@ -82,13 +89,6 @@ "\n", "Now try updating the next program ``05_Loop_with_Turtle.py`` with a loop. " ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/lessons/00_Turtles/05b_Loop_with_Turtle.py b/lessons/00_Turtles/05b_Loop_with_Turtle.py index 5aed03b9..e4e14c07 100644 --- a/lessons/00_Turtles/05b_Loop_with_Turtle.py +++ b/lessons/00_Turtles/05b_Loop_with_Turtle.py @@ -16,17 +16,9 @@ tina.shape('turtle') # Set the shape of the turtle to a turtle tina.speed(2) # Make the turtle move as fast, but not too fast. -tina.forward(150) # Move tina forward by the forward distance -tina.left(90) # Turn tina left by the left turn - -tina.forward(150) # Continue the last two steps three more times -tina.left(90) # to draw a square - -tina.forward(150) -tina.left(90) - -tina.forward(150) -tina.left(90) +for i in range(4): + tina.forward(150) # Move tina forward by the forward distance + tina.left(90) # Turn tina left by the left turn turtle.exitonclick() # Close the window when we click on it diff --git a/lessons/00_Turtles/05c_Loop_with_Turtle.py b/lessons/00_Turtles/05c_Loop_with_Turtle.py index 790e179e..ec9a396b 100644 --- a/lessons/00_Turtles/05c_Loop_with_Turtle.py +++ b/lessons/00_Turtles/05c_Loop_with_Turtle.py @@ -7,5 +7,19 @@ ( You can cut and past most of it! ) """ +import turtle # Tell Python we want to work with the turtle +turtle.setup (width=600, height=600) # Set the size of the window + +tina = turtle.Turtle() # Create a turtle named tina + +tina.shape('turtle') # Set the shape of the turtle to a turtle +tina.speed(2) # Make the turtle move as fast, but not too fast. + +for i in range(5): + tina.forward(150) # Move tina forward by the forward distance + tina.left(72) # Turn tina left by the left turn + + +turtle.exitonclick() # Close the window when we click on it ... # Your code here diff --git a/lessons/00_Turtles/06a_Variables_and_Functions.ipynb b/lessons/00_Turtles/06a_Variables_and_Functions.ipynb index 8170d4f9..9b302a2c 100644 --- a/lessons/00_Turtles/06a_Variables_and_Functions.ipynb +++ b/lessons/00_Turtles/06a_Variables_and_Functions.ipynb @@ -97,9 +97,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Angle for 1 sides is Ellipsis\n", + "Angle for 2 sides is Ellipsis\n", + "Angle for 3 sides is Ellipsis\n", + "Angle for 4 sides is Ellipsis\n", + "Angle for 5 sides is Ellipsis\n", + "Angle for 6 sides is Ellipsis\n", + "Angle for 7 sides is Ellipsis\n", + "Angle for 8 sides is Ellipsis\n", + "Angle for 9 sides is Ellipsis\n" + ] + } + ], "source": [ "# Run me!\n", "\n", @@ -144,19 +160,45 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'say_hello' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[4], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43msay_hello\u001b[49m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mbob\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;241m3\u001b[39m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'say_hello' is not defined" + ] + } + ], "source": [ "say_hello('bob',3)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'say_hello' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[3], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43msay_hello\u001b[49m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m-- nunya business!!!\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;241m5\u001b[39m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'say_hello' is not defined" + ] + } + ], + "source": [ + "say_hello('-- nunya business!!!', 5)" + ] } ], "metadata": { @@ -175,7 +217,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/lessons/00_Turtles/06b_Variables_and_Functions.ipynb b/lessons/00_Turtles/06b_Variables_and_Functions.ipynb index 1479a69f..f156ab7a 100644 --- a/lessons/00_Turtles/06b_Variables_and_Functions.ipynb +++ b/lessons/00_Turtles/06b_Variables_and_Functions.ipynb @@ -33,9 +33,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "60.0" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Run me\n", "# Compute the angle for a number of sides\n", @@ -124,17 +135,51 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'say_hello' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[2], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43msay_hello\u001b[49m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mbob\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;241m3\u001b[39m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'say_hello' is not defined" + ] + } + ], "source": [ + "\n", "say_hello('bob',3)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 Hello -- NUNYA BUSINESS!!!\n", + "1 Hello -- NUNYA BUSINESS!!!\n", + "2 Hello -- NUNYA BUSINESS!!!\n", + "3 Hello -- NUNYA BUSINESS!!!\n", + "4 Hello -- NUNYA BUSINESS!!!\n", + "5 Hello -- NUNYA BUSINESS!!!\n", + "6 Hello -- NUNYA BUSINESS!!!\n" + ] + } + ], + "source": [ + "def say_hello(name, times): # define the function, and give it a name. 'name' and 'times' are parameters\n", + "\n", + " for i in range(times): # This is the body of the function\n", + " print(i, \"Hello \", name)\n", + "\n", + "say_hello('-- NUNYA BUSINESS!!!', 7) " + ] } ], "metadata": { @@ -153,7 +198,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/lessons/00_Turtles/07_Efficient_Turtle.py b/lessons/00_Turtles/07_Efficient_Turtle.py index 46865d59..68af9456 100644 --- a/lessons/00_Turtles/07_Efficient_Turtle.py +++ b/lessons/00_Turtles/07_Efficient_Turtle.py @@ -17,22 +17,30 @@ def draw_polygon(sides): - angle = ... # Calculate angle from number of sides + angle = 360/sides - for i in range(...): # Loop through the number of sides - ... # Move tina forward by the forward distance - ... # Turn tina left by the left turn + for i in range(sides): # Loop through the number of sides + tina.forward(200) + tina.left(angle) # Turn tina left by the left turn -draw_polygon(...) # Draw a square +draw_polygon(4) # Draw a square -... # Move tina to another spot on the screen +tina.penup() +tina.goto(100,100) +tina.pendown() # Move tina to another spot on the screen -draw_polygon(...) # Draw a pentagon +draw_polygon(5) # Draw a pentagon -... # Move tina to another spot on the screen +tina.penup() +tina.goto(100,0) +tina.pendown() # Move tina to another spot on the screen -draw_polygon(...) # Draw a hexagon +draw_polygon(6) # Draw a hexagon + +tina.penup() +tina.goto(200,-100) +tina.pendown() # Move tina to another spot on the screen turtle.exitonclick() # Close the window when we click on it diff --git a/lessons/00_Turtles/08a_More_Turtle_Programs.ipynb b/lessons/00_Turtles/08a_More_Turtle_Programs.ipynb index 2d894a5e..bfb53058 100644 --- a/lessons/00_Turtles/08a_More_Turtle_Programs.ipynb +++ b/lessons/00_Turtles/08a_More_Turtle_Programs.ipynb @@ -79,6 +79,11 @@ "```\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, { "cell_type": "markdown", "metadata": {}, @@ -342,7 +347,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.11" } }, "nbformat": 4, diff --git a/lessons/00_Turtles/08b_More_Turtle_programs.py b/lessons/00_Turtles/08b_More_Turtle_programs.py index f55ccc31..9e350880 100644 --- a/lessons/00_Turtles/08b_More_Turtle_programs.py +++ b/lessons/00_Turtles/08b_More_Turtle_programs.py @@ -8,3 +8,42 @@ directory ) and moves to the corners of the screen in a square pattern. """ +# Change the Turtle Image + + +import turtle + + +def set_turtle_image(turtle, image_name): + """Set the turtle's shape to a custom image.""" + + from pathlib import Path + image_dir = Path(__file__).parent / "images" + image_path = str(image_dir / image_name) + + screen = turtle.getscreen() + screen.addshape(image_path) + turtle.shape(image_path) + +# Set up the screen +screen = turtle.Screen() +screen.setup(width=600, height=600) + +# Create a turtle and set its shape to the custom GIF +t = turtle.Turtle() + +set_turtle_image(t, "pikachu.gif") + + +t.speed(3) + +t.penup() +t.goto(200, 200) +t.goto(200,-200) +t.goto(-200, -200) +t.goto(-200, 200) +t.goto(200,200) + + +turtle.exitonclick() + diff --git a/lessons/00_Turtles/08c_More_Turtle_Programs.py b/lessons/00_Turtles/08c_More_Turtle_Programs.py index e80bdf19..248096da 100644 --- a/lessons/00_Turtles/08c_More_Turtle_Programs.py +++ b/lessons/00_Turtles/08c_More_Turtle_Programs.py @@ -7,3 +7,45 @@ Then change the code so that the turtle has a different image ( look in the 'images' directory ) and moves to the corners of the screen in a square pattern. """ +# Change the Background Image + + + + +import turtle + +def set_background_image(window, image_name): + """Set the background image of the turtle window to the image with the given name.""" + + from pathlib import Path + from PIL import Image + + + image_dir = Path(__file__).parent / "images" + image_path = str(image_dir / image_name) + + image = Image.open(image_path) + + window.setup(image.width, image.height, startx=0, starty=0) + window.bgpic(image_path) + +# Set up the screen +import turtle # Tell Python we want to work with the turtle +turtle.setup(width=600, height=600) # Set the size of the window + +tina = turtle.Turtle() # Create a turtle named tina + +screen = turtle.Screen() # Get the screen that tina is on +set_background_image(screen, "emoji.png") # Set the background image of the screen + +tina.speed(3) + +tina.penup() +tina.goto(200, 200) +tina.goto(200,-200) +tina.goto(-200, -200) +tina.goto(-200, 200) +tina.goto(200,200) + +turtle.exitonclick() + diff --git a/lessons/00_Turtles/08d_More_Turtle_Programs.py b/lessons/00_Turtles/08d_More_Turtle_Programs.py index 350130f5..107bc18b 100644 --- a/lessons/00_Turtles/08d_More_Turtle_Programs.py +++ b/lessons/00_Turtles/08d_More_Turtle_Programs.py @@ -13,3 +13,39 @@ y = random.randint(-300, 300) """ + +# Double click on this cell to copy the code + +import turtle as turtle +import random +turtle.setup(width=600, height=600) + +t = turtle.Turtle() +screen = turtle.Screen() +t.shape("turtle") +t.turtlesize(stretch_wid=10, stretch_len=10, outline=4) # Make the turtle really big + +def turtle_clicked(t, x, y): + """Function that gets called when the user clicks on the turtle + + This function will make the turtle tilt 20 degrees 18 times, making a full + circle. It is called by the turtle when the user clicks on it. + + Args: + t (Turtle): The turtle object that was clicked + x (int): The x coordinate of the click + y (int): The y coordinate of the click + """ + t.penup() + print('turtle clicked!') + t.goto(x,y) + t.pendown() + t.circle(30) + +# Connect the turtle to the turtle_clicked function +screen.onclick(lambda x, y, t=t: turtle_clicked(t, x,y)) + + +turtle.done() # Important! Use `done` not `exitonclick` to keep the window open + + diff --git a/lessons/00_Turtles/09_LeagueBot.py b/lessons/00_Turtles/09_LeagueBot.py index 3aa88030..027b53eb 100644 --- a/lessons/00_Turtles/09_LeagueBot.py +++ b/lessons/00_Turtles/09_LeagueBot.py @@ -15,6 +15,28 @@ screen.setup(width=600, height=600) screen.bgcolor('white') + + +... # Your Code Here +def set_turtle_image(turtle, image_name): + """Set the turtle's shape to a custom image.""" + + from pathlib import Path + image_dir = Path(__file__).parent / "images" + image_path = str(image_dir / image_name) + + screen = turtle.getscreen() + screen.addshape(image_path) + turtle.shape(image_path) + t = turtle.Turtle() +set_turtle_image(t, "leaguebot_bolt.gif") + +t.turtlesize(stretch_wid=10, stretch_len=10, outline=1) +t.pendown() +t.pencolor('blue') -... # Your Code Here \ No newline at end of file +for i in range(6): + t.left(60) + t.forward(50) + \ No newline at end of file diff --git a/lessons/00_Turtles/10a_Tash_Me.py b/lessons/00_Turtles/10a_Tash_Me.py index 08cea35b..9cff07a1 100644 --- a/lessons/00_Turtles/10a_Tash_Me.py +++ b/lessons/00_Turtles/10a_Tash_Me.py @@ -3,11 +3,49 @@ Write a program that: 1) Loads an emoji image as the background 2) Make the turtle shape a moustach -3) Move the moustache to the right spont on the emoji +3) Move the moustache to the right spot on the emoji Hint: See 08a_More Turtle Programs, section 'Change the Background Image' and 'Change the Turtle Shape' """ ... # Your code here +def set_background_image(window, image_name): + + from pathlib import Path + from PIL import Image + + + image_dir = Path(__file__).parent / "images" + image_path = str(image_dir / image_name) + + image = Image.open(image_path) + + window.setup(image.width, image.height, startx=0, starty=0) + window.bgpic(image_path) +import turtle +turtle.setup(width=600, height=600) + +tina = turtle.Turtle() + +screen = turtle.Screen() +set_background_image(screen, "emoji.png") +def set_turtle_image(turtle, image_name): + """Set the turtle's shape to a custom image.""" + + from pathlib import Path + image_dir = Path(__file__).parent / "images" + image_path = str(image_dir / image_name) + + screen = turtle.getscreen() + screen.addshape(image_path) + turtle.shape(image_path) + +set_turtle_image(tina, "moustache1.gif") +tina.goto(300,0) + + + + +turtle.exitonclick() diff --git a/lessons/00_Turtles/10b_Tash_Me_Click.py b/lessons/00_Turtles/10b_Tash_Me_Click.py index 0e92e108..241444e9 100644 --- a/lessons/00_Turtles/10b_Tash_Me_Click.py +++ b/lessons/00_Turtles/10b_Tash_Me_Click.py @@ -7,3 +7,57 @@ ... # Your code here +def set_background_image(window, image_name): + + + from pathlib import Path + from PIL import Image + + + image_dir = Path(__file__).parent / "images" + image_path = str(image_dir / image_name) + + image = Image.open(image_path) + + window.setup(image.width, image.height, startx=0, starty=0) + window.bgpic(image_path) +import turtle +turtle.setup(width=600, height=600) + +tina = turtle.Turtle() + +screen = turtle.Screen() +set_background_image(screen, "emoji.png") +def set_turtle_image(turtle, image_name): + """Set the turtle's shape to a custom image.""" + + from pathlib import Path + image_dir = Path(__file__).parent / "images" + image_path = str(image_dir / image_name) + + screen = turtle.getscreen() + screen.addshape(image_path) + turtle.shape(image_path) + +set_turtle_image(tina, "moustache1.gif") +tina.goto(300,0) +def turtle_clicked(t, x, y): + """Function that gets called when the user clicks on the turtle + + This function will make the turtle tilt 20 degrees 18 times, making a full + circle. It is called by the turtle when the user clicks on it. + + Args: + t (Turtle): The turtle object that was clicked + x (int): The x coordinate of the click + y (int): The y coordinate of the click + """ + + print('turtle clicked!') + + t.goto(x,y) +tina.onclick(lambda x, y, tina=tina: turtle_clicked(tina, x, y)) + + + +turtle.done() diff --git a/lessons/00_Turtles/10c_Tash_Me_Twirl.py b/lessons/00_Turtles/10c_Tash_Me_Twirl.py index 40b384d9..0ddef266 100644 --- a/lessons/00_Turtles/10c_Tash_Me_Twirl.py +++ b/lessons/00_Turtles/10c_Tash_Me_Twirl.py @@ -9,3 +9,59 @@ ... # Your code here +def set_background_image(window, image_name): + + + from pathlib import Path + from PIL import Image + + + image_dir = Path(__file__).parent / "images" + image_path = str(image_dir / image_name) + + image = Image.open(image_path) + + window.setup(image.width, image.height, startx=0, starty=0) + window.bgpic(image_path) +import turtle +turtle.setup(width=600, height=600) + +tina = turtle.Turtle() + +screen = turtle.Screen() +#set_background_image(screen, "emoji.png") +def set_turtle_image(turtle, image_name): + """Set the turtle's shape to a custom image.""" + + from pathlib import Path + image_dir = Path(__file__).parent / "images" + image_path = str(image_dir / image_name) + + screen = turtle.getscreen() + screen.addshape(image_path) + turtle.shape(image_path) + +set_turtle_image(tina, "moustache2.gif") +#tina.goto(300,0) +def turtle_clicked(t, x, y): + """Function that gets called when the user clicks on the turtle + + This function will make the turtle tilt 20 degrees 18 times, making a full + circle. It is called by the turtle when the user clicks on it. + + Args: + t (Turtle): The turtle object that was clicked + x (int): The x coordinate of the click + y (int): The y coordinate of the click + """ + + print('turtle clicked!') + #t.goto(x, y) + for i in range(0,360, 20): + t.tilt(i) + +tina.onclick(lambda x, y, tina=tina: turtle_clicked(tina, x, y)) + + + +turtle.done() diff --git a/lessons/00_Turtles/11_Lists.ipynb b/lessons/00_Turtles/11_Lists.ipynb index 1266bf5f..0b60759a 100644 --- a/lessons/00_Turtles/11_Lists.ipynb +++ b/lessons/00_Turtles/11_Lists.ipynb @@ -140,6 +140,22 @@ "cell_type": "markdown", "metadata": {}, "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dooooodoooooo" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/lessons/00_Turtles/12_Color_Lines.py b/lessons/00_Turtles/12_Color_Lines.py index a0be2cf0..88a3c6b3 100644 --- a/lessons/00_Turtles/12_Color_Lines.py +++ b/lessons/00_Turtles/12_Color_Lines.py @@ -17,11 +17,15 @@ colors = [ 'red', 'blue', 'black', 'orange'] # define a list of colors for color in colors: # loop through the colors - ... # Your code here - + tina.color(color) + tina.forward(50) + tina.left(90) # 2) Make another square, but put the colors in reverse order, using a negative index. - +for color in reversed(colors): # loop through the colors + tina.color(color) + tina.forward(50) + tina.left(-90) ... # Your code here turtle.exitonclick() # Close the window when we click on it \ No newline at end of file diff --git a/lessons/00_Turtles/13_Flaming_Ninja_Star.py b/lessons/00_Turtles/13_Flaming_Ninja_Star.py index b8c8464b..03187301 100644 --- a/lessons/00_Turtles/13_Flaming_Ninja_Star.py +++ b/lessons/00_Turtles/13_Flaming_Ninja_Star.py @@ -22,14 +22,14 @@ def getNextColor(i): turtle.setup (width=600, height=600) window = turtle.Screen() -baseSize = 200 # the size of the black part of the star +baseSize = 1 # the size of the black part of the star flameSize = 130 # the length of the flaming arms t = turtle.Turtle() t.shape("turtle") -t.width(2) +t.width(20) t.speed(0) @@ -40,17 +40,17 @@ def getNextColor(i): t.begin_fill() - t.forward(64) + t.forward(47) - t.left(40) + t.left(34) t.forward(flameSize) - t.right(170) + t.right(123) t.forward(flameSize) - t.right(62) + t.right(53) t.forward(baseSize) diff --git a/lessons/00_Turtles/16_Turtle_Spiral.py b/lessons/00_Turtles/16_Turtle_Spiral.py index f167d58b..4340c21e 100644 --- a/lessons/00_Turtles/16_Turtle_Spiral.py +++ b/lessons/00_Turtles/16_Turtle_Spiral.py @@ -38,8 +38,8 @@ def getRandomColor(): # Move the turtle (5*i) pixels. 'i' is the loop variable myTurtle.forward(9 * i) - # Turn the turtle (360/7) degrees to the right - myTurtle.right(360 / 7 + i*5) + # Turn the turtle (30/7) degrees to the right + myTurtle.right(30 / 91 + i*5) # Change the turtle width to 'i' (the loop variable) myTurtle.width(i) diff --git a/lessons/01_Types_and_Logic/02_Control_Flow.ipynb b/lessons/01_Types_and_Logic/02_Control_Flow.ipynb index 08700f15..7963393e 100644 --- a/lessons/01_Types_and_Logic/02_Control_Flow.ipynb +++ b/lessons/01_Types_and_Logic/02_Control_Flow.ipynb @@ -46,9 +46,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'a' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[1], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Evaluating boolean expressions. \u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124ma == 11:\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[43ma\u001b[49m \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m11\u001b[39m)\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124ma == 10:\u001b[39m\u001b[38;5;124m\"\u001b[39m, a \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m10\u001b[39m)\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124ma < 20:\u001b[39m\u001b[38;5;124m\"\u001b[39m, a \u001b[38;5;241m<\u001b[39m \u001b[38;5;241m20\u001b[39m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'a' is not defined" + ] + } + ], "source": [ "# Evaluating boolean expressions. \n", "print(\"a == 11:\", a == 11)\n", @@ -77,9 +89,31 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a==10 True\n", + "b<20 True\n", + "c==30 False\n", + "c=='30' True\n", + "a == b-5 True\n" + ] + }, + { + "data": { + "text/plain": [ + "Ellipsis" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Test Yourself\n", "\n", @@ -91,22 +125,22 @@ "\n", "# Is a equal to 10?\n", "\n", - "print(a == 10)\n", + "print(\"a==10\", a == 10)\n", "\n", "# Is b less than 20?\n", - "\n", + "print (\"b<20\", b<20)\n", "...\n", "\n", "# Is c equal to the *integer* 30?\n", - "\n", + "print(\"c==30\", c==30)\n", "...\n", "\n", "# Is c equal to the *string* '30'?\n", - "\n", + "print(\"c=='30'\", c=='30')\n", "...\n", "\n", "# Is a equal to b minus 5?\n", - "\n", + "print(\"a == b-5\", a==b-5)\n", "...\n" ] }, @@ -157,9 +191,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "success\n" + ] + } + ], "source": [ "# Test Yourself\n", "\n", @@ -175,22 +217,22 @@ "\n", "# Set last_is_world to be true if the last world in s is 'world'\n", "\n", - "last_is_world = ...\n", + "last_is_world = s.endswith('world')\n", "\n", "# set last_is_hello to be true if the last world in s is 'hello'\n", "\n", - "last_is_hello = ...\n", + "last_is_hello = s.endswith('hello')\n", "\n", "# if a is 10 and the last word in s is 'world' print 'success'\n", "\n", - "if ...:\n", - " print(...)\n", + "if a==10 and s.endswith('world'):\n", + " print('success')\n", "\n", "\n", "# If the integer value of c is 30 or b is evenly divisible by 5, print 'success'\n", "\n", - "if ...:\n", - " print(...)\n", + "if c==30 and b/5:\n", + " print('success')\n", "\n", "\n" ] @@ -246,22 +288,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fb\n" + ] + } + ], "source": [ "# Test yourself\n", "\n", - "fb = ...\n", + "fb = 67\n", "\n", - "if ...:\n", - " print(...)\n", + "if fb%5 == 0:\n", + " print('fizz')\n", "\n", - "elif ...:\n", - " ...\n", + "elif fb%3 == 0:\n", + " print('buzz')\n", " \n", "else:\n", - " ...\n", + " print('fb')\n", "\n" ] }, @@ -329,7 +379,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -343,7 +393,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.0" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/lessons/01_Types_and_Logic/03_My_Ages.py b/lessons/01_Types_and_Logic/03_My_Ages.py index e3ecea4b..15550480 100644 --- a/lessons/01_Types_and_Logic/03_My_Ages.py +++ b/lessons/01_Types_and_Logic/03_My_Ages.py @@ -37,12 +37,26 @@ window.withdraw() # Hide the window; we just want to see pop ups # Ask the user's age - +age = simpledialog.askinteger("Your Age", "How old are you?") # Use if statements to determine the age group +if age<3 and age >-1: + group = 'baby' +if age<6 and age>2: + group = 'toddler' +if age<13 and age>5: + group = 'child' +if age<20 and age>12: + group = 'teen' +if age<65 and age>19: + group = 'adult' +if age>64: + group = 'senior' +else: + group = 'nobody' # and create a message # Show the message to the user - +messagebox.showinfo('What you are', "You are a " + group) window.mainloop() # Keeps the window open diff --git a/lessons/01_Types_and_Logic/04_Simple_Adder.py b/lessons/01_Types_and_Logic/04_Simple_Adder.py index 7d7e2f4c..ec4933da 100644 --- a/lessons/01_Types_and_Logic/04_Simple_Adder.py +++ b/lessons/01_Types_and_Logic/04_Simple_Adder.py @@ -10,16 +10,21 @@ """ # Import the required modules +from tkinter import messagebox, simpledialog, Tk # import required modules +window = Tk() # Create a window object +window.withdraw() # Hide the window; we just want to see pop ups # Create a window object # Hide the window, hint: use the withdraw method # Ask the user for the first number - +num1 = simpledialog.askinteger("Number 1", "Gimme a number") # Ask the user for the second number - +num2 = simpledialog.askinteger("Number 2", "Gimme another number") # Display the sum of the two numbers +final = num1+num2 +messagebox.showinfo('Sum', "The sum is: " + str(final)) # Keep the window open - +window.mainloop() diff --git a/lessons/01_Types_and_Logic/05_Infuriating_Calculator.py b/lessons/01_Types_and_Logic/05_Infuriating_Calculator.py index 30dd284e..daa9f224 100644 --- a/lessons/01_Types_and_Logic/05_Infuriating_Calculator.py +++ b/lessons/01_Types_and_Logic/05_Infuriating_Calculator.py @@ -22,19 +22,36 @@ """ # Import the required modules +from tkinter import messagebox, simpledialog, Tk # import required modules +window = Tk() # Create a window object +window.withdraw() # Hide the window; we just want to see pop ups # Create a window object # Hide the window, hint: use the withdraw method # Ask the user for the first number - +num1 = simpledialog.askinteger("Number 1", "Gimme a number") # Ask the user for the second number +num2 = simpledialog.askinteger("Number 2", "Gimme another number") -# Ask the user for the math operation +# Ask the user for the math operation +oper = simpledialog.askstring("Operation", "Gimme a operation in STRINGY TERMS") # Use if-elif-else statements to provide the desired math operation on the numbers and display the result. - +if oper == 'add': + final = num1+num2 +if oper == 'subtract': + final = num1-num2 +if oper == 'multiply': + final = num1*num2 +if oper == 'divide': + final = num1/num2 +else: + messagebox.showerror # If the user enters an unknown operation, display an error message. ( use messagebox.showerror() +messagebox.showinfo('Final Answer', "Your answer is: " + str(final)) + +window.mainloop() # Keep the window open diff --git a/lessons/01_Types_and_Logic/07_Code_Challenges.ipynb b/lessons/01_Types_and_Logic/07_Code_Challenges.ipynb index 1401903e..faf1cbfa 100644 --- a/lessons/01_Types_and_Logic/07_Code_Challenges.ipynb +++ b/lessons/01_Types_and_Logic/07_Code_Challenges.ipynb @@ -76,14 +76,38 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "weird\n", + "weird\n", + "weird\n", + "weird\n", + "weird\n", + "weird\n", + "weird\n", + "weird\n" + ] + } + ], "source": [ "# Your solution here\n", - "\n", "for n in [3, 5, 7, 11, 13, 17, 19, 23]:\n", - " ..." + "\n", + " if n%2==1:\n", + " print('weird')\n", + " if n%2==0 and 120:\n", + " print('not weird') \n", + " \n", + " " ] }, { @@ -109,7 +133,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -123,7 +147,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.9" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/lessons/02_Loops/02_Loops_with_Range.ipynb b/lessons/02_Loops/02_Loops_with_Range.ipynb index ac37d8fd..95fdf486 100644 --- a/lessons/02_Loops/02_Loops_with_Range.ipynb +++ b/lessons/02_Loops/02_Loops_with_Range.ipynb @@ -92,12 +92,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2013, 2015, 2017, 2019, 2021, 2023, 2025]\n" + ] + }, + { + "data": { + "text/plain": [ + "Ellipsis" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Test yourself\n", - "\n", + "print(list(range(2013, 2026, 2)))\n", "..." ] }, @@ -151,7 +169,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -165,7 +183,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.0" + "version": "3.12.11" } }, "nbformat": 4, diff --git a/lessons/02_Loops/03a_Lists.ipynb b/lessons/02_Loops/03a_Lists.ipynb index f9d41f48..2cc0f47e 100644 --- a/lessons/02_Loops/03a_Lists.ipynb +++ b/lessons/02_Loops/03a_Lists.ipynb @@ -32,18 +32,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "9280847b", "metadata": { "lines_to_next_cell": 0 }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "milk\n" + ] + } + ], "source": [ "# Indexing a list\n", "\n", "things_to_buy = [ 'apples','oranges','bread','milk']\n", "\n", - "a = things_to_buy[1]\n", + "a = things_to_buy[3]\n", "print(a)\n", "\n", "# Try changing the number in the [] and see what happens. " @@ -395,19 +403,38 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "6c51bbf8", "metadata": { "title": "[python]" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['bob', 'alex', 'brumblesnoozle']\n" + ] + } + ], "source": [ "# Test yourself\n", "\n", "# Here is how to get a name from the user.\n", "# name = input(\"What is your friend's name? \")\n", "# Look at the ^^^^ top of the window ^^^ for the prompt\n", - "\n" + "l = []\n", + "name1 = input(\"What is your friend's name?\")\n", + "name2 = input(\"What is another friend's name?\")\n", + "name3 = input(\"What is one other friend's name?\")\n", + "\n", + "l.append(name1)\n", + "l.append(name2)\n", + "l.append(name3)\n", + "\n", + "l.sort\n", + "\n", + "print(l)" ] } ], @@ -418,7 +445,7 @@ "notebook_metadata_filter": "-all" }, "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -432,7 +459,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.0" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/lessons/02_Loops/03b_Crazy_Tina.py b/lessons/02_Loops/03b_Crazy_Tina.py index bb2582f5..a7d974b3 100644 --- a/lessons/02_Loops/03b_Crazy_Tina.py +++ b/lessons/02_Loops/03b_Crazy_Tina.py @@ -22,15 +22,15 @@ tina.speed(2) # Make the turtle move as fast, but not too fast. -forwards = [ ... ] -lefts = [ ... ] -colors = [ ... ] +forwards = [-20, 30, -40, -19, 27, -39, 43, 94] +lefts = [10, -20, 30, 23, -13, 12, -14, -38] +colors = ['red', 'blue', 'green', 'yellow', 'pink', 'orange', 'purple', 'brown'] for i in range(8): - forward = ... - left = ... - color = ... + forward = forwards[i] + left = lefts[i] + color = colors[i] tina.color(color) diff --git a/lessons/02_Loops/03c_Tuples.ipynb b/lessons/02_Loops/03c_Tuples.ipynb index 93ca04c5..22a47478 100644 --- a/lessons/02_Loops/03c_Tuples.ipynb +++ b/lessons/02_Loops/03c_Tuples.ipynb @@ -73,9 +73,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "(3, 4)\n" + ] + } + ], "source": [ "t = (1, 2, 3, 4, 5) \n", "\n", @@ -93,7 +102,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -107,7 +116,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.0" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/lessons/02_Loops/04a_Indexing_and_Slicing.ipynb b/lessons/02_Loops/04a_Indexing_and_Slicing.ipynb index a047f923..98c44f96 100644 --- a/lessons/02_Loops/04a_Indexing_and_Slicing.ipynb +++ b/lessons/02_Loops/04a_Indexing_and_Slicing.ipynb @@ -46,9 +46,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1:3] ['blue', 'black']\n", + "[:2] ['red', 'blue']\n", + "[2:] ['black', 'orange']\n" + ] + } + ], "source": [ "# Slicing lists (Run Me!)\n", "\n", @@ -83,9 +93,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[-3:] [8, 9, 10]\n", + "[:-3] [1, 2, 3, 4, 5, 6, 7]\n", + "[-6:-3] [5, 6, 7]\n", + "[2:-2] [3, 4, 5, 6, 7, 8]\n", + "[-6:8] [5, 6, 7, 8]\n", + "[-1] 10\n", + "[-3:] [8, 9, 10]\n" + ] + } + ], "source": [ "# Slicing with negative ( Run me!)\n", "\n", @@ -153,7 +177,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -167,7 +191,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/lessons/02_Loops/04b_List_Story.py b/lessons/02_Loops/04b_List_Story.py index 785c7d3e..be9a38d6 100644 --- a/lessons/02_Loops/04b_List_Story.py +++ b/lessons/02_Loops/04b_List_Story.py @@ -9,7 +9,9 @@ words = ['Once', '👦', 'upon', '🐕', 'park', 'met', 'with', 'a', 'the', 'time', 'to', 'who', '🐈', '👧', 'and', 'went', 'had', 'play', '⚽.', 'they'] -story = [] + +#. once upon a time a dog met +story = [words[0], words[2], words[7], words[9]] # Create a story using the words in the list diff --git a/lessons/02_Loops/05_Strings.ipynb b/lessons/02_Loops/05_Strings.ipynb index 89e5d060..ccbae5cf 100644 --- a/lessons/02_Loops/05_Strings.ipynb +++ b/lessons/02_Loops/05_Strings.ipynb @@ -80,9 +80,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a\tb?\tc!!\t\n", + "1\t2\t3\t\n", + "\n" + ] + } + ], "source": [ "# Tabs and Newlines\n", "\n", @@ -111,18 +121,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Roses are red, voilets are blue, Sugar is sweet, and dogs are too\n", + "a\tb\tc\t\n", + "1\t2\t3\n", + "\n" + ] + } + ], "source": [ "# Test Yourself\n", "\n", - "poem = \"\"\"\n", - "\"\"\"\n", + "poem = \"Roses are red,\" \" voilets are blue,\" \" Sugar is sweet,\" \" and dogs are too\"\n", "\n", "print(poem)\n", "\n", - "friends = \"\"\n", + "friends = \"a\\tb\\tc\\t\\n1\\t2\\t3\\n\"\n", "\n", "print(friends)\n", "\n", @@ -168,9 +188,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'name' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[1], line 5\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# More F-Strings\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \n\u001b[1;32m 3\u001b[0m \u001b[38;5;66;03m# You can put lots of expressions inside the curly braces, not just variable names\u001b[39;00m\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[43mname\u001b[49m\u001b[38;5;241m.\u001b[39mupper()\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m is \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mage\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m years old. In 5 years, he will be \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mage\u001b[38;5;250m \u001b[39m\u001b[38;5;241m+\u001b[39m\u001b[38;5;250m \u001b[39m\u001b[38;5;241m5\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m years old.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 7\u001b[0m \u001b[38;5;66;03m# You can add a colon after the variable name to format the output\u001b[39;00m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;66;03m# For instance, to make a number appear with commas as thousands separators, you can write {number:,}\u001b[39;00m\n\u001b[1;32m 9\u001b[0m \u001b[38;5;66;03m# or to make it have only 2 decimal places, you can write {number:.2f}\u001b[39;00m\n\u001b[1;32m 11\u001b[0m number \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1234567.890123\u001b[39m\n", + "\u001b[0;31mNameError\u001b[0m: name 'name' is not defined" + ] + } + ], "source": [ "# More F-Strings\n", "\n", @@ -203,9 +235,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Dear John,\n", + "\n", + "Congratulations! You have won a unicorn in our prize draw. \n", + "You are only 14 years old, so you must be very lucky!\n", + "\n", + "Yours sincerely,\n", + "The Prize Draw Team\n", + "\n" + ] + } + ], "source": [ "# Run Me\n", "\n", @@ -253,14 +301,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "!1 *2 = 2\n", + "!2 *2 = 4\n", + "!3 *2 = 6\n", + "!4 *2 = 8\n", + "!5 *2 = 10\n", + "!6 *2 = 12\n", + "!7 *2 = 14\n", + "!8 *2 = 16\n" + ] + } + ], "source": [ "# Test Yourself\n", "\n", "for i in range(1, 9):\n", - " ..." + " nums = f\"!{i} *2 = {i*2}\"\n", + " print(nums)\n" ] }, { @@ -312,9 +376,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['a', 'b', 'c', 'd', 'e']\n" + ] + } + ], "source": [ "# split on commas\n", "\n", @@ -333,9 +405,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python is fun to learn\n", + "a,b,c,d,e\n" + ] + } + ], "source": [ "# Run Me!\n", "# Join with spaces\n", @@ -358,9 +439,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python is amazing to learn\n" + ] + } + ], "source": [ "# Run Me!\n", "m = \"Python is fun to learn\"\n", @@ -416,9 +505,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python is fun!\n", + "Python is fun!\n" + ] + } + ], "source": [ "# Example\n", "\n", @@ -455,9 +553,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 30, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The train in Spain makes passengers complain.\n", + "The train in Spain makes flowers grow again.\n", + "The passengers grow flowers in Spain.\n", + "The flowers in Spain train passengers to complain.\n" + ] + } + ], "source": [ "# Test yourself \n", "\n", @@ -468,21 +577,41 @@ "s5 = \" \" \n", "\n", "# Print \"The train in Spain makes passengers complain.\"\n", - "\n", + "coco = s1[:-1]\n", + "period = s1[-1]\n", + "print(coco + s5 + s2 + period)\n", "\n", "# Print \"The rain in Spain makes flowers grow again\"\n", - "\n", - "\n", - "# Print \"The passengers grow flowers in Spain\n", - "\n", - "\n", - "# Print \"The flowers in Spain train passengers to complain.\"\n" + "s1list = s1.split()\n", + "train = s1list.pop(1)\n", + "rain = train[1:]\n", + "s1list.insert(1, train)\n", + "ss = ' '.join(s1list)\n", + "\n", + "newSpain = s1list.pop(3)\n", + "Period = newSpain[-1]\n", + "doo = ss[:-1]\n", + "\n", + "makes = s2.split()[0]\n", + "print(doo + ' ' + makes + ' ' + s3[0] + ' ' + s3[1] + ' ' + s3[2] + Period)\n", + "# Print \"The passengers grow flowers in Spain.\"\n", + "the = s1.split()[0]\n", + "pas = s2.split()[1]\n", + "lil = s1[10:]\n", + "\n", + "\n", + "print(the + ' ' + pas + ' ' + s3[1] + ' ' + s3[0] + ' ' + lil)\n", + "\n", + "# Print \"The flowers in Spain train passengers to complain.\"\n", + "lily = lil[:-1]\n", + "comp = s2.split()[2]\n", + "print (the + ' ' + s3[0] + ' ' + lily + ' ' + train + ' ' + pas + ' ' + s4 + ' ' + comp + Period)" ] } ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -496,7 +625,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.0" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/lessons/02_Loops/06_Fizz_Buzz_Badgers.py b/lessons/02_Loops/06_Fizz_Buzz_Badgers.py index 135e7afa..bcbcb603 100644 --- a/lessons/02_Loops/06_Fizz_Buzz_Badgers.py +++ b/lessons/02_Loops/06_Fizz_Buzz_Badgers.py @@ -17,7 +17,7 @@ """ -for i in range(1, 31): # Change only this line +for i in range(70, 130, 15): # Change only this line # Don't change anything below this line if i % 15 == 0: diff --git a/lessons/02_Loops/07_For_Loop_Gauntlet.ipynb b/lessons/02_Loops/07_For_Loop_Gauntlet.ipynb index c89802bc..64deab24 100644 --- a/lessons/02_Loops/07_For_Loop_Gauntlet.ipynb +++ b/lessons/02_Loops/07_For_Loop_Gauntlet.ipynb @@ -29,15 +29,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "id": "d0752dd4", "metadata": { "title": "[python]" }, - "outputs": [], + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (779618103.py, line 4)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m Cell \u001b[0;32mIn[12], line 4\u001b[0;36m\u001b[0m\n\u001b[0;31m print(a-=a)\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], "source": [ "# Display all numbers from 0 to 100 \n", - "\n" + "a = 100\n", + "for i in range(100):\n", + " print(a-=a)" ] }, { @@ -52,7 +63,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "id": "aec8cf23", "metadata": { "title": "[python]" @@ -60,7 +71,11 @@ "outputs": [], "source": [ "# Display all numbers from 100 to 0 \n", - "\n" + "# range(end)\n", + "# range(start, end)\n", + "# range(start,end,step). range(100,0)\n", + "for i in range(100,0):\n", + " print(i)\n" ] }, { @@ -75,15 +90,122 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "id": "ed3d8616", "metadata": { "lines_to_next_cell": 0, "title": "[python]" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "3\n", + "4\n", + "5\n", + "6\n", + "7\n", + "8\n", + "9\n", + "10\n", + "11\n", + "12\n", + "13\n", + "14\n", + "15\n", + "16\n", + "17\n", + "18\n", + "19\n", + "20\n", + "21\n", + "22\n", + "23\n", + "24\n", + "25\n", + "26\n", + "27\n", + "28\n", + "29\n", + "30\n", + "31\n", + "32\n", + "33\n", + "34\n", + "35\n", + "36\n", + "37\n", + "38\n", + "39\n", + "40\n", + "41\n", + "42\n", + "43\n", + "44\n", + "45\n", + "46\n", + "47\n", + "48\n", + "49\n", + "50\n", + "51\n", + "52\n", + "53\n", + "54\n", + "55\n", + "56\n", + "57\n", + "58\n", + "59\n", + "60\n", + "61\n", + "62\n", + "63\n", + "64\n", + "65\n", + "66\n", + "67\n", + "68\n", + "69\n", + "70\n", + "71\n", + "72\n", + "73\n", + "74\n", + "75\n", + "76\n", + "77\n", + "78\n", + "79\n", + "80\n", + "81\n", + "82\n", + "83\n", + "84\n", + "85\n", + "86\n", + "87\n", + "88\n", + "89\n", + "90\n", + "91\n", + "92\n", + "93\n", + "94\n", + "95\n", + "96\n", + "97\n", + "98\n", + "99\n" + ] + } + ], "source": [ - "# Display all even numbers from 2 to 100 \n" + "# Display all even numbers from 2 to 100 \n", + "for i in range(2, 100):\n", + " print(i)" ] }, { @@ -98,15 +220,73 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "id": "038f48bf", "metadata": { "lines_to_next_cell": 0, "title": "[python]" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "3\n", + "5\n", + "7\n", + "9\n", + "11\n", + "13\n", + "15\n", + "17\n", + "19\n", + "21\n", + "23\n", + "25\n", + "27\n", + "29\n", + "31\n", + "33\n", + "35\n", + "37\n", + "39\n", + "41\n", + "43\n", + "45\n", + "47\n", + "49\n", + "51\n", + "53\n", + "55\n", + "57\n", + "59\n", + "61\n", + "63\n", + "65\n", + "67\n", + "69\n", + "71\n", + "73\n", + "75\n", + "77\n", + "79\n", + "81\n", + "83\n", + "85\n", + "87\n", + "89\n", + "91\n", + "93\n", + "95\n", + "97\n" + ] + } + ], "source": [ - "# Display all odd numbers from 1 to 99 " + "# Display all odd numbers from 1 to 99 \n", + "for i in range(1, 99, 2):\n", + " print (i)" ] }, { @@ -128,12 +308,64 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "id": "174bdcd9", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 is odd\n", + "2 is even\n", + "3 is odd\n", + "4 is even\n", + "5 is odd\n", + "6 is even\n", + "7 is odd\n", + "8 is even\n", + "9 is odd\n", + "10 is even\n", + "11 is odd\n", + "12 is even\n", + "13 is odd\n", + "14 is even\n", + "15 is odd\n", + "16 is even\n", + "17 is odd\n", + "18 is even\n", + "19 is odd\n", + "20 is even\n", + "21 is odd\n", + "22 is even\n", + "23 is odd\n", + "24 is even\n", + "25 is odd\n", + "26 is even\n", + "27 is odd\n", + "28 is even\n", + "29 is odd\n", + "30 is even\n", + "31 is odd\n", + "32 is even\n", + "33 is odd\n", + "34 is even\n", + "35 is odd\n", + "36 is even\n", + "37 is odd\n", + "38 is even\n", + "39 is odd\n" + ] + } + ], "source": [ - "# Display all numbers from 1 to 500." + "# Display all numbers from 1 to 500.\n", + "\n", + "for i in range(1, 40):\n", + " if i%2 == 0:\n", + " print(str(i) + ' is even')\n", + " elif i%2 == 1:\n", + " print(str(i) + ' is odd') \n" ] }, { @@ -146,15 +378,135 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "id": "620b3886", "metadata": { "lines_to_next_cell": 0, "title": "[python]" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "7\n", + "14\n", + "21\n", + "28\n", + "35\n", + "42\n", + "49\n", + "56\n", + "63\n", + "70\n", + "77\n", + "84\n", + "91\n", + "98\n", + "105\n", + "112\n", + "119\n", + "126\n", + "133\n", + "140\n", + "147\n", + "154\n", + "161\n", + "168\n", + "175\n", + "182\n", + "189\n", + "196\n", + "203\n", + "210\n", + "217\n", + "224\n", + "231\n", + "238\n", + "245\n", + "252\n", + "259\n", + "266\n", + "273\n", + "280\n", + "287\n", + "294\n", + "301\n", + "308\n", + "315\n", + "322\n", + "329\n", + "336\n", + "343\n", + "350\n", + "357\n", + "364\n", + "371\n", + "378\n", + "385\n", + "392\n", + "399\n", + "406\n", + "413\n", + "420\n", + "427\n", + "434\n", + "441\n", + "448\n", + "455\n", + "462\n", + "469\n", + "476\n", + "483\n", + "490\n", + "497\n", + "504\n", + "511\n", + "518\n", + "525\n", + "532\n", + "539\n", + "546\n", + "553\n", + "560\n", + "567\n", + "574\n", + "581\n", + "588\n", + "595\n", + "602\n", + "609\n", + "616\n", + "623\n", + "630\n", + "637\n", + "644\n", + "651\n", + "658\n", + "665\n", + "672\n", + "679\n", + "686\n", + "693\n", + "700\n", + "707\n", + "714\n", + "721\n", + "728\n", + "735\n", + "742\n", + "749\n", + "756\n", + "763\n", + "770\n" + ] + } + ], "source": [ - "# Display all multiples of 7 from 0 to 777" + "# Display all multiples of 7 from 0 to 777\n", + "for i in range(0, 777, 7):\n", + " print (i)" ] }, { @@ -169,15 +521,95 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "6db862fd", "metadata": { "lines_to_next_cell": 0, "title": "[python]" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "in\n", + "2012\n", + "i was\n", + "0\n", + "years old\n", + "in\n", + "2013\n", + "i was\n", + "1\n", + "years old\n", + "in\n", + "2014\n", + "i was\n", + "2\n", + "years old\n", + "in\n", + "2015\n", + "i was\n", + "3\n", + "years old\n", + "in\n", + "2016\n", + "i was\n", + "4\n", + "years old\n", + "in\n", + "2017\n", + "i was\n", + "5\n", + "years old\n", + "in\n", + "2018\n", + "i was\n", + "6\n", + "years old\n", + "in\n", + "2019\n", + "i was\n", + "7\n", + "years old\n", + "in\n", + "2020\n", + "i was\n", + "8\n", + "years old\n", + "in\n", + "2021\n", + "i was\n", + "9\n", + "years old\n", + "in\n", + "2022\n", + "i was\n", + "10\n", + "years old\n", + "in\n", + "2023\n", + "i was\n", + "11\n", + "years old\n", + "in\n", + "2024\n", + "i was\n", + "12\n", + "years old\n" + ] + } + ], "source": [ - "# Your Code Here" + "# Your Code Here\n", + "\n", + "for i in range(13):\n", + " year = 2012+i\n", + " print ('in')\n", + " print(year)\n", + " print( 'i was')\n", + " print (i)\n", + " print('years old')" ] }, { @@ -234,15 +666,38 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "id": "8c847ed3", "metadata": { "lines_to_next_cell": 0, "title": "[python]" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0,0) \n", + "(0,1) \n", + "(0,2) \n", + "\n", + "(1,0) \n", + "(1,1) \n", + "(1,2) \n", + "\n", + "(2,0) \n", + "(2,1) \n", + "(2,2) \n", + "\n" + ] + } + ], "source": [ - "# Display the output shown above" + "# Display the output shown above\n", + "for i in range(3):\n", + " for j in range(3):\n", + " print(f\"({i},{j})\", end= ' \\n')\n", + " print()" ] }, { @@ -263,15 +718,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 47, "id": "bb0a4a5b", "metadata": { "lines_to_next_cell": 0, "title": "[python]" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1) (2) (3) \n", + "(4) (5) (6) \n", + "(7) (8) (9) \n" + ] + } + ], "source": [ - "# Display the numbers 1 through 9 in a 3x3 square grid" + "# Display the numbers 1 through 9 in a 3x3 square grid\n", + "for i in range(3):\n", + " for j in range(3):\n", + " print(f\"({3*i+j+1})\", end= ' ')\n", + " print()" ] }, { @@ -286,15 +755,36 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 48, "id": "ced82638", "metadata": { "lines_to_next_cell": 0, "title": "[python]" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) \n", + "(11) (12) (13) (14) (15) (16) (17) (18) (19) (20) \n", + "(21) (22) (23) (24) (25) (26) (27) (28) (29) (30) \n", + "(31) (32) (33) (34) (35) (36) (37) (38) (39) (40) \n", + "(41) (42) (43) (44) (45) (46) (47) (48) (49) (50) \n", + "(51) (52) (53) (54) (55) (56) (57) (58) (59) (60) \n", + "(61) (62) (63) (64) (65) (66) (67) (68) (69) (70) \n", + "(71) (72) (73) (74) (75) (76) (77) (78) (79) (80) \n", + "(81) (82) (83) (84) (85) (86) (87) (88) (89) (90) \n", + "(91) (92) (93) (94) (95) (96) (97) (98) (99) (100) \n" + ] + } + ], "source": [ - "# Display the numbers 1 through 100 in a 10x10 square grid. " + "# Display the numbers 1 through 100 in a 10x10 square grid. \n", + "for i in range(10):\n", + " for j in range(10):\n", + " print(f\"({10*i+j+1})\", end= ' ')\n", + " print()" ] }, { @@ -318,12 +808,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 63, "id": "3b81fd1e", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0) (0) (0) (0) (0) (0) \n", + "(1) (1) (1) (1) (1) (1) \n", + "(2) (2) (2) (2) (2) (2) \n", + "(3) (3) (3) (3) (3) (3) \n", + "(4) (4) (4) (4) (4) (4) \n", + "(5) (5) (5) (5) (5) (5) \n" + ] + } + ], "source": [ - "# Display the asterisk pattern shown above" + "# Display the asterisk pattern shown above\n", + "for i in range(6):\n", + " for j in range(6):\n", + " print(f\"({i})\", end= ' ')\n", + " print()" ] }, { @@ -340,7 +847,7 @@ "notebook_metadata_filter": "-all" }, "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -354,7 +861,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.9" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/lessons/02_Loops/09_FizzBuzz_Gui_Grid.py b/lessons/02_Loops/09_FizzBuzz_Gui_Grid.py index 06460da0..32bbbe2d 100644 --- a/lessons/02_Loops/09_FizzBuzz_Gui_Grid.py +++ b/lessons/02_Loops/09_FizzBuzz_Gui_Grid.py @@ -33,6 +33,22 @@ # Create a 10x10 grid using nested loops # Or you can use a single loop and calculate the row and column +for i in range(10): + for j in range(10): + num = 10*i+j+1 + print(f"({num})", end= ' ') + if num % 2 == 0: + Text(app, text=str(num), grid=[i, j], color='blue') + else: + Text(app, text=str(num), grid=[i, j], color='red') + if num % 5 == 0: + Text(app, text='🦡', grid=[i, j]) + if num % 3 == 0: + Text(app, text='🍄', grid=[i, j]) + if num % 15 == 0: + Text(app, text='🐍', grid=[i, j]) + + # In the loop, calculate or increment the number diff --git a/lessons/02_Loops/10_More_Iterables.ipynb b/lessons/02_Loops/10_More_Iterables.ipynb index 9423895f..6a3ee754 100644 --- a/lessons/02_Loops/10_More_Iterables.ipynb +++ b/lessons/02_Loops/10_More_Iterables.ipynb @@ -19,9 +19,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, 'red')\n", + "(1, 'blue')\n", + "(2, 'black')\n", + "(3, 'orange')\n" + ] + } + ], "source": [ "# Enumerate\n", "\n", @@ -42,9 +53,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1, 2, 3)\n", + "1 2 3\n" + ] + } + ], "source": [ "t = (1,2,3)\n", "a,b,c = t\n", @@ -71,6 +91,24 @@ "execution_count": null, "metadata": {}, "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# 0 color is red\n", + "# 1 color is blue\n", + "# 2 color is black\n", + "# 3 color is orange\n" + ] + } + ], "source": [ "# Enumerate with Unpacking\n", "\n", @@ -174,9 +212,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a 1\n", + "b 2\n", + "c 3\n", + "d 4\n" + ] + } + ], "source": [ "# Zip \n", "\n", @@ -196,9 +245,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Move 10 units in direction 0 degrees and color red\n", + "Move 20 units in direction 90 degrees and color blue\n", + "Move 40 units in direction 0 degrees and color black\n", + "Move 10 units in direction 270 degrees and color orange\n" + ] + } + ], "source": [ "# Use zip to iterate over two lists at once\n", "\n", @@ -236,9 +296,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[999995, 999996, 999997, 999998, 999999]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from itertools import islice # Important! \n", "\n", @@ -254,9 +325,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n", + "4\n" + ] + } + ], "source": [ "# Demonstrate islice\n", "\n", @@ -299,6 +382,21 @@ "execution_count": null, "metadata": {}, "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "red blue black orange red blue " + ] + } + ], "source": [ "# Use cycle and islice\n", "\n", @@ -306,7 +404,7 @@ "\n", "colors = [ 'red', 'blue', 'black', 'orange']\n", "\n", - "for color in islice(cycle(colors), 25):\n", + "for color in islice(cycle(colors), 6):\n", " print(color, end=' ')\n" ] }, @@ -325,7 +423,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -339,7 +437,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.0" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/lessons/02_Loops/11_Iterable_Turtle.ipynb b/lessons/02_Loops/11_Iterable_Turtle.ipynb index 3bf9413b..6aadbf3c 100644 --- a/lessons/02_Loops/11_Iterable_Turtle.ipynb +++ b/lessons/02_Loops/11_Iterable_Turtle.ipynb @@ -12,32 +12,59 @@ "Use what you've learned about lists, loop, cycle, slice and zip to draw a pattern\n", "\n", "\"\"\"\n", + "import turtle \n", + "turtle.setup (width=600, height=600)\n", "\n", - "t = ... # Create a turtle like in previous programs, like 04_Crazy_Tina.py\n", + "t = turtle.Turtle() # Create a turtle like in previous programs, like 04_Crazy_Tina.py\n", "\n", - "colors = ... # Make a list of colors\n", + "colors = 'red', 'blue', 'green', 'purple', 'pink' # Make a list of colors\n", "\n", "directions = [ # Create a list of directions and angles\n", - " ( , ),\n", - " ( , ), ... # Add more\n", + " ( 45, 10 ),\n", + " ( 5, 40 ), \n", + " ( 10, 60 ),\n", + " ( 65, 35 ),\n", + " ( 25, 5 )\n", "]\n", "\n", "# Zip the colors and directions together, then unpack them. THere is a good example of this\n", "# in 10_More_iterables.ipynb in the discussion of zip()\n", "\n", - "for ... in zip( ... , ...):\n", - " t.color( ... )\n", - " t.forward( ... )\n", - " t.left( ... )\n", + "for c, d in zip( colors , directions):\n", + " t.color( c )\n", + " t.forward( d[1] )\n", + " t.left( d[0] )\n", "\n", "\n", - "# Don't forget the special way to end a turtle program. \n" + "# Don't forget the special way to end a turtle program. \n", + "turtle.exitonclick()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" } }, "nbformat": 4, diff --git a/lessons/02_Loops/12_More_Loops.ipynb b/lessons/02_Loops/12_More_Loops.ipynb index ff74b609..1864cbe8 100644 --- a/lessons/02_Loops/12_More_Loops.ipynb +++ b/lessons/02_Loops/12_More_Loops.ipynb @@ -220,7 +220,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -234,7 +234,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.9" + "version": "3.12.11" } }, "nbformat": 4, diff --git a/lessons/02_Loops/13_Number_Guess.py b/lessons/02_Loops/13_Number_Guess.py index 6665813a..bb59b9e4 100644 --- a/lessons/02_Loops/13_Number_Guess.py +++ b/lessons/02_Loops/13_Number_Guess.py @@ -31,6 +31,7 @@ """ import random +from tkinter import messagebox, simpledialog def ask_integer(prompt): """Function to ask the user for an integer""" @@ -42,15 +43,28 @@ def ask_integer(prompt): # Pick the random number - +n = random.randint(1, 100) # In your loop: - +i = 0 +while True: # Get the user's guess - + guess = simpledialog.askinteger("guess", "Guess the number between 1-100") # If the user's guess is divisible by 7, tell the user to start over + if guess%7 == 0: + messagebox.showinfo('ERROR', "BAD NUMBER, PLEASE START OVER") + n = random.randint(1, 100) # If the user's guess is too high, tell the user + elif guess > n: + messagebox.showinfo('INCORRECT', "TOO HIGH") # If the user's guess is too low, tell the user + elif guess < n: + messagebox.showinfo('INCORRECT', "TOO LOW") # If the user's guess is correct, tell the user and break out of the loop + elif guess == n: + messagebox.showinfo('CORRECT', "YOU GOT IT!!!") + break + + diff --git a/lessons/02_Loops/99_Extras.ipynb b/lessons/02_Loops/99_Extras.ipynb index 63b8f26d..3527f195 100644 --- a/lessons/02_Loops/99_Extras.ipynb +++ b/lessons/02_Loops/99_Extras.ipynb @@ -67,7 +67,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -81,7 +81,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.0" + "version": "3.12.11" } }, "nbformat": 4, diff --git a/lessons/03_Data_Structures_Func/01_Functions.ipynb b/lessons/03_Data_Structures_Func/01_Functions.ipynb index 0cfdc868..6bc1e3fa 100644 --- a/lessons/03_Data_Structures_Func/01_Functions.ipynb +++ b/lessons/03_Data_Structures_Func/01_Functions.ipynb @@ -93,7 +93,7 @@ "# Call function with \"positional\" arguments. He first argument\n", "# is assigned `name`, the second is assigned `greeting`.\n", "\n", - "greet_user(\"Alice\", \"Bounjour\")\n", + "greet_user(\"Alice\", \"Bonjour\")\n", "\n", "# We can also call the function with \"keyword\" arguments. This\n", "# allows us to specify the arguments in any order.\n", @@ -206,11 +206,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# Test yourself\n", + "def find_char(char, string):\n", + " for i in range (len(string)):\n", + " if char == string[i]:\n", + " return i\n", + " else:\n", + " return -1\n", "\n", "# Write your own find_char function that takes a character and a string\n", "\n", @@ -258,24 +264,35 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "# Test Yourself\n", "\n", "# Write a function to add two numbers and return the result\n", + "def add(i, j):\n", + " return i+j\n", "\n", "# Write a function to subtract two numbers and return the result \n", - "\n", + "def subtract(i, j):\n", + " return i-j\n", "# Write a function to print \"Same\" if two numbers are the same, otherwise print \"Different\"\n", - "\n", + "def same_or_diff(i, j):\n", + " if i == j : \n", + " return(f\"{'same'}\")\n", + " elif i != j:\n", + " return(f\"{'different'}\")\n", "# Use your functions to show that 2 + 2 = 4\n", - "\n", + "assert add(2, 2) ==4\n", "# Use your functions to show that ( 5 + 3) - 2 = 6\n", + "assert add(5, 3) ==8\n", + "assert subtract (8, 2) == 6\n", "\n", "# Use your functions to show that 2 + 2 != 3 + 3 = 6\n", - "\n" + "assert add(2,2) == 4\n", + "assert add(3,3) == 6\n", + "assert same_or_diff(4,6) == 'different'\n" ] }, { @@ -291,9 +308,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, Bob\n" + ] + } + ], "source": [ "name = 'Bob'\n", "\n", @@ -333,9 +358,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "ValueError", + "evalue": "invalid literal for int() with base 10: 'This is not an integer'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mValueError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[17]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mThis is not an integer\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[31mValueError\u001b[39m: invalid literal for int() with base 10: 'This is not an integer'" + ] + } + ], "source": [ "int(\"This is not an integer\")" ] @@ -349,9 +386,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Converting 0 to an integer 0\n", + "Converting 1 to an integer 1\n", + "Converting 65 to an integer 65\n" + ] + }, + { + "ename": "ValueError", + "evalue": "invalid literal for int() with base 10: 'Bob'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mValueError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[18]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m e \u001b[38;5;129;01min\u001b[39;00m [\u001b[32m0\u001b[39m,\u001b[32m1\u001b[39m, \u001b[32m65\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mBob\u001b[39m\u001b[33m'\u001b[39m, \u001b[32m23\u001b[39m,\u001b[33m'\u001b[39m\u001b[33mlarry\u001b[39m\u001b[33m'\u001b[39m]:\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m i = \u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43me\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 3\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mConverting \u001b[39m\u001b[38;5;132;01m{\u001b[39;00me\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m to an integer \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mi\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m\"\u001b[39m)\n", + "\u001b[31mValueError\u001b[39m: invalid literal for int() with base 10: 'Bob'" + ] + } + ], "source": [ "for e in [0,1, 65, 'Bob', 23,'larry']:\n", " i = int(e)\n", @@ -369,7 +427,20 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Converting 0 to an integer 0\n", + "Converting 1 to an integer 1\n", + "Converting 65 to an integer 65\n", + "Could not convert Bob to an integer\n", + "Converting 23 to an integer 23\n", + "Could not convert larry to an integer\n" + ] + } + ], "source": [ "for e in [0,1, 65, 'Bob', 23,'larry']:\n", "\n", @@ -396,7 +467,19 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "TypeError", + "evalue": "list indices must be integers or slices, not str", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mTypeError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[1]\u001b[39m\u001b[32m, line 7\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;66;03m# Run me! Uncomment one of the code lines to see the error it produces\u001b[39;00m\n\u001b[32m 2\u001b[39m \u001b[38;5;66;03m# Put the comment back to see another error\u001b[39;00m\n\u001b[32m 3\u001b[39m \u001b[38;5;66;03m# Index a list with a string\u001b[39;00m\n\u001b[32m 5\u001b[39m my_list = [\u001b[32m1\u001b[39m,\u001b[32m2\u001b[39m,\u001b[32m3\u001b[39m,\u001b[32m4\u001b[39m,\u001b[32m5\u001b[39m]\n\u001b[32m----> \u001b[39m\u001b[32m7\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[43mmy_list\u001b[49m\u001b[43m[\u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43mBob\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m]\u001b[49m) \u001b[38;5;66;03m# TypeError: list indices must be integers or slices, not str\u001b[39;00m\n\u001b[32m 9\u001b[39m \u001b[38;5;66;03m#print(my_list[20]) # IndexError: list index out of range\u001b[39;00m\n\u001b[32m 10\u001b[39m \n\u001b[32m 11\u001b[39m \u001b[38;5;66;03m#assert False # AssertionError ( Although you don't usually catch assertions ) \u001b[39;00m\n\u001b[32m 12\u001b[39m \n\u001b[32m 13\u001b[39m \u001b[38;5;66;03m#x = 10 / 0 # ZeroDivisionError: division by zero\u001b[39;00m\n", + "\u001b[31mTypeError\u001b[39m: list indices must be integers or slices, not str" + ] + } + ], "source": [ "# Run me! Uncomment one of the code lines to see the error it produces\n", "# Put the comment back to see another error\n", @@ -408,9 +491,9 @@ "\n", "#print(my_list[20]) # IndexError: list index out of range\n", "\n", - "# assert False # AssertionError ( Although you don't usually catch assertions ) \n", + "#assert False # AssertionError ( Although you don't usually catch assertions ) \n", "\n", - "# x = 10 / 0 # ZeroDivisionError: division by zero\n", + "#x = 10 / 0 # ZeroDivisionError: division by zero\n", "\n" ] }, @@ -482,25 +565,63 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Got an exception list index out of range\n", + "2 is not in the list, but the 2th number is 45\n", + "found it\n", + "found it\n", + "2 is not in the list, but the 2th number is 45\n" + ] + }, + { + "ename": "TypeError", + "evalue": "int() argument must be a string, a bytes-like object or a real number, not 'NoneType'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mTypeError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[26]\u001b[39m\u001b[32m, line 19\u001b[39m\n\u001b[32m 16\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m strnum == \u001b[33m'\u001b[39m\u001b[33mq\u001b[39m\u001b[33m'\u001b[39m:\n\u001b[32m 17\u001b[39m \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m19\u001b[39m num = \u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mstrnum\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 20\u001b[39m \u001b[38;5;66;03m# If the user's number is in the list, print \"Found it!\" and contine the loop\u001b[39;00m\n\u001b[32m 21\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m num \u001b[38;5;129;01min\u001b[39;00m l:\n", + "\u001b[31mTypeError\u001b[39m: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'" + ] + } + ], "source": [ "# Test Yourself\n", "\n", "# Check if the user's numbers are in this list:\n", "\n", + "from tkinter import messagebox, simpledialog\n", + "\n", + "\n", "l = [5,10,45, 56]\n", "\n", "# Forever loop until the user enters a number in the list\n", + "while True:\n", "\n", " # Get a number from the user. \n", - "\n", + " strnum = simpledialog.askstring(\"Integer\", \"Gimme another number\") \n", " # If the user enteres 'q', exit the loop\n", + " if strnum == 'q':\n", + " break\n", "\n", + " num = int(strnum)\n", " # If the user's number is in the list, print \"Found it!\" and contine the loop\n", - "\n", - " # If the user's number is not in the list, find the n'th number in the list. Print it and continue the loop\n" + " if num in l:\n", + " print('found it')\n", + " # If the user's number is not in the list, find the n'th number in the list. Print it and continue the loop\n", + " else:\n", + " try:\n", + " print(strnum + ' is not in the list, but the ' + strnum + 'th number is ' + str(l[num]))\n", + " except Exception as e:\n", + " # Get all types of exceptions. \n", + " print(f\"Got an exception {e}\")\n", + " \n" ] }, { @@ -513,7 +634,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -527,7 +648,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.9" + "version": "3.12.11" } }, "nbformat": 4, diff --git a/lessons/03_Data_Structures_Func/02_Dicts_Sets.ipynb b/lessons/03_Data_Structures_Func/02_Dicts_Sets.ipynb index 63ec7f11..a11e6951 100644 --- a/lessons/03_Data_Structures_Func/02_Dicts_Sets.ipynb +++ b/lessons/03_Data_Structures_Func/02_Dicts_Sets.ipynb @@ -26,9 +26,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['a', 'a', 'b', 'b', 'c', 'c']\n", + "{'b', 'a', 'c'}\n" + ] + } + ], "source": [ "l = ['a','a','b','b','c','c']\n", "print(l)\n", @@ -78,9 +87,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('a', 'a', 'b', 'b', 'c', 'c')\n", + "{'b', 'a', 'c'}\n", + "['H', 'e', 'l', 'l', 'o']\n", + "['b', 'a', 'c']\n" + ] + } + ], "source": [ "c = \"Hello\"\n", "l = ['a','a','b','b','c','c']\n", @@ -177,7 +197,17 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31mRunning cells with 'Python 3.11.2' requires the ipykernel package.\n", + "\u001b[1;31mCreate a Python Environment with the required packages." + ] + } + ], "source": [ "# Dictionary example\n", "\n", @@ -253,7 +283,17 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31mRunning cells with 'Python 3.11.2' requires the ipykernel package.\n", + "\u001b[1;31mCreate a Python Environment with the required packages." + ] + } + ], "source": [ "d = { \n", " \"one\": 1, \n", @@ -459,9 +499,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 86, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('funny', ['snollygoster', 'skedaddle'])\n", + "('funny', ['lollygag', 'collywobble'])\n", + "('not funny', [])\n", + "('funny', ['snollygoster'])\n", + "('not funny', [])\n", + "('funny', ['skedaddle', 'lollygag'])\n", + "('funny', ['skedaddle', 'collywobble'])\n", + "('not funny', [])\n" + ] + } + ], "source": [ "funny_sentences = [\n", " \"The snollygoster tried to skedaddle before anyone noticed his mischief.\",\n", @@ -473,12 +528,9 @@ " \"We decided to skedaddle from the park when we saw the kids starting to lollygag near the mud puddles.\",\n", " \"The sudden collywobbles made him want to skedaddle from the roller coaster line.\",\n", " \"The teacher was flummoxed by the students' whippersnapper antics during the lesson.\"\n", - "]\n", - "\n", - "def check_funny_words(sentence):\n", - " \"\"\"\n", + " \"\"\"\n", " Checks if any funny words are present in the given sentence.\n", - "\n", + " \n", " Args:\n", " sentence (str): The sentence to check for funny words.\n", "\n", @@ -487,6 +539,21 @@ " If no funny words are found, returns \"Not funny\".\n", " \"\"\"\n", " \n", + "\n", + "]\n", + "\n", + "def check_funny_words(sentence):\n", + " words = [\"snollygoster\", \"skedaddle\", \"lollygag\", \"collywobble\"]\n", + " l = []\n", + " str = \"not funny\"\n", + " \n", + " for word in words:\n", + " if word in s:\n", + " l.append(word)\n", + " str = \"funny\"\n", + "\n", + " return str, l \n", + " \n", " # IMPLEMENT ME!\n", "\n", "\n", @@ -564,7 +631,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -578,7 +645,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.9" + "version": "3.12.11" } }, "nbformat": 4, diff --git a/lessons/03_Data_Structures_Func/04_Funny_Words_Db.py b/lessons/03_Data_Structures_Func/04_Funny_Words_Db.py index 301dcba9..0d816174 100644 --- a/lessons/03_Data_Structures_Func/04_Funny_Words_Db.py +++ b/lessons/03_Data_Structures_Func/04_Funny_Words_Db.py @@ -1,4 +1,4 @@ -from guizero import App, Box, Text, TextBox, PushButton, ListBox, error +from guizero import App, Box, Text, TextBox, PushButton, ListBox, error """Funny Words Dictionary @@ -19,15 +19,9 @@ an error message will be displayed and new definitions will not be added. """ - - -# Implement the functions below - - -def add_definition(db, key, value): - """ +""" Add a new definition to the database. - + Parameters: - db (dict): The database to add the definition to. - key (str): The key for the new definition. @@ -39,11 +33,20 @@ def add_definition(db, key, value): If there are already 5 items in the database, an error message is displayed and the new item is not added. """ - # Check the limit +# Implement the functions below - # Set the item in the database - pass +def add_definition(db, key, value): + + + + # Check the limit + if len(db)>=5: + print("there can only be 5 definitions in the database") + else: + db[key]=value + + def delete_definition(db, key): @@ -59,7 +62,7 @@ def delete_definition(db, key): """ # Delete the item from db if it is present - + db.remove(key) pass diff --git a/lessons/03_Data_Structures_Func/05_Splat_Comprehension.ipynb b/lessons/03_Data_Structures_Func/05_Splat_Comprehension.ipynb index d66e5ffb..34848a4a 100644 --- a/lessons/03_Data_Structures_Func/05_Splat_Comprehension.ipynb +++ b/lessons/03_Data_Structures_Func/05_Splat_Comprehension.ipynb @@ -14,7 +14,18 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n", + "1\n", + "6\n", + "7\n" + ] + } + ], "source": [ "# A 2 dimensional array is an array of arrays. Here is an example:\n", "\n", @@ -68,12 +79,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[4, 5, 6]\n" + ] + } + ], "source": [ "# Try it! \n", - "# See what print( two_dimensional_array[1] ) produces\n" + "print( two_dimensional_array[1] )\n" ] }, { @@ -125,9 +144,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3]\n", + "[4, 5, 6]\n", + "[7, 8, 9]\n", + "\n", + "(1, 4, 7)\n", + "(2, 5, 8)\n", + "(3, 6, 9)\n" + ] + } + ], "source": [ "def pretty_print_2d(a):\n", " \"\" \"Prints a 2D array in a pretty way\" \"\"\n", @@ -184,9 +217,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1, 4, 7)\n", + "(2, 5, 8)\n", + "(3, 6, 9)\n" + ] + } + ], "source": [ "for e in zip([1, 2, 3],[4, 5, 6],[7, 8, 9]):\n", " print(e)" @@ -229,9 +272,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 4, 7]\n", + "[2, 5, 8]\n", + "[3, 6, 9]\n" + ] + } + ], "source": [ "# First transpose:\n", "t = zip(*board)\n", @@ -335,7 +388,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -349,12 +402,12 @@ " [7, 8, 9]\n", " ]\n", "\n", - "# Uncomment below and replace the ... with code that will produce the expected output.\n", - "#d1 = [ board[...][...] for i in range(3) ]\n", - "#assert d1 == [1, 5, 9]\n", "\n", - "#d2 = [ board[...][...] for i in range(3) ]\n", - "#assert d2 == [3, 5, 7]\n", + "d1 = [ board[0][0], board[1][1], board [2][2] ]\n", + "assert d1 == [1, 5, 9]\n", + "\n", + "d2 = [ board[0][2], board[1][1], board[2][0] ]\n", + "assert d2 == [3, 5, 7]\n", "\n" ] }, @@ -387,7 +440,37 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "1 ===\n", + "True\n", + "False\n", + "False\n", + "\n", + "2 ===\n", + "{'x'}\n", + "{'o'}\n", + "{'o', 'x'}\n", + "{'o', 'x'}\n", + "\n", + "3 ===\n", + "1\n", + "1\n", + "2\n", + "2\n", + "\n", + "4 ===\n", + "True\n", + "True\n", + "False\n", + "False\n" + ] + } + ], "source": [ "x_won = ['x','x','x']\n", "o_won = ['o','o','o']\n", @@ -436,9 +519,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "'x'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "x_wins_boards = [\n", " # x wins in row 1\n", @@ -511,12 +605,9 @@ "def check_row(l):\n", " \"\"\"Check if a player won on a row\n", " Args:\n", - " l: a 3 element iterable\n", - " \n", - " Returns:\n", - " The winner's token ( x or o ) if there is one, otherwise None\n", - " \"\"\"\n", - " \n", + " l: a 3 element iterable\"\"\"\n", + " if all(e == l[0] and e != \"\" for e in l):\n", + " return l[0]\n", " return None\n", "\n", "\n", @@ -526,21 +617,41 @@ "def check_board(board):\n", " \"\"\"Check if a player has won on a board\n", " Args:\n", - " board: a 3x3 2D array\n", - " \n", - " Returns:\n", - " The winner's token ( x or o ) if there is one, otherwise None\n", - " \"\"\"\n", + " board: a 3x3 2D array \"\"\"\n", + "\n", + " for row in board:\n", + " winner = check_row(row)\n", + " if winner:\n", + " return winner\n", + "\n", + " for col in zip(*board):\n", + " winner = check_row(col)\n", + " if winner:\n", + " return winner\n", + "\n", + " winner = check_row([board[i][i] for i in range(3)])\n", + " if winner:\n", + " return winner\n", + "\n", + " winner = check_row([board[i][2 - i] for i in range(3)])\n", + " if winner:\n", + " return winner\n", "\n", " return None\n", "\n", "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "\n", "# Next, write some test code to test your functions. You should start by testing rows, like this\n", "# \n", "\n", - "# board = x_wins_boards[0]\n", - "# check_row( board[0]) # Should be None\n", - "# check_row( board[1]) # Should be 'x'\n", + "board = x_wins_boards[0]\n", + "check_row( board[0]) # Should be None\n", + "check_row( board[1]) # Should be 'x'\n", "#\n", "# Test the rows to determine if your check_rows() function works. \n", "# \n", @@ -554,9 +665,61 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Bad pipe message: %s [b' q=0.9, image/avif, image/webp, image/apng, */*; q=0.8, application/signed-exchange; v=b3; q=0.7\\r\\nHost: loc', b'host:40605\\r\\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTM']\n", + "Bad pipe message: %s [b' like Gecko) Chrome/145.0.0.0 Safari/537.36\\r\\nAccept-Encoding: gzip, deflate']\n", + "Bad pipe message: %s [b'br, zstd\\r\\nAccept-Language: en-US, en; q=0.9']\n", + "Bad pipe message: %s [b'Cache-Contro']\n", + "Bad pipe message: %s [b' max-age=0\\r\\nReferer: https://organic-space-bassoon-x7x77g4wqrgcpvxg.github.dev/\\r\\nX-Request-ID: 4efdb2fe4203']\n", + "Bad pipe message: %s [b'c78f67d2ea0c6d1634\\r\\nX-Real-IP: 10.241.0.36\\r\\nX-Forwarded', b'ort: 443\\r\\nX-Forwarded-Scheme: https\\r\\nX-Origi']\n", + "Bad pipe message: %s [b'l-URI: /\\r\\nX-Scheme: https\\r\\nsec-fetch-site: same-site\\r\\nsec-fetch-mode: navigate\\r\\nsec-fetch-dest: document\\r\\nsec', b'h-ua: \"Not:A-Brand\";v=\"99\", \"Google Chrome\";', b'\"145\", \"Chromium\";v=\"145\"\\r\\nsec-ch-ua-mobile: ?0\\r\\nsec-ch-ua-platform: \"macOS\"\\r\\npriority: u=0, i\\r\\nX-Forwarded-Proto: ht', b's\\r\\nX-Forwarded-Host: organic-space-bassoon-x7x77g4wqrgcpvxg-40605.app.github.dev\\r\\nX-Forwarded-For: 107.143.96.19\\r\\nP']\n", + "Bad pipe message: %s [b'8822 HTTP/1.1\\r\\nAccept: text/html, application/x', b'ml+xml, application/xml; q=0.9, image/avif, image/webp, image/apng, */*; q=0.8, application/signed-exch']\n", + "Bad pipe message: %s [b'ge; v=b3; q=0.7\\r\\nHost: localhost:40605\\r\\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15']\n", + "Bad pipe message: %s [b') AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36\\r\\nAccept-Encoding: gzip', b'deflate, br, zstd\\r\\nAccept-Language: en-US, ']\n", + "Bad pipe message: %s [b'; q=0.9\\r\\nReferer: https://1i1cej3dv6d6jor4kujopa2jmte4s66nhnv1smj2ojsiho1666o4.assets.github.dev/\\r\\nX']\n", + "Bad pipe message: %s [b'equest-ID: a24c6cde3798e21fcae583461b19cbf7\\r']\n", + "Bad pipe message: %s [b'-Real-IP:']\n", + "Bad pipe message: %s [b'0.241.0.36\\r\\nX-Forwarded-Port: 4', b'\\r\\nX-Forwarded-Scheme: https\\r\\nX-Original-URI: /?id=4', b'f3e1b-c0d6-4e82-a821-5a355d5b2da4&vscodeBrowserReqId=1775517018822\\r\\nX-Scheme: https\\r\\nsec-ch-ua: \"No', b'A-Brand\";v=\"99\", \"Google Chrome\";v=\"145\", \"Chromium\";v=\"145\"\\r\\nsec-ch-ua-mobile: ?0\\r\\nsec-ch-ua-platform: \"macOS\"\\r\\nse']\n", + "Bad pipe message: %s [b'fetch-site: same-site\\r\\nsec-fetch-mode: navigate\\r\\nsec-fetch-dest: iframe\\r\\npriority: u=0, i\\r\\nX-Forwa', b'ed-Proto: https\\r\\nX-Forwarded-Host: organic-space-bassoon-x7x77g4wqrgcpvxg-40605.app.github.dev\\r\\nX-Forwarded-For: ']\n", + "Bad pipe message: %s [b' q=0.9, image/avif, image/webp, image/apng, */*; q=0.8, application/signed-exchange; v=b3; q=0.7\\r\\nHost: loc', b'host:40605\\r\\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTM']\n", + "Bad pipe message: %s [b' like Gecko) Chrome/145.0.0.0 Safari/537.36\\r\\nAccept-Encoding: gzip, deflate']\n", + "Bad pipe message: %s [b'br, zstd\\r\\nAccept-Language: en-US, en; q=0.9']\n", + "Bad pipe message: %s [b'Referer: htt']\n", + "Bad pipe message: %s [b'://organic-space-bassoon-x7x77g4wqrgcpvxg.github.dev/\\r\\nX-Request-ID: 44c2559b091e056d69c3fdbf5cc33a34\\r\\nX-Real-I', b' 10.241.0.36\\r\\nX-Forwarded-Port: 443\\r\\nX-Forwarded-Scheme: https\\r\\nX-Original-URI:']\n", + "Bad pipe message: %s [b'\\r\\nX-Scheme: https\\r\\nsec-ch-ua: \"', b't:A-Brand\";v=\"99\", \"Google Chrome\";v=\"145\", \"Chromium\";v=\"145\"\\r\\nsec-ch-ua-mob', b'e: ?0\\r\\nsec-ch-ua-platform: \"macOS\"\\r\\nsec-fetch-site: same-site\\r\\nsec-fetch-mode: navigate\\r\\nsec-fetch-user:']\n", + "Bad pipe message: %s [b'8152 HTTP/1.1\\r\\nAccept: text/html, application/x']\n", + "Bad pipe message: %s [b'ml+xml, application/xml; q=0.9, image/avif, image/webp, image/apng, */*; q=0.8, application/signed-exch']\n", + "Bad pipe message: %s [b'ge; v=b3; q=0.7\\r\\nHost: localhost:40605\\r\\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15']\n", + "Bad pipe message: %s [b') AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36\\r\\nAccept-Encoding: gzip', b'deflate, br, zstd\\r\\nAccept-Language: en-US, ']\n", + "Bad pipe message: %s [b'; q=0.9\\r\\nReferer: https://1i1cej3dv6d6jor4kujopa2jmte4s66nhnv1smj2ojsiho1666o4.assets.github.dev/\\r\\nX']\n", + "Bad pipe message: %s [b'equest-ID: 94a77a233488834ec71434db41c0cca6\\r']\n", + "Bad pipe message: %s [b'-Real-IP:']\n", + "Bad pipe message: %s [b'0.241.0.36\\r\\nX-Forwarded-Port: 4', b'\\r\\nX-Forwarded-Scheme: https\\r\\nX-Original-URI: /?id=4', b'f3e1b-c0d6-4e82-a821-5a355d5b2da4&vscodeBrowserReqId=1775517028152\\r\\nX-Scheme: https\\r\\nsec-ch-ua: \"No', b'A-Brand\";v=\"99\", \"Google Chrome\";v=\"145\", \"Chromium\";v=\"145\"\\r\\nsec-ch-ua-mobile: ?0\\r\\nsec-ch-ua-platform: \"macOS\"\\r\\nse']\n", + "Bad pipe message: %s [b'fetch-site: same-site\\r\\nsec-fetch-mode: navigate\\r\\nsec-fetch-dest: iframe\\r\\npriority: u=0, i\\r\\nX-Forwa', b'ed-Proto: https\\r\\nX-Forwarded-Host: organic-space-bassoon-x7x77g4wqrgcpvxg-40605.app.github.dev\\r\\nX-Forwarded-For: ']\n", + "Bad pipe message: %s [b'8885 HTTP/1.1\\r\\nAccept: text/html, application/x']\n", + "Bad pipe message: %s [b'ml+xml, application/xml; q=0.9, image/avif, image/webp, image/apng, */*; q=0.8, application/signed-exch']\n", + "Bad pipe message: %s [b'ge; v=b3; q=0.7\\r\\nHost: localhost:40605\\r\\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15']\n", + "Bad pipe message: %s [b') AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36\\r\\nAccept-Encoding: gzip', b'deflate, br, zstd\\r\\nAccept-Language: en-US, ']\n", + "Bad pipe message: %s [b'; q=0.9\\r\\nReferer: https://1i1cej3dv6d6jor4kujopa2jmte4s66nhnv1smj2ojsiho1666o4.assets.github.dev/\\r\\nX']\n", + "Bad pipe message: %s [b'equest-ID: 4f5e4129621fcfa4f0b8309c8de91135\\r']\n", + "Bad pipe message: %s [b'-Real-IP:']\n", + "Bad pipe message: %s [b'0.241.0.36\\r\\nX-Forwarded-Port: 4', b'\\r\\nX-Forwarded-Scheme: https\\r\\nX-Original-URI: /?id=4', b'f3e1b-c0d6-4e82-a821-5a355d5b2da4&vscodeBrowserReqId=1775517028885\\r\\nX-Scheme: https\\r\\nsec-ch-ua: \"No', b'A-Brand\";v=\"99\", \"Google Chrome\";v=\"145\", \"Chromium\";v=\"145\"\\r\\nsec-ch-ua-mobile: ?0\\r\\nsec-ch-ua-platform: \"macOS\"\\r\\nse']\n", + "Bad pipe message: %s [b'fetch-site: same-site\\r\\nsec-fetch-mode: navigate\\r\\nsec-fetch-dest: iframe\\r\\npriority: u=0, i\\r\\nX-Forwa', b'ed-Proto: https\\r\\nX-Forwarded-Host: organic-space-bassoon-x7x77g4wqrgcpvxg-40605.app.github.dev\\r\\nX-Forwarded-For: ']\n", + "Bad pipe message: %s [b' q=0.9, image/avif, image/webp, image/apng, */*; q=0.8, application/signed-exchange; v=b3; q=0.7\\r\\nHost: loc', b'host:40605\\r\\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTM']\n", + "Bad pipe message: %s [b' like Gecko) Chrome/145.0.0.0 Safari/537.36\\r\\nAccept-Encoding: gzip, deflate']\n", + "Bad pipe message: %s [b'br, zstd\\r\\nAccept-Language: en-US, en; q=0.9']\n", + "Bad pipe message: %s [b'Referer: htt']\n", + "Bad pipe message: %s [b'://organic-space-bassoon-x7x77g4wqrgcpvxg.github.dev/\\r\\nX-Request-ID: 22ade41511f18db1919f3f39d12a3103\\r\\nX-Real-I', b' 10.241.0.36\\r\\nX-Forwarded-Port: 443\\r\\nX-Forwarded-Scheme: https\\r\\nX-Original-URI:']\n", + "Bad pipe message: %s [b'\\r\\nX-Scheme: https\\r\\nsec-ch-ua: \"', b't:A-Brand\";v=\"99\", \"Google Chrome\";v=\"145\", \"Chromium\";v=\"145\"\\r\\nsec-ch-ua-mob', b'e: ?0\\r\\nsec-ch-ua-platform: \"macOS\"\\r\\nsec-fetch-site: same-site\\r\\nsec-fetch-mode: navigate\\r\\nsec-fetch-user:']\n" + ] + } + ], "source": [ "# Final Test\n", "# If all of your functions are working this code should pass:\n", @@ -566,6 +729,18 @@ "assert all([ check_board(board) is None for board in no_winner_boards ] )" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, { "cell_type": "markdown", "metadata": {}, @@ -577,9 +752,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3]\n", + "[4, 5, 6]\n", + "[7, 8, 9]\n", + "(1, 4, 7)\n", + "(2, 5, 8)\n", + "(3, 6, 9)\n" + ] + } + ], "source": [ "l = [\n", " [1, 2, 3],\n", @@ -607,7 +795,7 @@ ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -621,7 +809,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.9" + "version": "3.12.12" } }, "nbformat": 4, diff --git a/lessons/03_Data_Structures_Func/06_Tic_Tac_Toe.py b/lessons/03_Data_Structures_Func/06_Tic_Tac_Toe.py index 9c90264b..f41360b1 100644 --- a/lessons/03_Data_Structures_Func/06_Tic_Tac_Toe.py +++ b/lessons/03_Data_Structures_Func/06_Tic_Tac_Toe.py @@ -1,5 +1,6 @@ #imports -from guizero import App, Box, PushButton, Text, info +import pygame +import sys X_MARK = "X" O_MARK = "O" @@ -15,9 +16,11 @@ def check_row(l): Returns: The winner's token ( x or o ) if there is one, otherwise None """ - + if all(e == l[0] and e != "" for e in l): + return l[0] return None + def check_win(board): """Check if a player has won on a board Args: @@ -26,8 +29,26 @@ def check_win(board): Returns: The winner's token ( x or o ) if there is one, otherwise None """ + for row in board: + winner = check_row(row) + if winner: + return winner + + for col in zip(*board): + winner = check_row(col) + if winner: + return winner + + winner = check_row([board[i][i] for i in range(3)]) + if winner: + return winner + + winner = check_row([board[i][2 - i] for i in range(3)]) + if winner: + return winner return None + # The following code is the main part of the program. It creates a GUI for the # game and handles the game logic. Implement the functions above first, then @@ -36,72 +57,88 @@ def check_win(board): class TicTacToe: """A Simple Tic Tac Toe game""" - app = None - board = None # The storage for user's markers - buttons = None # Holds UI elements for the board - board_pane = None # - message = None - turn_n = 0 - turn = X_MARK - def __init__(self, win_func=check_win): - self.board = None # The stoage for user's markers + pygame.init() + self.screen = pygame.display.set_mode((300, 400)) + pygame.display.set_caption('Tic Tac Toe Game') + self.clock = pygame.time.Clock() - self.app = App('Tic Tac Toe Game', bg='burlywood') - self.board_pane = Box(self.app, layout='grid') # Holds UI elements for the board - self.message = Text(self.app, text="It is your turn, " + self.current_turn) - - self.reset_button = PushButton(self.app, text='Reset', command=self.reset) - - self.message.text_color = "green" - self.win_func = win_func - self.reset() def reset(self): """Reset the game state""" + self.board = [[None for _ in range(3)] for _ in range(3)] self.turn_n = 0 - self.turn = X_MARK - self.message.value = "It's your turn, " + self.current_turn - - self.board = [[None for _ in range(3)] for _ in range(3)] - self.buttons = [[None for _ in range(3)] for _ in range(3)] - - # generate a 3x3 grid - for x in range(3): - for y in range(3): - self.buttons[x][y] = PushButton(self.board_pane, text='', grid=[x, y], width=3, command=self.do_turn, args=[x,y]) - - def start(self): - """Start the game""" - self.app.display() + self.winner = None + self.message = "It's your turn, " + self.current_turn @property def current_turn(self): """Return the current player's marker, based on the current turn number""" return [X_MARK, O_MARK][self.turn_n % 2] - def do_turn(self, x, y): - """Handle one player turn, and return a marker if one of the players won""" - self.board[x][y] = self.current_turn - self.buttons[x][y].text = self.current_turn - self.buttons[x][y].disable() - - self.turn_n += 1 - self.message.value = f"It's your turn, {self.current_turn}" - - winner = self.win_func(self.board) - - if winner: - self.message.value = f"Player {winner} won!" - info("Tic-tac-toe",f"Player {winner} won!") - for row in self.buttons: - for button in row: - button.disable() - elif self.turn_n == 9: - self.message.value = "It's a draw!" - info("Tic-tac-toe","It's a draw!") + def draw(self): + self.screen.fill((255, 222, 173)) # burlywood + + # Draw grid + for i in range(1, 3): + pygame.draw.line(self.screen, (0, 0, 0), (i * 100, 0), (i * 100, 300), 2) + pygame.draw.line(self.screen, (0, 0, 0), (0, i * 100), (300, i * 100), 2) + + # Draw marks + for x in range(3): + for y in range(3): + if self.board[x][y] == X_MARK: + # Draw X + pygame.draw.line(self.screen, (0, 0, 0), (x*100 + 20, y*100 + 20), (x*100 + 80, y*100 + 80), 3) + pygame.draw.line(self.screen, (0, 0, 0), (x*100 + 80, y*100 + 20), (x*100 + 20, y*100 + 80), 3) + elif self.board[x][y] == O_MARK: + # Draw O + pygame.draw.circle(self.screen, (0, 0, 0), (x*100 + 50, y*100 + 50), 30, 3) + + # Draw message (simple text without font) + # For now, skip text, or use print + print(self.message) # Print to console + + # Draw reset button + pygame.draw.rect(self.screen, (200, 200, 200), (100, 340, 100, 40)) + # No text for button + + pygame.display.flip() + + def handle_click(self, pos): + x, y = pos + if y < 300: # board area + cell_x = x // 100 + cell_y = y // 100 + if self.board[cell_x][cell_y] is None and self.winner is None: + self.board[cell_x][cell_y] = self.current_turn + self.turn_n += 1 + self.winner = self.win_func(self.board) + if self.winner: + self.message = f"Player {self.winner} won!" + elif self.turn_n == 9: + self.message = "It's a draw!" + else: + self.message = f"It's your turn, {self.current_turn}" + elif 100 <= x <= 200 and 340 <= y <= 380: # reset button + self.reset() + + def run(self): + running = True + while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + elif event.type == pygame.MOUSEBUTTONDOWN: + self.handle_click(event.pos) + + self.draw() + self.clock.tick(60) + + pygame.quit() + sys.exit() ttt = TicTacToe(check_win) -ttt.start() +ttt.run() diff --git a/lessons/10_Turtles/10_Welcome/10_Welcome.ipynb b/lessons/10_Turtles/10_Welcome/10_Welcome.ipynb new file mode 100644 index 00000000..e733bb09 --- /dev/null +++ b/lessons/10_Turtles/10_Welcome/10_Welcome.ipynb @@ -0,0 +1,61 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Getting Started with Python\n", + "\n", + "This is the first lesson of your first Python class with the League of Amazing\n", + "Programmers. To follow these lessons, you should be reading this file in Visual\n", + "Studio Code if you are on your own computer, or if you are using a website, it\n", + "should be Github Codespaces, or the League Code Server. \n", + "\n", + "We will be writing programs in Python, and starting with turtle programming,\n", + "which is a fun way to learn programming because you will be drawing pictures\n", + "like this:\n", + "\n", + "
\n", + " \"spiral\"\n", + "
\n", + "\n", + "\n", + "It's called turtle programming because you are controlling a turtle that moves\n", + "around the screen drawing lines. You can make the turtle move forward, turn left\n", + "or right, and change the color of the lines it draws.\n", + "\n", + "However, before we start, we need to setup a few things, so let's move to the\n", + "next lesson to get started. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.11" + }, + "syllabus": { + "uid": "RRTPqCQu" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lessons/10_Turtles/10_Welcome/20_Open_The_Screen.ipynb b/lessons/10_Turtles/10_Welcome/20_Open_The_Screen.ipynb new file mode 100644 index 00000000..676bdaf5 --- /dev/null +++ b/lessons/10_Turtles/10_Welcome/20_Open_The_Screen.ipynb @@ -0,0 +1,48 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## Open a Virtual Screen on the Web\n", + "\n", + "If you started your editor as a Codespace on Github, that is, you clicked\n", + "on a button like \n", + "to start your editor, then you'll need to open a virtual screen. Most of the time this will happen automatically, but if it doesn't click on the monitor icon in the upper right of the screen. \n", + "\n", + "Now you have a virtual screen running. When your program writes to the screen, it will show up in this window. \n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.11" + }, + "syllabus": { + "uid": "KmgIQbhr" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lessons/10_Turtles/10_Welcome/30_Run_Programs.ipynb b/lessons/10_Turtles/10_Welcome/30_Run_Programs.ipynb new file mode 100644 index 00000000..7e27a6c7 --- /dev/null +++ b/lessons/10_Turtles/10_Welcome/30_Run_Programs.ipynb @@ -0,0 +1,212 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Running Programs\n", + "\n", + "We will be running Python program in two different ways: in Python files, and in\n", + "code Notebooks. \n", + "\n", + "* Notebook files end with `.ipynb`. These files are very special, because they\n", + " are both documents you can read and have programs that you can run. \n", + "* Python files end with `.py`. You can run them as normal programs, by pressing \n", + " the ▶️ play bytton. \n", + "\n", + "## Run Notebook Code Cells\n", + "\n", + "Notice that this file is a Notebook file. If you are reading the file in Visual\n", + "Studio Code, you will see \"⏩ Run All\" at the top of the screen, and some\n", + "paragraphs that have code will have a \"▶️\" on the left side. \n", + "\n", + "Below is a code cell you can try to run. If you hover your pointer over the\n", + "cell, you will see a \"▶️\" button. Click it to run the code." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello 👋 World 🌎 ! Today is 2025-06-14\n" + ] + } + ], + "source": [ + "import datetime\n", + "\n", + "date = datetime.date.today() # Get the Date\n", + "\n", + "s = F\"Hello 👋 World 🌎 ! Today is\" # Make a string with a message and the date\n", + "\n", + "print(s, date) # Print the string. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "Here is what that code cell looks like with the run button. Try running it!\n", + "\n", + "
\n", + "\n", + "The first time you press the \"▶️\" it may not do anything. Well, it did do\n", + " something, but you might not have seen it. After you click the button, look at\n", + " the top of the Visual Studio window for a box that looks like: \n", + "\n", + "
\n", + "\n", + "If you see this, you will want to select an entry for a Python interpreter. It\n", + "might look like \" .venv (Python 3.11)\" or maybe \"★ Python 3.12\" or something\n", + "like that. Pick the first one in the list, or the one with the \"★ \". Select an interpreter and then re-run the code. \n", + "\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You will have to select an interpreter every time you open a new notebook." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The block of code is called a \"Cell\", which is what we'll call it in the future.\n", + "In addition to running it with the ▶️ button, you can also press ⇧ (shift key) +\n", + "Enter to run it.\n", + "\n", + "Here are some other tips for cells: \n", + "\n", + "* Click in the cell to edit it. When the cell is editable, you will see a blue\n", + " bar on the side and a blue outline around the cell. \n", + "* Some operations on a cell, like moving it up or down, require it to be in\n", + " \"Command Mode\". Hit the Esc key to enter command mode. The blue side bar will\n", + " stay, but the blue outline will disappear. \n", + "* When a cell is active, there is a small menu in the upper right with more\n", + " options. \n", + " \n", + "## Assignment\n", + "\n", + "Now, you try it: \n", + "\n", + "1. Copy the Hello World code in the cell above to the cell below. \n", + "2. Change the code to also print out your name\n", + "3. Run the code. " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Write your Hello World code below\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run `.py` programs\n", + "\n", + "The files that end in `.py` are normal Python programs, and the type of program you will \n", + "run most often. Now let's run a Python program, which is in the file named ``02_Meet_Tina.py``. \n", + "\n", + "There are a few ways to do this, but the easiest is to look in the lower left of\n", + "the screen for the Lesson Browser actions: \n", + "\n", + "
\n", + "\n", + "Just click on the Run and Stop buttons. You can also click on \"Next Lesson\" to\n", + "go to the next lesson. \n", + "\n", + "### Use the ▶️ button\n", + "\n", + "Here is another way to run a program. \n", + "\n", + "1. Click on the file name to open the file\n", + "2. Look in the upper right for these icons: \n", + " click on the ▶️ run button to run the program. \n", + "3. Click on the window to close it. \n", + "\n", + "### Hit the F5 Key\n", + "\n", + "You can also run the program by hitting the F5 key. On a Mac, you will have to\n", + "hold down the fn key and then hit F5. This is a bit different than using the run\n", + "button, because F5 will open the debugger. \n", + "\n", + "The first time you hit F5, look at the top of the IDE window. You should see a\n", + "selection window that reads \"Select Debugger\". Select the first option, \"Python\n", + "Debugger\". Then, on the next window, select \"Python File. Debug currently active\n", + "Python file\". After that, you will see the debug bar: \n", + "\n", + "
\n", + "\n", + "We will learn all of the features for the debugger later, but for now you just\n", + "need to know that you press the red square to exit your program, and the gree\n", + "circle to re-run it. \n", + "\n", + "\n", + "
\n", + "\n", + "You can't run a program again until you end the currently running program. If\n", + "you see a turtle window open, then you should either click on the window to\n", + "close it ( if the program ends with `turtle.exitonclick()` or click on the X in\n", + "the upper right of the turtle window. )\n", + "\n", + "Or, if you are using the debugger, click the red square in the debugger bar. \n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, open the next file, ``02_Meet_Tina.py`` and run it." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" + }, + "syllabus": { + "uid": "cNLK6qtR" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lessons/10_Turtles/10_Welcome/README.md b/lessons/10_Turtles/10_Welcome/README.md new file mode 100644 index 00000000..c6ba2821 --- /dev/null +++ b/lessons/10_Turtles/10_Welcome/README.md @@ -0,0 +1,9 @@ + +--- + +uid: AZCeRx3O + +--- + +# Welcome + diff --git a/lessons/10_Turtles/20_Introducing_Tina/10_Meet_Tina/Meet_Tina.py b/lessons/10_Turtles/20_Introducing_Tina/10_Meet_Tina/Meet_Tina.py new file mode 100644 index 00000000..50dbaa2d --- /dev/null +++ b/lessons/10_Turtles/20_Introducing_Tina/10_Meet_Tina/Meet_Tina.py @@ -0,0 +1,102 @@ +""" +Run this program to meet Tina the Turtle. Tina is a +hexagon with legs and a head. + +You can run this program by: + +1) clicking on ▶️ icon at the top of the editor +window +2) Hit the F5 function key + +You won't understand what this program is doing just +yet, but don't worry, that's what you will be +learning in the next few lessons. +""" + +import turtle # Tell Python we want to work with the turtle +turtle.setup(600,600,0,0) # Set the size of the window + +tina = turtle.Turtle() # Create a turtle named tina + +tina.speed('fastest') # Set the speed of the turtle to fastest + +# Draw the hexagon +tina.penup() # Lift the pen up so we can move tina without drawing +tina.goto(-100, 175) # Move tina to the starting position +tina.pendown() +tina.begin_fill() + +def head_pos(l=200): + """ Position of tina's head, relative to the center of the screen""" + from math import radians, tan + return (l/2) / tan(radians(30)) + +def draw_body(t, l = 200): + """Draw the body of the turtle""" + t.pencolor('green') # Set the pen color to green + t.fillcolor('green') # Set the fill color to green + t.penup() + t.goto(0,0) # Move tina to the center of the screen + t.setheading(-90) # Set the heading of tina to -90 degrees + t.forward(head_pos(l)) # Move tina forward by the head position + t.right(90) # Turn tina right by 90 degrees + t.backward( l/2 ) # Move tina backward by half the length + t.pendown() + t.begin_fill() + for _ in range(6): + t.forward(l) # Move tina forward by the length + t.right(60) # Turn tina right by 60 degrees + t.end_fill() + +def draw_leg(t, a, r=170, w=40, l=50): + """Draw A Leg""" + t.penup() + t.goto(0, 0) # Move tina to the center of the screen + t.setheading(a) # Set the heading of tina to the angle + t.forward(r) # Move tina forward by the radius + t.pendown() + t.pencolor('brown') # Set the pen color to brown + t.fillcolor('brown') # Set the fill color to brown + t.begin_fill() + t.left(90) # Turn tina left by 90 degrees + t.forward(w/2) # Move tina forward by half the width + t.right(90) # Turn tina right by 90 degrees + t.forward(l) # Move tina forward by the length + t.right(90) # Turn tina right by 90 degrees + t.forward(w) # Move tina forward by the width + t.right(90) # Turn tina right by 90 degrees + t.forward(l) # Move tina forward by the length + t.right(90) # Turn tina right by 90 degrees + t.forward(w/2) # Move tina forward by half the width + t.end_fill() + +def draw_head(): + """Draw a brown head at the head position""" + tina.penup() + tina.goto(0, head_pos()-20) # Move tina to the head position + tina.pendown() + tina.pencolor('brown') # Set the pen color to brown + tina.fillcolor('brown') # Set the fill color to brown + tina.begin_fill() + tina.circle(50) # Draw a circle with radius 50 + tina.end_fill() + +def say_hello(): + """Make tina say hello, with text to the right of her head""" + tina.penup() + tina.goto(75, head_pos()+75) # Move tina to the position for the text + tina.pendown() + tina.write("Hello! I'm Tina!", font=("Arial", 20, "normal")) # Write the text + +draw_head() + +for lp in (30, -30, -150, 150): + draw_leg(tina, lp) # Draw the legs at the specified angles + +draw_leg(tina, -90, r=170, w=10, l=50) # This one is actually a tail! + +draw_body(tina) # Draw the body of the turtle + +say_hello() # Make tina say hello + +turtle.exitonclick() # Close the window when we click on it \ No newline at end of file diff --git a/lessons/10_Turtles/20_Introducing_Tina/10_Meet_Tina/README.md b/lessons/10_Turtles/20_Introducing_Tina/10_Meet_Tina/README.md new file mode 100644 index 00000000..854f60fb --- /dev/null +++ b/lessons/10_Turtles/20_Introducing_Tina/10_Meet_Tina/README.md @@ -0,0 +1,11 @@ +--- +uid: tvO1dlwm +--- + +# Meet Tina + +Run this program to meet Tina. You can run the program by + +1. (Best) Click the green  ▶️ run  button in the bottom left of the screen. +2. Hit the F5 key. +3. Click the ▶️ icon in the editor title bar ( upper right) \ No newline at end of file diff --git a/lessons/10_Turtles/20_Introducing_Tina/20_What_Can_Tina_Do.ipynb b/lessons/10_Turtles/20_Introducing_Tina/20_What_Can_Tina_Do.ipynb new file mode 100644 index 00000000..9681fa3b --- /dev/null +++ b/lessons/10_Turtles/20_Introducing_Tina/20_What_Can_Tina_Do.ipynb @@ -0,0 +1,66 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# What Can Tina Do?\n", + "\n", + "The first program where you met Tina was pretty complicated! But it was made of a lot of simple parts. The next program is simpler, and has commands that you can figure out for yourself. In the next program, `02c_Squares_and_Circles`, Tina will draw a square and a circle. Your task will be to read the program, figure out what it does, and change it. \n", + "\n", + "Here is what some of the program will look like: \n", + "\n", + "```python\n", + "tina = turtle.Turtle() # Create a turtle named tina\n", + "\n", + "tina.pencolor('blue') # Set the pen color to blue\n", + "tina.forward(200) # Move tina forward by the forward distance\n", + "tina.right(90) # Turn tina left by the left turn\n", + "\n", + "```\n", + "\n", + "The program will have a lot of lines like this. Each line is a command for Tina to do something. The commands are in English, and they are pretty easy to understand. What you will do is: \n", + "\n", + "Run the program, then read through the program and figure out what each command does. The part of the program at the start of the line: \n", + "\n", + "```python\n", + "tina.forward(200) \n", + "```\n", + "\n", + "is the command. What could this line do? Maybe ... move Tina forward by 200 steps?\n", + "\n", + "After that will be a comment, which looks like this: \n", + "\n", + "```python\n", + "# Move tina forward by the forward distance\n", + "```\n", + "\n", + "Comments are only for people to read, and they start with a `#`. They are there to help you understand the program.\n", + "\n", + "## Assignment\n", + "\n", + "1. Run the program `02c_Squares_and_Circles` and see what it does.\n", + "2. Read through the program and figure out what each command does.\n", + "3. Change the program so that Tina draws a square and a circle of different sizes and colors.\n", + "4. Run the program again and see what it does now.\n", + "\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.12.11" + }, + "syllabus": { + "uid": "7tUP3zAZ" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/10_Turtles/20_Introducing_Tina/30_Squares_and_Circles/README.md b/lessons/10_Turtles/20_Introducing_Tina/30_Squares_and_Circles/README.md new file mode 100644 index 00000000..239cf3a0 --- /dev/null +++ b/lessons/10_Turtles/20_Introducing_Tina/30_Squares_and_Circles/README.md @@ -0,0 +1,10 @@ +--- +uid: E7KlecQ3 +--- + +# Squares and Circles + +1. Run the program `02b_Squares_and_Circles` and see what it does. +2. Read through the program and figure out what each command does. +3. Change the program so that Tina draws a square and a circle of different sizes and colors. +4. Run the program again and see what it does now. \ No newline at end of file diff --git a/lessons/10_Turtles/20_Introducing_Tina/30_Squares_and_Circles/Squares_and_Circles.py b/lessons/10_Turtles/20_Introducing_Tina/30_Squares_and_Circles/Squares_and_Circles.py new file mode 100644 index 00000000..7e22ab03 --- /dev/null +++ b/lessons/10_Turtles/20_Introducing_Tina/30_Squares_and_Circles/Squares_and_Circles.py @@ -0,0 +1,75 @@ +""" +This is a simple Turtle program that draws a square and writes a message. The +lines that start with a # are comments. They are not executed by Python. The +lines inside the three quotes are also comments, but of a different sort ( +called "doc comments" ) Comments are used to explain what the code does. Read +the program and try to understand what each line does. +""" + +import turtle # Tell Python we want to work with the turtle +turtle.setup(600,600,0,0) # Set the size of the window + +tina = turtle.Turtle() # Create a turtle named tina + +tina.shape('turtle') # Set the shape of the turtle to a turtle +tina.speed(2) # Make the turtle move as fast, but not too fast. + +## +## Move Tina to the Starting Position +# + +tina.penup() # Lift the pen up so we can move tina without drawing +tina.goto(-100, 100) # Move tina to the starting position +tina.pendown() # Put the pen down so we can draw + +## +## Draw a Square +## + +tina.pencolor('blue') # Set the pen color to blue +tina.forward(200) # Move tina forward by the forward distance +tina.right(90) # Turn tina right a quarter turn + +tina.pencolor('red') # Set the pen color to red +tina.forward(200) # Continue the last two steps three more times +tina.right(90) # to draw a square + +tina.pencolor('green') # Set the pen color to green +tina.forward(200) +tina.right(90) + +tina.pencolor('purple') # Set the pen color to purple +tina.forward(200) +tina.right(90) + +## +## Draw a Circle +## + +tina.penup() +tina.goto(0, -75) +tina.pendown() + +tina.pendown() +tina.color('red') # Set the color of tina to red +tina.begin_fill() +tina.circle(75) +tina.end_fill() + +## +## Write a Message +## + +tina.penup() # Lift the pen up so we can move tina without drawing +tina.goto(-50, -150) +tina.forward(20) # Move tina forward by 20 +tina.left(90) # Turn tina left by 90 degrees +tina.forward(20) # Move tina forward by 20 +tina.write("Why, hello there!") # Write the message "Why, hello there!" +tina.backward(20) # Move tina backward by 20 + +turtle.exitonclick() # Close the window when we click on it + +# You're on your way, soon you'll be writing your own programs! +# But first, let's save your progress. Continue with +# the next file, 03_Check_In_Your_Code.ipynb \ No newline at end of file diff --git a/lessons/10_Turtles/20_Introducing_Tina/40_Check_In_Your_Code.ipynb b/lessons/10_Turtles/20_Introducing_Tina/40_Check_In_Your_Code.ipynb new file mode 100644 index 00000000..02882c66 --- /dev/null +++ b/lessons/10_Turtles/20_Introducing_Tina/40_Check_In_Your_Code.ipynb @@ -0,0 +1,147 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Check In Your Code\n", + "\n", + "Now that you have written a few programs, you have made changes to the source code in\n", + "your Codespace. If you want to save those changes for later – and you almost\n", + "certainly do – you should \"check it in\" to Source Control. If you don't,\n", + "eventually your GitHub codespace will be stopped automatically, then deleted\n", + "after a few weeks, and you will lose your changes. So check your code in!\n", + "\n", + "## Make a Change\n", + "\n", + "Let's make a change to `02a_Meet_Tina` so we have something to check in. You can\n", + "change anything you want! Maybe make the circle a different size \n", + "( change `tina.circle(100, steps=50)` ) or change what tina says ( change\n", + "`tina.write(\"Why, hello there!\")` ) or anything else, then save your file. \n", + "\n", + "## Commit and sync your code\n", + "\n", + "Once you have made the change, save your file. Then, on the left side of the\n", + "Codespace window, look for this icon. The number may be different for you (it\n", + "will probably be 1). \n", + "\n", + "
\n", + "\n", + "This is the Source Control icon; click on it to get access to the Source Control tool for\n", + "checking in your code. Now the Source Control pane should look like this: \n", + "\n", + "
\n", + "\n", + "To check in your code enter a message in the Message box to describe what you\n", + "changed, then click on the ✓ Commit button. That will check in your changes,\n", + "but they aren't really stored permanently yet.\n", + "\n", + "After you commit, the blue button will change to:\n", + "\n", + "
\n", + "\n", + "Click the Sync button, and *now* your changes are safely in your GitHub account's repository. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One problem you might have is if you click the ✓ Commit button and it doesn't\n", + "seem to do anything, but the edit pane ( where you edit files ) changes to look\n", + "like this:\n", + "\n", + "
\n", + "\n", + "This happens if you click the ✓ Commit button without entering a commit message first. There are two ways to proceed:\n", + "\n", + "1. Close the edit message file by clicking on the x in the files tab. then go\n", + " back to the Source Control window and enter a message before clicking on the\n", + " ✓ Commit button. \n", + "2. Enter a commit message at the top of the edit message file, save the file,\n", + " then close it, and the commit process will finish. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Remember to check in your code frequently! The best thing to do is check in\n", + "after every lesson, but you should be especially diligent about checking code in\n", + "before you finish your lessons for the day. \n", + "\n", + "If you want to force your Codespace to stop, click on the blue area in the lower\n", + "left corner. That will pop up a menu ( at the top of the screen ) with options\n", + "to stop the codespace. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Continue your Lessons" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you want to resume your lessons, you will probably find that your Codespace has been automatically stopped. You should have already checked in your code, but if you didn't, your changes will still be in the Codespace. If you left the browser window open, it will look like this:\n", + "\n", + "
\n", + "\n", + "If you see that, just click on the green \"Restart Codespace\" to pick up where you left off. \n", + "\n", + "If you don't still have that window open, it is still easy to restart your Codespace. \n", + "\n", + "First, go your GitHub account and look for the repository called \"Python-Apprentice.\" \n", + "\n", + "Next, click on the \n", + "button, and in the popup window, select the \"Codespaces\" tab. You should *not*\n", + "see the green \"Create Codespace\" button, but rather, it should look something\n", + "like this: \n", + "\n", + "
\n", + "\n", + "The codespaces have crazy names, like this one, \"expert broccoli\".\n", + "\n", + "If your Codespace isn't actually stopped, it is still running, you will see \"Active\" along with a green dot: \n", + "\n", + "
\n", + "\n", + " Either way, you can click on the crazy name link to open the Codespace and continue your lessons. \n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" + }, + "syllabus": { + "uid": "doD6P7fk" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lessons/10_Turtles/20_Introducing_Tina/README.md b/lessons/10_Turtles/20_Introducing_Tina/README.md new file mode 100644 index 00000000..8a081375 --- /dev/null +++ b/lessons/10_Turtles/20_Introducing_Tina/README.md @@ -0,0 +1,9 @@ + +--- + +uid: NtvhO8WR + +--- + +# Introducing Tina + diff --git a/lessons/10_Turtles/30_Turtle_Tricks/10_Turtle_Tricks.py b/lessons/10_Turtles/30_Turtle_Tricks/10_Turtle_Tricks.py new file mode 100644 index 00000000..8167867e --- /dev/null +++ b/lessons/10_Turtles/30_Turtle_Tricks/10_Turtle_Tricks.py @@ -0,0 +1,20 @@ +""" +For this program, you will tell Tina the Turtle to draw a triangle. + +You should look at the previous programs to see how to use the turtle commands. +Copy lines of code from those programs to this one to draw a triangle. +""" + +# These lines are needed in most turtle programs +import turtle # Tell Python we want to work with the turtle +turtle.setup(600,600,0,0) # Set the size of the window + +tina = turtle.Turtle() # Create a turtle named tina + +# Use tina.forward() and tina.left() to draw a triangle +# Make each side of the triangle a different color with +# tina.pencolor() + +... # Your code here + +turtle.exitonclick() # Close the window when we click on it \ No newline at end of file diff --git a/lessons/10_Turtles/30_Turtle_Tricks/20_Turtle_Tricks.py b/lessons/10_Turtles/30_Turtle_Tricks/20_Turtle_Tricks.py new file mode 100644 index 00000000..5598ef1f --- /dev/null +++ b/lessons/10_Turtles/30_Turtle_Tricks/20_Turtle_Tricks.py @@ -0,0 +1,20 @@ +""" +For this program, you will tell Tina the Turtle to draw +a pentagon. + +You should look at the previous program, 02_Meet_Tina.py +to see how to use the turtle commands. +""" + +# These lines are needed in most turtle programs +import turtle # Tell Python we want to work with the turtle +turtle.setup(600,600,0,0) # Set the size of the window +tina = turtle.Turtle() # Create a turtle named tina + +# Use tina.forward() and tina.left() to draw a pentagon +# Make each side of the pentagon a different color with +# tina.pencolor() + +... # Your code here + +turtle.exitonclick() # Close the window when we click on it \ No newline at end of file diff --git a/lessons/10_Turtles/30_Turtle_Tricks/30_Turtle_Tricks.py b/lessons/10_Turtles/30_Turtle_Tricks/30_Turtle_Tricks.py new file mode 100644 index 00000000..cecf2e9f --- /dev/null +++ b/lessons/10_Turtles/30_Turtle_Tricks/30_Turtle_Tricks.py @@ -0,0 +1,24 @@ +""" +For this program, you will tell Tina the Turtle to draw +multiple shapes. + +Draw two circles, filled with different colors, +and in different places on the screen. + +You should look at the previous program, 02_Meet_TIna.py +to see how to use the turtle commands. +""" + +# These lines are needed in most turtle programs +import turtle # Tell Python we want to work with the turtle +turtle.setup(600,600,0,0) # Set the size of the window +tina = turtle.Turtle() # Create a turtle named tina + +# Use tina.circle() to draw a circle, and tina.goto() to move tina to a new location +# Use tina.begin_fill(), tina.end_fill(), and tina.fillcolor() to fill in the shapes + +... # Your code here + +turtle.exitonclick() # Close the window when we click on it + +# Dont forget to check in your code! \ No newline at end of file diff --git a/lessons/10_Turtles/30_Turtle_Tricks/README.md b/lessons/10_Turtles/30_Turtle_Tricks/README.md new file mode 100644 index 00000000..5a5e6772 --- /dev/null +++ b/lessons/10_Turtles/30_Turtle_Tricks/README.md @@ -0,0 +1,9 @@ + +--- + +uid: c6l7hD7a + +--- + +# Turtle Tricks + diff --git a/lessons/10_Turtles/40_Loops/10_Loops.ipynb b/lessons/10_Turtles/40_Loops/10_Loops.ipynb new file mode 100644 index 00000000..676b87f9 --- /dev/null +++ b/lessons/10_Turtles/40_Loops/10_Loops.ipynb @@ -0,0 +1,118 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Loops and Variables\n", + "\n", + "In our first Tina the Turtle program, we had Tina draw a square, but it was \n", + "very tedious, and involved a lot of repetition: \n", + "\n", + "```python \n", + "import turtle # Tell Python we want to work with the turtle\n", + "turtle.setup(600,600,0,0) # Set the size of the window\n", + "\n", + "tina = turtle.Turtle() # Create a turtle named tina\n", + "\n", + "tina.shape('turtle') # Set the shape of the turtle to a turtle\n", + "tina.speed(2) # Make the turtle move as fast, but not too fast. \n", + "\n", + "tina.forward(150) # Move tina forward by the forward distance\n", + "tina.left(90) # Turn tina left by the left turn\n", + "\n", + "tina.forward(150) # Continue the last two steps three more times\n", + "tina.left(90) # to draw a square\n", + "\n", + "tina.forward(150)\n", + "tina.left(90)\n", + "\n", + "tina.forward(150)\n", + "tina.left(90)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "vscode": { + "languageId": "plaintext" + } + }, + "source": [ + "The code \n", + "\n", + "```python \n", + "tina.forward(150)\n", + "tina.left(90)\n", + "\n", + "```\n", + "\n", + "gets repeated 4 times. That doesn't seem right!\n", + "\n", + "We can improve this code with a loop. Here is an example of a loop:\n", + "\n", + "( Remember that you can run it; click the \"▶️\" on the left. \n", + " ) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# For loop; try changing the number of iterations to 6\n", + "for i in range(4):\n", + " print('Loop Iteration', i)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that the number of iterations is the number inside of the parentheses in\n", + "`range()`. Also notice that the `print` statement is indented below the `for` loop\n", + "line. Indenting is how you tell python what lines of code should be repeated. \n", + "\n", + "The `i` in the line `for i in range(4)` is a variable; it will hold the number of the \n", + "iteration, starting at 0. For most of our loops in this module we won't use the \n", + "variable, but we will study it more in a later module. \n", + "\n", + "\n", + "Now try updating the next program ``05_Loop_with_Turtle.py`` with a loop. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" + }, + "syllabus": { + "uid": "abX8sNwB" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/10_Turtles/40_Loops/20_Loop_with_Turtle.py b/lessons/10_Turtles/40_Loops/20_Loop_with_Turtle.py new file mode 100644 index 00000000..49d6dda9 --- /dev/null +++ b/lessons/10_Turtles/40_Loops/20_Loop_with_Turtle.py @@ -0,0 +1,28 @@ +""" +Turtles with a loop. + +This program has four identical lines of code to draw a square, +but you know you can use a loop to make the program simpler. +""" + +import turtle # Tell Python we want to work with the turtle +turtle.setup(600,600,0,0) # Set the size of the window + +tina = turtle.Turtle() # Create a turtle named tina + +tina.shape('turtle') # Set the shape of the turtle to a turtle +tina.speed(2) # Make the turtle move as fast, but not too fast. + +tina.forward(150) # Move tina forward by the forward distance +tina.left(90) # Turn tina left by the left turn + +tina.forward(150) # Continue the last two steps three more times +tina.left(90) # to draw a square + +tina.forward(150) +tina.left(90) + +tina.forward(150) +tina.left(90) + +turtle.exitonclick() # Close the window when we click on it \ No newline at end of file diff --git a/lessons/10_Turtles/40_Loops/30_Loop_with_Turtle.py b/lessons/10_Turtles/40_Loops/30_Loop_with_Turtle.py new file mode 100644 index 00000000..324da245 --- /dev/null +++ b/lessons/10_Turtles/40_Loops/30_Loop_with_Turtle.py @@ -0,0 +1,9 @@ +""" +Turtles with a loop. + +Study the previous program, 05a_Loop_with_Turtle.py, and then +write a new program that uses a loop to draw a pentagon. +( You can cut and past most of it! ) +""" + +... # Your code here \ No newline at end of file diff --git a/lessons/10_Turtles/40_Loops/README.md b/lessons/10_Turtles/40_Loops/README.md new file mode 100644 index 00000000..3d9eb27b --- /dev/null +++ b/lessons/10_Turtles/40_Loops/README.md @@ -0,0 +1,9 @@ + +--- + +uid: wVDXfv96 + +--- + +# Loops + diff --git a/lessons/10_Turtles/50_Variables_and_Functions/10_Variables_and_Functions.ipynb b/lessons/10_Turtles/50_Variables_and_Functions/10_Variables_and_Functions.ipynb new file mode 100644 index 00000000..3274a706 --- /dev/null +++ b/lessons/10_Turtles/50_Variables_and_Functions/10_Variables_and_Functions.ipynb @@ -0,0 +1,175 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Variables and Functions\n", + "\n", + "
\n", + " A few things to remember:\n", + "\n", + " 1) Commit your code! Review `03_Check_In_You_Code` for a reminder \n", + " on how to commit and sync your changes. \n", + " 2) Remember that these `.ipynb` files have runnable cells. Review `01_Get_Started`, \n", + " in the section \"Running Programs\" for a reminder on how to run code cells in this file. \n", + " \n", + "
\n", + "\n", + "\n", + "Here is one of the ways to solve the last assignment, making shapes with a\n", + "loop:\n", + "\n", + "```python \n", + "\n", + "import turtle # Tell Python we want to work with the turtle\n", + "turtle.setup(600,600,0,0) # Set the size of the window\n", + "\n", + "tina = turtle.Turtle() # Create a turtle named tina\n", + "\n", + "for i in range(4):\n", + " tina.forward(150) # Move tina forward by the forward distance\n", + " tina.left(90) # Turn tina left by the left turn\n", + "\n", + "\n", + "```\n", + "\n", + "Let's see if we can make this code even simpler. Notice that the code that draws\n", + "the square has a range of `4` and left turn of `90` degrees, and $4*90 = 360$,\n", + "and there are 360 degrees in a circle. The pentagram has a range of `5` and a\n", + "left turn of `72` degrees, and $5*72=360$. Hmm... could we come up with a way to\n", + "compute the angle for any number of sides? To do that, we going to use\n", + "variables and math. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run me\n", + "# Compute the angle for a number of sides\n", + "\n", + "sides = 6\n", + "angle = 360/sides\n", + "\n", + "angle" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we want 6 sides the angle is 60 degrees, and sure enough, $60*6 = 360$.\n", + "\n", + "The words `sides` and `angle` are __variables__, which are like the names of boxes \n", + "that can hold values. We can __assign__ values to variables, then use those variables \n", + "in other places. \n", + "\n", + "```python \n", + "\n", + "sides = 4\n", + "angle = 360/sides # Calculate the angle from the number of sides. \n", + "\n", + "for i in range(sides):\n", + " tina.forward(150) # Move tina forward by the forward distance\n", + " tina.left(angle) # Turn tina left by the left turn\n", + "\n", + "```\n", + "\n", + "In this program, if you change the number that we assign to `sides`, the angle will change automatically!\n", + "\n", + "Let's see if the angles created by this equation seem correct. Fill in the\n", + "'...' in the program in the cell below to calculate angles from sides: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run me!\n", + "\n", + "for sides in range(1, 10):\n", + " angle = ...\n", + " print(\"Angle for \", sides, \" sides is \", angle)\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Functions\n", + "\n", + "We can make another improvement in our program; by grouping \n", + "the commands to create a shape into a __function__. Here is an example of a function:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def say_hello(name, times): # define the function, and give it a name. 'name' and 'times' are parameters\n", + "\n", + " for i in range(times): # This is the body of the function\n", + " print(i, \"Hello \", name)\n", + "\n", + "say_hello(\"John\", 5) # Call the function, and pass it two arguments" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The line that starts with 'def' is the start of the function definition, and the\n", + "last line is where we call the function -- we actually run it. Try calling the\n", + "function again with different parameters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "say_hello('bob',3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" + }, + "syllabus": { + "uid": "HOBo0wvj" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/10_Turtles/50_Variables_and_Functions/20_Efficient_Turtle.py b/lessons/10_Turtles/50_Variables_and_Functions/20_Efficient_Turtle.py new file mode 100644 index 00000000..2060ccb8 --- /dev/null +++ b/lessons/10_Turtles/50_Variables_and_Functions/20_Efficient_Turtle.py @@ -0,0 +1,35 @@ + +""" +More Efficient Turtles + +Use what you've learned about functions and variables to make a program that +can draw a square, pentagon, and hexagon with a single function +""" + +import turtle # Tell Python we want to work with the turtle +turtle.setup(600,600,0,0) # Set the size of the window + +tina = turtle.Turtle() # Create a turtle named tina + +tina.shape('turtle') # Set the shape of the turtle to a turtle +tina.speed(2) # Make the turtle move as fast, but not too fast. + +def draw_polygon(sides): + + angle = ... # Calculate angle from number of sides + + for i in range(...): # Loop through the number of sides + ... # Move tina forward by the forward distance + ... # Turn tina left by the left turn + +draw_polygon(...) # Draw a square + +... # Move tina to another spot on the screen + +draw_polygon(...) # Draw a pentagon + +... # Move tina to another spot on the screen + +draw_polygon(...) # Draw a hexagon + +turtle.exitonclick() # Close the window when we click on it \ No newline at end of file diff --git a/lessons/10_Turtles/50_Variables_and_Functions/README.md b/lessons/10_Turtles/50_Variables_and_Functions/README.md new file mode 100644 index 00000000..744738e7 --- /dev/null +++ b/lessons/10_Turtles/50_Variables_and_Functions/README.md @@ -0,0 +1,9 @@ + +--- + +uid: O1qsljMz + +--- + +# Variables and Functions + diff --git a/lessons/10_Turtles/60_More_Turtle_Programs/10_More_Turtle_Programs.ipynb b/lessons/10_Turtles/60_More_Turtle_Programs/10_More_Turtle_Programs.ipynb new file mode 100644 index 00000000..7ebc70f4 --- /dev/null +++ b/lessons/10_Turtles/60_More_Turtle_Programs/10_More_Turtle_Programs.ipynb @@ -0,0 +1,337 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Learn more about the Turtle\n", + "\n", + "( Have you checked in your code? ) \n", + "\n", + "We've seen a lot of Turtle programs so far, but there is a lot more to the\n", + "Python turtle. Fortunately, there is a list of everything that the Turtle is\n", + "capable of: the Python documentation for the turtle module. Visit this site to see\n", + "the full documentation: \n", + "\n", + "https://docs.python.org/3.10/library/turtle.html\n", + "\n", + "There are a lot of interesting new things in this documentation! For instance: \n", + "\n", + "* You can make the turtle go to a position with `setx()` and `sety()`\n", + "* You can set the turtle shape from any image file with `.addshape` and `turtle.shape()`" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "vscode": { + "languageId": "plaintext" + } + }, + "source": [ + "# Change the Turtle Image\n", + "\n", + "Here is an example of how you can change the look of the turtle to an image. \n", + "You can copy the ``set_turtle_image()`` function into your own programs. \n", + "\n", + "Important:\n", + "* The image file must be a GIF. ( The file name ends in `.gif` )\n", + "* The image file must be in the `image` directory, and the `image` directory\n", + " must be in the same directory as your program. \n", + "\n", + "```python\n", + "\n", + "import turtle\n", + "\n", + "def set_turtle_image(turtle, image_name):\n", + " \"\"\"Set the turtle's shape to a custom image.\"\"\"\n", + "\n", + " from pathlib import Path\n", + " image_dir = Path(__file__).parent.parent / \"images\"\n", + " image_path = str(image_dir / image_name)\n", + "\n", + " screen = turtle.getscreen()\n", + " screen.addshape(image_path)\n", + " turtle.shape(image_path)\n", + "\n", + "# Set up the screen\n", + "screen = turtle.Screen()\n", + "screen.setup(width=600, height=600)\n", + "\n", + "# Create a turtle and set its shape to the custom GIF\n", + "t = turtle.Turtle()\n", + "\n", + "set_turtle_image(t, \"pikachu.gif\")\n", + "\n", + "t.penup()\n", + "t.speed(3)\n", + "\n", + "for i in range(4):\n", + " t.goto(200, 200)\n", + " t.goto(-200, -200)\n", + "\n", + "turtle.exitonclick() \n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Change the Background Image\n", + "\n", + "Important:\n", + "* The image file can be a GIF or a PNG\n", + "* The image file must be in the `image` directory, and the `image` directory\n", + " must be in the same directory as your program. \n", + "\n", + "```python\n", + "\n", + "import turtle\n", + "\n", + "def set_background_image(window, image_name):\n", + " \"\"\"Set the background image of the turtle window to the image with the given name.\"\"\"\n", + "\n", + " from pathlib import Path\n", + " from PIL import Image\n", + "\n", + " image_dir = Path(__file__).parent.parent / \"images\"\n", + " image_path = str(image_dir / image_name)\n", + "\n", + " image = Image.open(image_path)\n", + " \n", + " window.setup(image.width, image.height, startx=0, starty=0)\n", + " window.bgpic(image_path)\n", + "\n", + "# Set up the screen\n", + "import turtle # Tell Python we want to work with the turtle\n", + "turtle.setup(width=600, height=600) # Set the size of the window\n", + "\n", + "tina = turtle.Turtle() # Create a turtle named tina\n", + "\n", + "screen = turtle.Screen() # Get the screen that tina is on\n", + "set_background_image(screen, \"emoji.png\") # Set the background image of the screen\n", + "\n", + "turtle.exitonclick() \n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# More than One Turtle\n", + "\n", + "You can have more than one turtle on the screen. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```python\n", + "# Double click on this cell to copy the code. \n", + "\n", + "import turtle as turtle\n", + "\n", + "screen = turtle.Screen()\n", + "screen.setup(width=600, height=600)\n", + "screen.bgcolor('white')\n", + "\n", + "t1 = turtle.Turtle()\n", + "t1.penup()\n", + "t1.shape(\"turtle\")\n", + "\n", + "t2 = turtle.Turtle()\n", + "t2.penup()\n", + "t2.shape(\"arrow\")\n", + "\n", + "for i in range(-200, 200):\n", + " t1.goto(i,i)\n", + " t2.goto(i,-i)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Click on the Screen\n", + "\n", + "You can make the turtle do things when you click on the screen. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```python\n", + "# Double click on this cell to copy the code \n", + "\n", + "import turtle as turtle\n", + "\n", + "screen = turtle.Screen()\n", + "screen.setup(width=600, height=600)\n", + "screen.bgcolor('white')\n", + "\n", + "t = turtle.Turtle()\n", + "t.penup()\n", + "t.shape(\"turtle\")\n", + "\n", + "# This is the function that gets called when you click on the screen\n", + "def screen_clicked(x, y):\n", + " \"\"\"Print the x and y coordinates of the screen when clicked.\n", + " and make the turtle move to the clicked location.\"\"\"\n", + "\n", + " print('You pressed: x=' + str(x) + ', y=' + str(y))\n", + "\n", + " t.goto(x, y)\n", + " \n", + "screen.onclick(screen_clicked) # Important! Tell Python which function to use when the screen is clicked\n", + "\n", + "turtle.done() # Important! Use `done` not `exitonclick` to keep the window open\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Click on the Turtle\n", + "\n", + "You can execute a function when the user clicks on the turtle. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```python \n", + "# Double click on this cell to copy the code\n", + "\n", + "import turtle as turtle\n", + "\n", + "turtle.setup(width=600, height=600)\n", + "\n", + "t = turtle.Turtle()\n", + "\n", + "t.shape(\"turtle\")\n", + "t.turtlesize(stretch_wid=10, stretch_len=10, outline=4) # Make the turtle really big\n", + "\n", + "def turtle_clicked(t, x, y):\n", + " \"\"\"Function that gets called when the user clicks on the turtle\n", + "\n", + " This function will make the turtle tilt 20 degrees 18 times, making a full\n", + " circle. It is called by the turtle when the user clicks on it.\n", + "\n", + " Args:\n", + " t (Turtle): The turtle object that was clicked\n", + " x (int): The x coordinate of the click\n", + " y (int): The y coordinate of the click\n", + " \"\"\"\n", + "\n", + " print('turtle clicked!')\n", + " \n", + " for i in range(0,360, 20): # Full circle, 20 degrees at a time\n", + " t.tilt(20) # Tilt the turtle 20 degrees\n", + "\n", + "# Connect the turtle to the turtle_clicked function\n", + "t.onclick(lambda x, y, t=t: turtle_clicked(t, x, y))\n", + "\n", + "turtle.done() # Important! Use `done` not `exitonclick` to keep the window open\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "In the line `t.onclick(lambda x, y, t=t: turtle_clicked(t, x, y))` the\n", + "lambda keyword is used to create an anonymous function, a function that does not\n", + "have a name. Lambda functions are advanced, we'll explain them in a future\n", + "lesson, but for now, just know that this is a way to pass arguments to a\n", + "function when using the `onclick` method. You can just copy this line to make\n", + "the turtle respond to clicks.\n", + "\n", + "\n", + "## But Which Turtle?\n", + "Unfortunately, if you have multiple turtles, you wont be able to tell which\n", + "turtle was clicked on in the ``turtle_clicked`` function. Here is one way to\n", + "solve that problem, using some advanced Python that we have not learned yet. \n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "```python\n", + "# Double click on this cell to copy the code\n", + "\n", + "import turtle as turtle\n", + "\n", + "screen = turtle.Screen()\n", + "screen.setup(width=600, height=600)\n", + "screen.bgcolor('white')\n", + "\n", + "t = turtle.Turtle()\n", + "t.penup()\n", + "t.shape(\"turtle\")\n", + "t.turtlesize(stretch_wid=10, stretch_len=10, outline=4)\n", + "\n", + "def turtle_clicked(t, x, y):\n", + "\n", + " print('turtle clicked!')\n", + " \n", + " for i in range(0,360, 20):\n", + " t.tilt(20)\n", + "\n", + "t.onclick(lambda x, y, t=t: turtle_clicked(t, x, y))\n", + "\n", + "turtle.done() # Important! Use `done` not `exitonclick` to keep the window open\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Check In Your Code\n", + "\n", + "Now would be a great time to ensure all of your changes are checked in. You can review how to check in your\n", + "code, and how to restart your Codespace, in our [Code Check In How To Guide](https://curriculum.jointheleague.org/howto/checkin_restart.html).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" + }, + "syllabus": { + "uid": "IloYptI2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/10_Turtles/60_More_Turtle_Programs/20_More_Turtle_programs.py b/lessons/10_Turtles/60_More_Turtle_Programs/20_More_Turtle_programs.py new file mode 100644 index 00000000..8a27e9bf --- /dev/null +++ b/lessons/10_Turtles/60_More_Turtle_Programs/20_More_Turtle_programs.py @@ -0,0 +1,7 @@ +""" +Copy the code from the previous lesson, 08a_More_Turtle_programs.ipynb, +from the section "Change the Turtle Image" + +Then change the code so that the turtle has a different image ( look in the 'images' +directory ) and moves to the corners of the screen in a square pattern. +""" \ No newline at end of file diff --git a/lessons/10_Turtles/60_More_Turtle_Programs/30_More_Turtle_Programs.py b/lessons/10_Turtles/60_More_Turtle_Programs/30_More_Turtle_Programs.py new file mode 100644 index 00000000..088e6989 --- /dev/null +++ b/lessons/10_Turtles/60_More_Turtle_Programs/30_More_Turtle_Programs.py @@ -0,0 +1,7 @@ +""" +Copy the code from the previous lesson, 08a_More_Turtle_programs.ipynb, +from the section "Change the Background Image" + +Then change the code so that the turtle has a different image ( look in the 'images' +directory ) and moves to the corners of the screen in a square pattern. +""" \ No newline at end of file diff --git a/lessons/10_Turtles/60_More_Turtle_Programs/40_More_Turtle_Programs.py b/lessons/10_Turtles/60_More_Turtle_Programs/40_More_Turtle_Programs.py new file mode 100644 index 00000000..3aecd860 --- /dev/null +++ b/lessons/10_Turtles/60_More_Turtle_Programs/40_More_Turtle_Programs.py @@ -0,0 +1,13 @@ +""" +Copy the code from the previous lesson, 08a_More_Turtle_programs.ipynb, +from the section " Click on the Turtle" + +Then change the code so that the turtle has a different image ( look in the 'images' +directory ) and when you click on it, it moves to a random location on the screen. + +Use this code to get a random x and y location + + import random + x = random.randint(-300, 300) + y = random.randint(-300, 300) +""" \ No newline at end of file diff --git a/lessons/10_Turtles/60_More_Turtle_Programs/README.md b/lessons/10_Turtles/60_More_Turtle_Programs/README.md new file mode 100644 index 00000000..2d219144 --- /dev/null +++ b/lessons/10_Turtles/60_More_Turtle_Programs/README.md @@ -0,0 +1,9 @@ + +--- + +uid: I4bCPbWz + +--- + +# More Turtle Programs + diff --git a/lessons/10_Turtles/70_Projects/10_LeagueBot.py b/lessons/10_Turtles/70_Projects/10_LeagueBot.py new file mode 100644 index 00000000..64076070 --- /dev/null +++ b/lessons/10_Turtles/70_Projects/10_LeagueBot.py @@ -0,0 +1,20 @@ +""" +LeagueBot + +Write your own turtle program! Here is what your program should do + +1) Change the turtle image to 'leaguebot_bot.gif' +2) Change the turtle size to 10x10 +3) Change the turtle line color to 'blue' +4) Draw a hexagon using a loop and variables. +""" + +import turtle as turtle + +screen = turtle.Screen() +screen.setup(width=600, height=600) +screen.bgcolor('white') + +t = turtle.Turtle() + +... # Your Code Here \ No newline at end of file diff --git a/lessons/10_Turtles/70_Projects/20_Tash_Me.py b/lessons/10_Turtles/70_Projects/20_Tash_Me.py new file mode 100644 index 00000000..f65cebf5 --- /dev/null +++ b/lessons/10_Turtles/70_Projects/20_Tash_Me.py @@ -0,0 +1,13 @@ +""" +Tash Me + +Write a program that: +1) Loads an emoji image as the background +2) Make the turtle shape a moustache +3) Move the moustache to the right spot on the emoji + +Hint: See 08a_More Turtle Programs, section 'Change the Background Image' and +'Change the Turtle Shape' +""" + +... # Your code here \ No newline at end of file diff --git a/lessons/10_Turtles/70_Projects/30_Tash_Me_Click.py b/lessons/10_Turtles/70_Projects/30_Tash_Me_Click.py new file mode 100644 index 00000000..9a953a9a --- /dev/null +++ b/lessons/10_Turtles/70_Projects/30_Tash_Me_Click.py @@ -0,0 +1,8 @@ +# Tash Me with a Click +# +# Update your Tash Me program ( copy your old program here ) to put +# the moustache where you click on the screen. +# +# Hint: See 08a_More Turtle Programs, section 'Click on the Screen' + +... # Your code here \ No newline at end of file diff --git a/lessons/10_Turtles/70_Projects/40_Tash_Me_Twirl.py b/lessons/10_Turtles/70_Projects/40_Tash_Me_Twirl.py new file mode 100644 index 00000000..c86ca34f --- /dev/null +++ b/lessons/10_Turtles/70_Projects/40_Tash_Me_Twirl.py @@ -0,0 +1,10 @@ +""" +Tash Me with a Twirl + +Update your Tash Me Click program ( copy your old program here ) +so the moustache will twirl when you click on it. + +Hint: See 08a_More Turtle Programs, section 'Click on the Turtle' +""" + +... # Your code here \ No newline at end of file diff --git a/lessons/10_Turtles/70_Projects/README.md b/lessons/10_Turtles/70_Projects/README.md new file mode 100644 index 00000000..2e2965b0 --- /dev/null +++ b/lessons/10_Turtles/70_Projects/README.md @@ -0,0 +1,9 @@ + +--- + +uid: eo3RVnyt + +--- + +# Projects + diff --git a/lessons/10_Turtles/80_Introducting_Lists/10_Lists.ipynb b/lessons/10_Turtles/80_Introducting_Lists/10_Lists.ipynb new file mode 100644 index 00000000..7b52c860 --- /dev/null +++ b/lessons/10_Turtles/80_Introducting_Lists/10_Lists.ipynb @@ -0,0 +1,159 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# First Look at Lists\n", + "\n", + "One of the most important data structures in Python is the list. A list in Python is\n", + "like a grocery list: \n", + "\n", + "```\n", + "Things To Buy\n", + " - apples\n", + " - oranges\n", + " - bread \n", + " - milk\n", + "```\n", + "\n", + "But in Python we would write it like this: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "things_to_buy = [ 'apples','oranges','bread','milk']\n", + "things_to_buy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The brackets, `[` and `]` are most often used to mean that something is a list. \n", + "\n", + "There are a lot of neat things we can do with a list.\n", + "\n", + "First, you can get a specific item from a list, using the `[]` with a number inside. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "things_to_buy[1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Getting values out of a list like this is called \"indexing\".\n", + "\n", + "Like most programming languages, the first item in a list is 0, not 1, so if\n", + "you wanted to get `apples` from the list, you would write `things_to_buy[0]`\n", + "\n", + "Another important thing about lists is you can _iterate_ them, which means 'do\n", + "something repeatedly'. Here is how we would print out all of the items in the\n", + "list: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "things_to_buy = [ 'apples','oranges','bread','milk']\n", + "\n", + "for item in things_to_buy:\n", + " print(item)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Loops and lists could be very useful for our turtle programs. For instance, we could make a square with \n", + "a different color on each side: \n", + "\n", + "```python\n", + "import turtle\n", + "tina = turtle.Turtle()\n", + "tina.shape(\"turtle\")\n", + "\n", + "forward = 50\n", + "left = 90\n", + "colors = [ 'red', 'blue', 'black', 'orange']\n", + "\n", + "for color in colors:\n", + " tina.color(color)\n", + " tina.forward(forward)\n", + " tina.left(left)\n", + "```\n", + "\n", + "Or, we could change the angle that tina turns: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "# Note we are going to print out what Tina does, instead of actually run Tina in a window. \n", + "\n", + "forward = 50\n", + "\n", + "for left in [ 45, 60, 90, 45, -90, 60, 22 , -45, 90]:\n", + " print(f\"tina.forward({forward})\")\n", + " print(f\"tina.left({left})\")\n", + " print(\" \")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There is a lot more that a list can do, but this is all we currently need to know. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" + }, + "syllabus": { + "uid": "0KEhJUGe" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/10_Turtles/80_Introducting_Lists/20_Color_Lines.py b/lessons/10_Turtles/80_Introducting_Lists/20_Color_Lines.py new file mode 100644 index 00000000..790be08f --- /dev/null +++ b/lessons/10_Turtles/80_Introducting_Lists/20_Color_Lines.py @@ -0,0 +1,24 @@ +""" +Color Lines + +1) Finish the program to make Tina draw a square with each side being a different color. +""" + +import turtle # Tell Python we want to work with the turtle +turtle.setup(600,600,0,0) # Set the size of the window + +tina = turtle.Turtle() # Create a turtle named tina + +tina.shape('turtle') # Set the shape of the turtle to a turtle +tina.speed(2) # Make the turtle move as fast, but not too fast. + +colors = [ 'red', 'blue', 'black', 'orange'] # define a list of colors + +for color in colors: # loop through the colors + ... # Your code here + +# 2) Make another square, but put the colors in reverse order, using a negative index. + +... # Your code here + +turtle.exitonclick() # Close the window when we click on it \ No newline at end of file diff --git a/lessons/10_Turtles/80_Introducting_Lists/README.md b/lessons/10_Turtles/80_Introducting_Lists/README.md new file mode 100644 index 00000000..4e809e0b --- /dev/null +++ b/lessons/10_Turtles/80_Introducting_Lists/README.md @@ -0,0 +1,9 @@ + +--- + +uid: g4kLhJ2U + +--- + +# Introducting Lists + diff --git a/lessons/10_Turtles/90_Graphics_Projects/10_Flaming_Ninja_Star.py b/lessons/10_Turtles/90_Graphics_Projects/10_Flaming_Ninja_Star.py new file mode 100644 index 00000000..a657bff5 --- /dev/null +++ b/lessons/10_Turtles/90_Graphics_Projects/10_Flaming_Ninja_Star.py @@ -0,0 +1,61 @@ +"""Flaming Ninja Star + +This program already works; run it to see what it does. +Then change it to make it draw a different pattern. +""" + +import random +import turtle + + +# Returns a random color! +def getRandomColor(): + return "#%06X" % (random.randint(0, 0xFFFFFF)) + + +colors = ["red", "blue", "green", "yellow", "orange"] + + +def getNextColor(i): + return colors[i % len(colors)] + +turtle.setup(600,600,0,0) # Set the size of the window +window = turtle.Screen() + +baseSize = 200 # the size of the black part of the star +flameSize = 130 # the length of the flaming arms + +t = turtle.Turtle() + +t.shape("turtle") + +t.width(2) + +t.speed(0) + +for i in range(25): + t.pencolor(getRandomColor()) + + t.fillcolor(getRandomColor()) + + t.begin_fill() + + t.forward(64) + + t.left(40) + + t.forward(flameSize) + + t.right(170) + + t.forward(flameSize) + + t.right(62) + + t.forward(baseSize) + + t.end_fill() + +t.hideturtle() + +turtle.done() \ No newline at end of file diff --git a/lessons/10_Turtles/90_Graphics_Projects/20_Crazy_Spiral.py b/lessons/10_Turtles/90_Graphics_Projects/20_Crazy_Spiral.py new file mode 100644 index 00000000..dcf86c36 --- /dev/null +++ b/lessons/10_Turtles/90_Graphics_Projects/20_Crazy_Spiral.py @@ -0,0 +1,29 @@ +""" +Crazy Spiral + +Make your own crazy spiral with a pattern like +in 14_FLaming_Ninja_Star.py, but use what you've learned about loops +""" + +... # Copy code to make a turtle and set up the window + +t = ... # Create a turtle named t + +# 1) Complete make_a_shape() to make the turtle move in some pattern. +# For instance, you can make it go left 30 degrees, then forward 50 pixels, +# then right 60 degrees, then forward 100 pixels. Make any shape you like. + +def make_a_shape(t): + """Make a shape with turtle t. Make it go left or right or forward""" + ... + +# 2) Call make_a_shape() in a loop to make the turtle draw a spiral. +# For instance, you can call make_a_shape() 100 times to make a spiral with 100 shapes. +# The second ... in the for loop should be the number of shapes you want to make, +# for example 100, or it could use islice(), cycle(), or a list of numbers. + +num_shapes = ... + +for i in range(...): + make_a_shape(t) + t.right(360/num_shapes) \ No newline at end of file diff --git a/lessons/10_Turtles/90_Graphics_Projects/30_Pentagon_Crazy.py b/lessons/10_Turtles/90_Graphics_Projects/30_Pentagon_Crazy.py new file mode 100644 index 00000000..280bf6a3 --- /dev/null +++ b/lessons/10_Turtles/90_Graphics_Projects/30_Pentagon_Crazy.py @@ -0,0 +1,41 @@ +""" +Pentagon Crazy + +This program already works. Run it, then change it to make it draw a different pattern. +""" + +import random +import turtle + +def getRandomColor(): + return "#%06X" % (random.randint(0, 0xFFFFFF)) + +def getNextColor(i): + return colors[i % len(colors)] + +window = turtle.Screen() +window.bgcolor("black") +window.setup(width=600, height=600, startx=0, starty=0) + +colors = ("red", "blue", "green", "yellow", "orange") + +myTurtle = turtle.Turtle() +myTurtle.shape("turtle") +myTurtle.speed(0) +myTurtle.width(1) + +sides = 5 +angle = 360 / sides + +for i in range(360): + if i == 100: + myTurtle.width(2) + if i == 200: + myTurtle.width(3) + myTurtle.pencolor(getNextColor(i)) + myTurtle.forward(i) + myTurtle.right(angle + 1) + +myTurtle.hideturtle() + +turtle.done() \ No newline at end of file diff --git a/lessons/10_Turtles/90_Graphics_Projects/40_Turtle_Spiral.py b/lessons/10_Turtles/90_Graphics_Projects/40_Turtle_Spiral.py new file mode 100644 index 00000000..82c50051 --- /dev/null +++ b/lessons/10_Turtles/90_Graphics_Projects/40_Turtle_Spiral.py @@ -0,0 +1,47 @@ +"""Penta Spiral + +This program already works. See if you can change it to make it draw a different pattern. +""" + +import random +import turtle + +# Returns a random color! +def getRandomColor(): + return "#%06X" % (random.randint(0, 0xFFFFFF)) + +window = turtle.Screen() +window.bgcolor("white") + +# Make a new turtle +myTurtle = turtle.Turtle() + +# This code sets our shape to a turtle +myTurtle.shape("turtle") + +# Set your turtle's speed +myTurtle.speed(0) + +# Set your turtle's color +myTurtle.color("green") + +# Use a loop to repeat the code below 50 times +for i in range(50): + + # Set the turtle color to a random color + myTurtle.pencolor(getRandomColor()) + + # Move the turtle (5*i) pixels. 'i' is the loop variable + myTurtle.forward(5 * i) + + # Turn the turtle (360/7) degrees to the right + myTurtle.right(360 / 7 + i*5) + + # Change the turtle width to 'i' (the loop variable) + myTurtle.width(i) + + # Check the pattern against the picture in the recipe. If it matches, you are done! + +turtle.done() + +# Now check in your code! \ No newline at end of file diff --git a/lessons/10_Turtles/90_Graphics_Projects/README.md b/lessons/10_Turtles/90_Graphics_Projects/README.md new file mode 100644 index 00000000..e5780bb6 --- /dev/null +++ b/lessons/10_Turtles/90_Graphics_Projects/README.md @@ -0,0 +1,9 @@ + +--- + +uid: 3shr4ruR + +--- + +# Graphics Projects + diff --git a/lessons/10_Turtles/README.md b/lessons/10_Turtles/README.md new file mode 100644 index 00000000..58454632 --- /dev/null +++ b/lessons/10_Turtles/README.md @@ -0,0 +1,27 @@ +--- +uid: Io0hFJiW +--- + +# Introduction to Python with Turtle Graphics + +This first module of the Python course teaches the basic syntax of Python +and how commands string together to form program. It also lightly +addresses important concepts that we will consider in more detail later, +such as: + +* Variables +* Loops +* Functions +* Lists + + +# PCEP Alignment + +* PCEP-30-01 1.1 – Understand Fundamental Terms and Definitions + * Interpreting and the Interpreter, Compilation and the Compiler + * Lexis, Syntax, and Semantics +* PCEP-30-01 1.2 – Understand Python’s Logic and Structure + * Keywords + * Instructions + * Indentation + * Comments \ No newline at end of file diff --git a/lessons/10_Turtles/images/README.md b/lessons/10_Turtles/images/README.md new file mode 100644 index 00000000..68eadd46 --- /dev/null +++ b/lessons/10_Turtles/images/README.md @@ -0,0 +1,15 @@ + +Some images drawn by Philipp Lenssen in late 1990s. + + +``` + My website is outer-court.com . An appropriate link to the site and credit by + name would be appreciated in your projects. + + License: http://creativecommons.org/licenses/by/3.0/ + + For more info please see + http://blog.outer-court.com/archive/2006-08-08-n51.html + http://opengameart.org/content/700-sprites + +``` \ No newline at end of file diff --git a/lessons/10_Turtles/images/boy_yellow.gif b/lessons/10_Turtles/images/boy_yellow.gif new file mode 100644 index 00000000..67e60ca6 Binary files /dev/null and b/lessons/10_Turtles/images/boy_yellow.gif differ diff --git a/lessons/10_Turtles/images/emoji.png b/lessons/10_Turtles/images/emoji.png new file mode 100644 index 00000000..412eb9f1 Binary files /dev/null and b/lessons/10_Turtles/images/emoji.png differ diff --git a/lessons/10_Turtles/images/emoji2.png b/lessons/10_Turtles/images/emoji2.png new file mode 100644 index 00000000..dc6b8564 Binary files /dev/null and b/lessons/10_Turtles/images/emoji2.png differ diff --git a/lessons/10_Turtles/images/girl_blue.gif b/lessons/10_Turtles/images/girl_blue.gif new file mode 100644 index 00000000..449614a0 Binary files /dev/null and b/lessons/10_Turtles/images/girl_blue.gif differ diff --git a/lessons/10_Turtles/images/girl_red.gif b/lessons/10_Turtles/images/girl_red.gif new file mode 100644 index 00000000..a985d710 Binary files /dev/null and b/lessons/10_Turtles/images/girl_red.gif differ diff --git a/lessons/10_Turtles/images/leaguebot_bolt.gif b/lessons/10_Turtles/images/leaguebot_bolt.gif new file mode 100644 index 00000000..976d978a Binary files /dev/null and b/lessons/10_Turtles/images/leaguebot_bolt.gif differ diff --git a/lessons/10_Turtles/images/leaguebot_bolt.svg b/lessons/10_Turtles/images/leaguebot_bolt.svg new file mode 100644 index 00000000..a4ae183c --- /dev/null +++ b/lessons/10_Turtles/images/leaguebot_bolt.svg @@ -0,0 +1,80 @@ + + + + + + leaguebot_bolt + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lessons/10_Turtles/images/leaguebot_flag.gif b/lessons/10_Turtles/images/leaguebot_flag.gif new file mode 100644 index 00000000..c36b3302 Binary files /dev/null and b/lessons/10_Turtles/images/leaguebot_flag.gif differ diff --git a/lessons/10_Turtles/images/moustache1.gif b/lessons/10_Turtles/images/moustache1.gif new file mode 100644 index 00000000..5103517c Binary files /dev/null and b/lessons/10_Turtles/images/moustache1.gif differ diff --git a/lessons/10_Turtles/images/moustache2.gif b/lessons/10_Turtles/images/moustache2.gif new file mode 100644 index 00000000..4ee30ba4 Binary files /dev/null and b/lessons/10_Turtles/images/moustache2.gif differ diff --git a/lessons/10_Turtles/images/moustache3.gif b/lessons/10_Turtles/images/moustache3.gif new file mode 100644 index 00000000..8828dc0f Binary files /dev/null and b/lessons/10_Turtles/images/moustache3.gif differ diff --git a/lessons/10_Turtles/images/pikachu.gif b/lessons/10_Turtles/images/pikachu.gif new file mode 100644 index 00000000..a06c2123 Binary files /dev/null and b/lessons/10_Turtles/images/pikachu.gif differ diff --git a/lessons/10_Turtles/images/sanic_64.png b/lessons/10_Turtles/images/sanic_64.png new file mode 100644 index 00000000..230dbb45 Binary files /dev/null and b/lessons/10_Turtles/images/sanic_64.png differ diff --git a/lessons/10_Turtles/images/spiral.png b/lessons/10_Turtles/images/spiral.png new file mode 100644 index 00000000..146fd196 Binary files /dev/null and b/lessons/10_Turtles/images/spiral.png differ diff --git a/lessons/20_Types_and_Logic/10_Numbers_and_Strings.ipynb b/lessons/20_Types_and_Logic/10_Numbers_and_Strings.ipynb new file mode 100644 index 00000000..921b8bba --- /dev/null +++ b/lessons/20_Types_and_Logic/10_Numbers_and_Strings.ipynb @@ -0,0 +1,577 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Reminder about Notebooks\n", + "\n", + "Remember that this document is an executable notebook, and each \"paragraph\" is called a \"cell\". Here are some tips for cells: \n", + "\n", + "* Click in the cell to edit it. When the cell is editable, you will see a blue bar on the side and a blue outline around the cell.\n", + "* Click on the \"▶️\" in the upper left of a cell to run it. If it doesn't do anything, look at the top of the screen to select a kernel. \n", + "* or Hit SHIFT-ENTER to run a cell. You can also run a cell by hitting SHIFT-ENTER\n", + "* Some operations on a cell, like moving it up or down, require it to be in \"Command Mode\". Hit the Esc key to enter command mode. The blue side \n", + " bar will stay, but the blue outline will disappear. \n", + "* When a cell is active, there is a small menu in the upper right with more options. \n", + "\n", + "If you run a cell and it doesn't look like it is doing anything, look at the top of the Visual Studio window for a box that looks like: \n", + "\n", + "
\n", + "\n", + "If you see this, you will want to click on the \"Python Environments\" and then\n", + "select an entry for a Python interpreter. It might look like \" .venv (Python\n", + "3.11)\" or maybe \"★ Python 3.12\" or something like that. Select an interpreter\n", + "and then re-run the code. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Variables and Datatypes\n", + "\n", + "In the lessons with Tina the Turtle you learned about variables. In this section\n", + "we are going to explore variables in more detail. You've seen several \n", + "different ways for declaring and assigning to a variable, such as: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "\n", + "# Assign to some variables. \n", + "age = 14\n", + "bank_account = 159.99\n", + "name = \"John\"\n", + "colors = [\"red\", \"blue\", \"green\"]\n", + "\n", + "print(f\"Name: {name}, Age: {age}, Bank Account: {bank_account}, Colors: {colors}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Types\n", + "\n", + "While all of these variable assignments have the same form, the *type* of the variables are all different. We can find out \n", + "what the type of the variable is with the ``type()`` function." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "\n", + "print(\"Age : \", type(age))\n", + "print(\"Bank : \", type(bank_account))\n", + "print(\"Name : \", type(name))\n", + "print(\"Colors: \", type(colors))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These types look a bit cryptic. Here is an explanation: \n", + "\n", + "* `int` is an integer, a number with no fraction part, like '3' \n", + "* `float` is a \"floating point number\" which does have a fraction part, like '3.5'\n", + "* `str` is a string, like a name. \n", + "* `list` is a list. \n", + "\n", + "There are many other types in Python. Each variable has a type, and the type determines what the variable can do and how you use it. For instance, you can add two variables, but what it means to add variables depends on what the variable is. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# add type integers\n", + "\n", + "a = 10\n", + "b = 20\n", + "\n", + "print(\"a + b = \", a + b)\n", + "\n", + "# add '10' to '20 as strings\n", + "\n", + "a = \"10\"\n", + "b = \"20\"\n", + "\n", + "print(\"a + b = \", a + b) # Wait, what????" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When we add `10` and `20` as integers, we get `30`, as you'd expect. But if you add them as strings it just sticks them together! What if you add an integer to a string?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 10\n", + "b = \"20\"\n", + "print(\"a + b = \", a + b)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Oh, that did not work, you can't add an integer to a string. But ... you can convert one to the other and then add them. To convert the variables, we will use `int()` and `str()`. ( Hmmm, the conversion functions have the same name as the type they convert to!)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 10\n", + "b = \"20\"\n", + "\n", + "# Convert b to an integer, then add\n", + "\n", + "print( a + int(b))\n", + "\n", + "# Convert a to a string, then add\n", + "\n", + "print( str(a) + b)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Numbers\n", + "\n", + "\n", + "Numbers seem really easy in Python; you just write numbers as you'd expect ... but there\n", + "are two kinds: integers and floating point numbers. Floating point numbers have a decimal\n", + "and integers don't.\n", + "\n", + "And, there are actually many ways to write these numbers. We can write integers in different bases. Here are\n", + "four different ways to write the number `37`:\n", + "\n", + "* Decimal, base 10: 37\n", + "* Octal, base 8: 0o45\n", + "* Hexadecimal, base 16: 0x25\n", + "* Binary, base 2: 0b100101\n", + "\n", + "When we count, we normally use decimal, base 10, and you may remember that when we write \n", + "the number `237` that actually means:\n", + "\n", + "* 2 * 100 + ( where 100 is 10*10 or 10^2 )\n", + "* 3 * 10 +\n", + "* 7\n", + "\n", + "Octal, Hexadecimal and Binary work the same way, but using bases of 8, 16 or 2. So, \n", + "we can decompose these numbers as:\n", + "\n", + "* Decimal 37 = 37 = (3*10 + 7)\n", + "* Octal 37 = 0o45 = (4*8 + 5)\n", + "* Hexadecimal 37 = 0x25 = (2*16 + 5)\n", + "* Binary 37 = 0b100101 = (1*32 + 0*16 + 0*8 + 1)\n", + "\n", + "Different number bases can be a difficult topic, so if you would like some more\n", + "explanation, Khan Academy has a few videos about number systems. \n", + "\n", + "* [Decimal and Binary](https://youtu.be/ku4KOFQ-bB4?si=PC9lZA_ZdXBilgsY)\n", + "* [Hexadecimal](https://youtu.be/4EJay-6Bioo?si=vFOama4qPED81GZA)\n", + "\n", + "As a programmer, you will probably never use octal, but you'll occasionally use\n", + "hexadecimal and binary. \n", + "\n", + "If you want to create these numbers, you can use the conversion functions ``oct()``, ``hex()`` and ``bin()``: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Conversion functions\n", + "\n", + "print(oct(37))\n", + "print(hex(37))\n", + "print(bin(37))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But what if you want to convert a string to a number? In that case you can use ``int()`` and ``float()``.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# String to integer and float\n", + "\n", + "print('int', int('1305'))\n", + "print('int',float('1305.32'))\n", + "\n", + "# The int() function can also take a second argument, which is the base of the number to be converted.\n", + "# so we can convert all of the other bases\n", + "\n", + "print('octal',int('45', 8))\n", + "print('octal',int('0o45', 8))\n", + "\n", + "print('hex',int('25', 16))\n", + "print('hex',int('0x25', 16))\n", + "\n", + "print('binary', int('100101', 2))\n", + "print('binary', int('0b100101', 2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For really big numbers you can use scientific notation or '_' to separate\n", + "digits, like you would normally use commas. So, here are three ways to write 1\n", + "million:\n", + "\n", + "* 1000000 \n", + "* 1_000_000 \n", + "* 1e6\n", + "\n", + "In the last one, scientific notation, the 'e' basically means the number of zeros, so ``1e6`` means \n", + "`1 followed by 6 zeros` ( more correctly it means 1 * 10^6. ) \n", + "\n", + "\n", + "### Operators\n", + "\n", + "Here are a few of the math operators that you can use on numbers. You've\n", + "probably seen most of them, but there may be one or two surprises. \n", + "\n", + "| operator | description | example | result |\n", + "|----------|-------------|---------|--------|\n", + "| + | addition | 2 + 3 | 5 |\n", + "| - | subtraction | 5 - 2 | 3 |\n", + "| * | multiplication | 4 * 6 | 24 |\n", + "| / | division | 11 / 4 | 2.75 |\n", + "| // | floor division (**aka integer division**) | 11 // 4 | 2 |\n", + "| % | modulo (**remainder**) | 11 % 4 | 3 |\n", + "| ** | exponentiation (**power**) | 2 ** 3 | 8 |\n", + "\n", + "\n", + "The floor division operator, `//` divides the two numbers and then \n", + "cuts off the decimal part, so you always get an integer. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "\n", + "# Floor division\n", + "\n", + "# Regular division will result in a float\n", + "\n", + "print(10 / 3)\n", + "\n", + "# But floor division is always an integer\n", + "\n", + "print(10 // 3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "\n", + "The modulo operator returns the remainder after the division. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "\n", + "# Modulo Operator\n", + "\n", + "print(\"9 % 3 == \" , 9 % 3 )\n", + "print(\"10 % 3 == \" , 10 % 3 )\n", + "print(\"11 % 3 == \" , 11 % 3 )\n", + "print(\"12 % 3 == \" , 12 % 3 )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An interesting thing about `//` and `%` is that they are related to each other;\n", + "the two operators can \"take apart\" a number that you can put back with a simple\n", + "equation. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "\n", + "a = 11\n", + "b = 3\n", + "\n", + "m = a % b # Modulo\n", + "fd = a // b # Floor division\n", + "\n", + "print(f\"{a} % {b} == m == \", m)\n", + "print(f\"{a} // {b} == fd == \", a // b)\n", + "\n", + "print(\"fd * b + m == a == \", fd * b + m)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "\n", + "# Example of the Modulo Operator\n", + "\n", + "for i in range(12):\n", + " print(f\"{i}:i // 3 == {i // 3} %3 == {i % 3} | ({i} // 3 * 3) + ({i} % 3) == {i // 3 * 3 + i % 3}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that the modulo operator works like a clock: the result goes around to\n", + "the maximum number, then goes back to 0. \n", + "\n", + "The most important thing you will do with the modulo operator is check if a\n", + "number is evenly divisible by another number, in which case the modulo value is\n", + "0. So, 6 is evenly divisible by 3 because ``6 % 3 == 0``." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Test yourself\n", + "\n", + "Write a program that computes how old you are by subtracting the current year from your birthday, but you have to start\n", + "with those numbers as strings. Then print your age in decimal, hexadecimal, octal and binary. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test yourself\n", + "\n", + "current_year = '2024' # Change to the current year. \n", + "birth_year = '1999' # Change to your birth year\n", + "\n", + "age = ... # Calculate the age\n", + "\n", + "print(\"You are \", age, \" years old in decimal\")\n", + "\n", + "print(\"You are \", ..., \" years old in hexadecimal\")\n", + "... # Print the age in octal\n", + "... # Print the age in binary\n", + "... # Print the age modulo 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Write a program that starts with two variables:\n", + "\n", + "* `kids` the number of kids \n", + "* `candy_bars` the number of candy bars\n", + "\n", + "You can set those variable to anything you want. You program should calculate how\n", + "to evenly distribute candy bars to the kids. Print out how many candy bars each\n", + "kid gets, and how many are left over. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test yourself\n", + "\n", + "kids = ...\n", + "candy_bars = ...\n", + "\n", + "candy_per_kid = ... # Calculate the number of candy bars each kid gets\n", + "print(\"Each kid gets \", candy_per_kid, \" candy bars\")\n", + "\n", + "candy_left_over = ... # Calculate the number of candy bars left over\n", + "print(\"There are \", candy_left_over, \" candy bars left over\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "\n", + "# Things to do with Strings\n", + "\n", + "a = 'Hello' # Define with single quotes\n", + "b = \"World\" # Define with double quotes\n", + "\n", + "print(a + \" \" +b + '!') # Concatenate with + \n", + "\n", + "print(a * 3) # Repeat with *\n", + "\n", + "print(a[0]) # Indexing, get the first letter\n", + "print(a[-1]) # Indexing, get the last letter\n", + "\n", + "num = 1234\n", + "\n", + "print(str(num)+ \" \" + str(num)) # Convert to a string\n", + "\n", + "print(f\"Embed a variable |{num}| in a string\") # Interpolation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are also many string methods, such as upper(), lower(), replace(), and split(). You should \n", + "see the [Python Documentation](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str) to see all of them; here are just a few. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "\n", + "s = \"Hello World!\"\n", + "\n", + "print(s.lower()) # Lowercase\n", + "print(s.upper()) # Uppercase\n", + "print(s.title()) # Titlecase, capitalize the first letter of each word\n", + "\n", + "print(s.replace('World', 'Python')) # Replace\n", + "print(s.split()) # Split string at spaces\n", + "\n", + "print(s.startswith('Hello')) # Startswith, returns True\n", + "print(s.startswith('Bogon')) # Startswith, returns False\n", + "print(s.endswith('World!')) # Endswith\n", + "\n", + "s = \" Hello World! \"\n", + "print(s.strip()) # Remove leading and trailing spaces" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Test Yourself\n", + "\n", + "Write a program that has three variables, for \"hello\", your name, and a greeting\n", + "like \"how are you?\". Combine the variables with spaces between them into one\n", + "string, then capitalize each word and print out the result." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test Yourself\n", + "\n", + "hello = ... # Define a string for hello\n", + "name = ... # Your name\n", + "greet = ... # \n", + "\n", + "hello3 = ... # make your hello string repeat three times\n", + "s = ... # Concatenate hello3, name and greet\n", + "titled = ... # Make it title case\n", + "\n", + "print(titled) # Print the string" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Check In Your Code\n", + "\n", + "Don't forget to check in your code. You can review how to check in your code,\n", + "and how to restart your Codespace, in our [Code Check In Howto Guide.](https://curriculum.jointheleague.org/howto/checkin_restart.html)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + }, + "syllabus": { + "uid": "HXQZ0Iui" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/20_Types_and_Logic/20_Control_Flow.ipynb b/lessons/20_Types_and_Logic/20_Control_Flow.ipynb new file mode 100644 index 00000000..a9f38e5b --- /dev/null +++ b/lessons/20_Types_and_Logic/20_Control_Flow.ipynb @@ -0,0 +1,332 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Control Flow\n", + "\n", + "Programs don't work very well if they can't make decisions, and we can make decisions with `if` instructions. \n", + "You will see these types of instructions called \"conditionals\" or \"control flow\" or \"branching.\" Here is an example: \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Conditionals \n", + "\n", + "a = 10\n", + "\n", + "if a == 11:\n", + " print(\"a is 11\")\n", + "\n", + "if a == 10:\n", + " print(\"a is 10\")\n", + "\n", + "if a < 20:\n", + " print(\"a is less than 20\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the ``if`` statements above, it is important to understand what comes after the ``if``: an expression that evaluates to a boolean. \n", + "\n", + "* An 'expression' is a bit of code that when run is reduced to a value, like a string or an integer. \n", + "* 'Evaluates' means that the code is being run to determine its value. \n", + "* A 'Boolean' is a type of value that is either True or False. \n", + "\n", + "For instance, the code `5+3` is an expression that evaluates to `8`. Let's evaluate the conditional expressions in the code above: \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Evaluating boolean expressions. \n", + "print(\"a == 11:\", a == 11)\n", + "print(\"a == 10:\", a == 10)\n", + "print(\"a < 20:\", a < 20)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First thing to notice is that we use two equal signs for conditional\n", + "expressions! You use one to assign a variable, and two to check if things are\n", + "equal. So:\n", + "\n", + "* `a = 3` means \"Assign the value of 3 to a\"\n", + "* `a == 3` means \"evaluate to `True` is a equal to 3\"\n", + "\n", + "Don't forget! This is a very common error. \n", + "\n", + "\n", + "## Test Yourself\n", + "\n", + "Add code to determine if the statements in the comments are True or False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test Yourself\n", + "\n", + "a = 10\n", + "b = 15\n", + "c = '30'\n", + "s = 'hello world'\n", + "\n", + "# Is a equal to 10?\n", + "\n", + "print(a == 10)\n", + "\n", + "# Is b less than 20?\n", + "...\n", + "\n", + "# Is c equal to the *integer* 30?\n", + "\n", + "...\n", + "\n", + "# Is c equal to the *string* '30'?\n", + "\n", + "...\n", + "\n", + "# Is a equal to b minus 5?\n", + "\n", + "..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## And and Or\n", + "\n", + "What if you want to do something only if both `a` was equal to 10 and `b` was equal to 15? In that case, you can use the logical operators `and` & `or`. The `and` operator returns `True` only when both sides of the operator are `True`, whereas `or` returns `True` if either side is `True`. For example:\n", + "\n", + "```python \n", + "True and True == True\n", + "True and False == False\n", + "False and False == False\n", + "\n", + "True or True == True\n", + "True or False == True\n", + "False or False == False\n", + "```\n", + "\n", + "You'll probably never write code like the above (and you probably shouldn't anyway) ... but you might write:\n", + "\n", + "```python \n", + "if a == 5 and s.startswith('hello'):\n", + " print(\"yeah!\")\n", + "\n", + "# or \n", + "\n", + "if time > \"11:30\" and time < \"12:30\":\n", + " print(\"Lunch time!\")\n", + "\n", + "# or\n", + "\n", + "if time < \"07:00\" or time > \"22:00\":\n", + " print(\"I am asleep\")\n", + "```\n", + "\n", + "## Test Yourself" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test Yourself\n", + "\n", + "a = 10\n", + "b = 15\n", + "c = '30'\n", + "s = 'hello world'\n", + "\n", + "\n", + "# set a_is_10 to be true if a is equal to 10\n", + "\n", + "a_is_10 = (a == 10)\n", + "\n", + "# Set last_is_world to be true if the last world in s is 'world'\n", + "\n", + "last_is_world = ...\n", + "\n", + "# set last_is_hello to be true if the last world in s is 'hello'\n", + "\n", + "last_is_hello = ...\n", + "\n", + "# if a is 10 and the last word in s is 'world' print 'success'\n", + "\n", + "if ...:\n", + " print(...)\n", + "\n", + "\n", + "# If the integer value of c is 30 or b is evenly divisible by 5, print 'success'\n", + "\n", + "if ...:\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Else and Else if\n", + "\n", + "There is more that `If` statements can do. You can add additional clauses with `elif` and execute specific code if\n", + "none of the `if` or `elif` blocks are ``True``. For instance: \n", + "\n", + "```python \n", + "\n", + "# Example of if-else\n", + "\n", + "if maybe_its_true:\n", + " # do this if maybe_its_true == True\n", + " ...\n", + "else:\n", + " # do this if maybe_its_true == False\n", + " ...\n", + "\n", + "# Example of if-elif-else\n", + "\n", + "maybe_this = ... \n", + "maybe_that = ...\n", + "\n", + "if maybe_this:\n", + " # do this if maybe_this_ == True\n", + " ...\n", + "elif maybe_that:\n", + " # do this if maybe_this == False and maybe_that == True\n", + " ...\n", + "else:\n", + " # do this if maybe_this == False and maybe_that == False\n", + " \n", + "```\n", + "\n", + "## Test Yourself\n", + "\n", + "Write a program that sets a variable `fb` to a number, then write a conditional that\n", + "\n", + "* If the number is evenly divisible by 5, print 'fizz'\n", + "* If the number is evenly divisible by 3, print 'buzz'\n", + "* If it is divisible by neither, print the number\n", + "\n", + "Test your program with different values of `fb`. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test yourself\n", + "\n", + "fb = ...\n", + "\n", + "if ...:\n", + " print(...)\n", + "\n", + "elif ...:\n", + " ...\n", + " \n", + "else:\n", + " ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is a common way of using `if`/`elif`/`else` blocks, to break a continuous\n", + "value ( like the amount of water in a cup ) into categories. In this case, each\n", + "category is larger than the one before it, so the program will only return the\n", + "smallest category that is just larger than the limit. \n", + "\n", + "You might also use this method for converting an age into an age range. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def convert_ml_to_imperial(ml):\n", + " # Conversion values\n", + " teaspoon_ml = 4.92892\n", + " tablespoon_ml = 3 * teaspoon_ml\n", + " cup_ml = 16 * tablespoon_ml\n", + " pint_ml = 2 * cup_ml\n", + " quart_ml = 2 * pint_ml\n", + " gallon_ml = 4 * quart_ml\n", + "\n", + " if ml <= teaspoon_ml:\n", + " print(f\"The next larger measure is: Teaspoon ({teaspoon_ml} ml)\")\n", + " elif ml <= tablespoon_ml:\n", + " print(f\"The next larger measure is: Tablespoon ({tablespoon_ml:.4f} ml)\")\n", + " elif ml <= cup_ml:\n", + " print(f\"The next larger measure is: Cup ({cup_ml:.3f} ml)\")\n", + " elif ml <= pint_ml:\n", + " print(f\"The next larger measure is: Pint ({pint_ml:.3f} ml)\")\n", + " elif ml <= quart_ml:\n", + " print(f\"The next larger measure is: Quart ({quart_ml:.3f} ml)\")\n", + " elif ml <= gallon_ml:\n", + " print(f\"The next larger measure is: Gallon ({gallon_ml:.2f} ml)\")\n", + " else:\n", + " print(\"The amount exceeds a gallon!\")\n", + "\n", + "# Ask the user for the amount of water in milliliters\n", + "ml = float(input(\"Enter the amount of water in the cup (in ml): \"))\n", + "\n", + "# Call the function to get the Imperial measure\n", + "convert_ml_to_imperial(ml)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + }, + "syllabus": { + "uid": "g6JPkFUs" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/20_Types_and_Logic/30_My_Ages.py b/lessons/20_Types_and_Logic/30_My_Ages.py new file mode 100644 index 00000000..59128593 --- /dev/null +++ b/lessons/20_Types_and_Logic/30_My_Ages.py @@ -0,0 +1,46 @@ +""" +Am I Big Yet? + +Ask the user's age then use an if-elif-else statement to +tell the user what age groups the user is in. The groups are: + +0-2: Baby +3-5: Toddler +6-12: Child +13-19: Teen +20-64: Adult +65+: Senior + +Except, if the user is the same age as you, print "You are pretty awesome!" + +Here is how you ask the user's age in integer format. The first argument is +the title of the window, the second is the message to the user. + +age = simpledialog.askinteger("Your Age", "How old are you?") + +Or, you could ask the user for a float with simpledialog.askfloat() + +age = simpledialog.askfloat("Your Age", "How old are you?") + +Here is how you show the user a message window. The first parameter is the title of the window, +the second is the message to show the user. + +messagebox.showinfo('What you are', "You are a baby.") +""" + +from tkinter import messagebox, simpledialog, Tk # import required modules + +window = Tk() # Create a window object +window.withdraw() # Hide the window; we just want to see pop ups + +# Ask the user's age + +# Use if statements to determine the age group +# and create a message + +# Show the message to the user + +window.mainloop() # Keeps the window open + +# TODO: +# Try to write your program so you only need to use one messagebox.showinfo() function. \ No newline at end of file diff --git a/lessons/20_Types_and_Logic/40_Simple_Adder.py b/lessons/20_Types_and_Logic/40_Simple_Adder.py new file mode 100644 index 00000000..62cc665c --- /dev/null +++ b/lessons/20_Types_and_Logic/40_Simple_Adder.py @@ -0,0 +1,22 @@ +""" +Write a Python program that asks the user for two numbers. The program should +display the sum of the two numbers. + +In this program we will just give you the comments for what you need to do. Look +at the comments and the code snippets in the previous lessons, like +03_My_Ages.py, to figure out how to complete the program. +""" + +# Import the required modules + +# Create a window object + +# Hide the window, hint: use the withdraw method + +# Ask the user for the first number + +# Ask the user for the second number + +# Display the sum of the two numbers + +# Keep the window open \ No newline at end of file diff --git a/lessons/20_Types_and_Logic/50_Infuriating_Calculator.py b/lessons/20_Types_and_Logic/50_Infuriating_Calculator.py new file mode 100644 index 00000000..0a25a999 --- /dev/null +++ b/lessons/20_Types_and_Logic/50_Infuriating_Calculator.py @@ -0,0 +1,39 @@ +""" +Infuriating Calculator + +Let's write a calculator that's really hard to use, not because we want it to be +hard, but just because we haven't learned how to make it easy yet. + +Ask the user for three things: + +1. A number +2. A second number +3. A math operation (add, subtract, multiply, divide) +4. Use if-elif-else statements to provide the desired math operation on the + numbers and display the result. + +If the user enters an unknown operation, display an error message. ( use +messagebox.showerror() + +For the number, you can ask for a float or an integer with +simpledialog.askfloat() or simpledialog.askinteger(), and for the math operation +you can ask for a string with simpledialog.askstring(). +""" + +# Import the required modules + +# Create a window object + +# Hide the window, hint: use the withdraw method + +# Ask the user for the first number + +# Ask the user for the second number + +# Ask the user for the math operation + +# Use if-elif-else statements to provide the desired math operation on the numbers and display the result. + +# If the user enters an unknown operation, display an error message. ( use messagebox.showerror() + +# Keep the window open \ No newline at end of file diff --git a/lessons/20_Types_and_Logic/60_Code_Challenges.ipynb b/lessons/20_Types_and_Logic/60_Code_Challenges.ipynb new file mode 100644 index 00000000..54f6dec9 --- /dev/null +++ b/lessons/20_Types_and_Logic/60_Code_Challenges.ipynb @@ -0,0 +1,134 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "# Code Challenges\n", + "\n", + "Code challenge apps are a great way to continue to improve your skills. But\n", + "first ... go check in your code. You can review how to check in your code, and\n", + "how to restart your Codespace, in our \n", + "[Code Check In How To Guide.](https://curriculum.jointheleague.org/howto/checkin_restart.html)\n", + "\n", + "\n", + "## Hacker Rank\n", + "\n", + "[Hacker Rank](https://www.hackerrank.com/) is a website that provides a series\n", + "of programming challenges. The challenges are organized by skills and difficulty\n", + "level. The website provides a platform for users to practice their programming\n", + "skills and to compete with others. Hacker Rank also provides a series of\n", + "tutorials and practice problems to help users improve their programming skills.\n", + "\n", + "In the \"Hacker Rank\" notebooks like this, we will give you challenges from\n", + "Hacker rank. Each section will have one challenge, with a link to the Hacker\n", + "Rank challenge. To use that link, you will have to create a Hacker Rank Account.\n", + "If you do, you will be able to keep track of your progress with the challenges. \n", + "\n", + "*Important* When you create your Hacker Rank account *use your Github account*.\n", + "When you go to the sign up page, look for a button like this: \n", + "\n", + "\n", + "\n", + "Using Github will make it easier to sign up and login later. \n", + "\n", + "## Code Wars\n", + "\n", + "Another practice site we really like is [Code Wars](https://www.codewars.com/).\n", + "Where Hacker Rank is fairly professional looking, Code Wars is more like Rocket\n", + "League for coding. \n", + "\n", + "When you sign up for Code Wars, also be sure to sign up with Github. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Challenges\n", + "\n", + "## If Else\n", + "\n", + "[Solve this Challenge on Hacker Rank](https://www.hackerrank.com/challenges/py-if-else/problem?isFullScreen=true)\n", + "\n", + "\n", + "Given an integer $n$, perform the following conditional actions:\n", + "\n", + "- if $n$ is odd, print `weird`\n", + "- if $n$ is even and in the inclusive range of 2 to 5, print `not weird`\n", + "- if $n$ is even and in the inclusive range of 6 to 20, print `weird`\n", + "- if $n$ is even and greater than 20, print `not weird`\n", + "\n", + "Or solve the problem here:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Your solution here\n", + "\n", + "for n in [3, 5, 7, 11, 13, 17, 19, 23]:\n", + " ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Hello Johnny\n", + "\n", + "[Solve this Challenge on Code Wars](https://www.codewars.com/kata/55225023e1be1ec8bc000390/train/python)\n", + "\n", + "Jenny has written a function that returns a greeting for a user. However, she's\n", + "in love with Johnny, and would like to greet him slightly different. She added a\n", + "special case to her function, but she made a mistake.\n", + "\n", + "Can you help her?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + }, + "syllabus": { + "uid": "jJI6aomB" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/lessons/20_Types_and_Logic/README.md b/lessons/20_Types_and_Logic/README.md new file mode 100644 index 00000000..e6687815 --- /dev/null +++ b/lessons/20_Types_and_Logic/README.md @@ -0,0 +1,45 @@ +--- +uid: ryHvW6vk +--- + +# PCEP Alignment + +* PCEP-30-01 1.3 – Use and Understand Different Types of Literals and Numeral Systems + * Boolean, Integers, Floating-Point Numbers + * Scientific Notation + * Strings + * Binary, Octal, Decimal, and Hexadecimal Numeral Systems + * Variables + * Naming Conventions + +* PCEP-30-01 1.4 – Choose Operators and Data Types Adequate to the Problem + * Numeric Operators: `**` `*` `/` `%` `//` `+` `–` + * String Operators: `*` `+` + * Assignment and Shortcut Operators + +* PCEP-30-01 2.1 – Build Complex Expressions and Determine Data Type + * Unary and Binary Operators + * Priorities and Binding + * Bitwise Operators: `~` `&` `^` `|` `<<` `>>` + * Boolean Operators: `not`, `and`, `or` + * Boolean Expressions + * Relational Operators ( `==` `!=` `>` `>=` `<` `<=` ) + * The Accuracy of Floating-Point Numbers + +* PCEP-30-01 2.2 – Perform Complex Input/Output Operations + * The `print()` and `input()` Functions + * The `sep=` and `end=` Keyword Parameters + * The `int()`, `float()`, `str()`, and `len()` Functions + * Type Casting + +* PCEP-30-01 2.3 – Operate on Strings + * Constructing, Assigning, Indexing, and Slicing Strings + * Immutability + * Quotes and Apostrophes Inside Strings + * Escaping Using the `\` Character + * Basic String Functions and Methods + +* PCEP-30-01 3.1 – Make Decisions and Branch the Flow with the `if` Instruction + * Conditional Statements: `if`, `if-else`, `if-elif`, `if-elif-else` + * Multiple Conditional Statements + * Nesting Conditional Statements \ No newline at end of file diff --git a/lessons/20_Types_and_Logic/__init__.py b/lessons/20_Types_and_Logic/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/lessons/20_Types_and_Logic/__init__.py @@ -0,0 +1 @@ + diff --git a/lessons/20_Types_and_Logic/lib/03_badgers_tk.py b/lessons/20_Types_and_Logic/lib/03_badgers_tk.py new file mode 100644 index 00000000..d5097bca --- /dev/null +++ b/lessons/20_Types_and_Logic/lib/03_badgers_tk.py @@ -0,0 +1,35 @@ +""" + +* If the number is evenly divisible by 5, print 'fizz' +* If the number is evenly divisible by 3, print 'buzz' +* If it is divisible by neither, print the number + + +""" + + +import jtl_lib # type: ignore +jtl_lib.add_path() +from lib.badgers import FizzBuzzer + +# Make fizzbuzz function work with graphics +# Inside the fizzbuzz function: +# return 'snake' to display the snake image, +# return 'badger' to display the badger image, and +# return 'mushroom' to display the mushroom image. +# return a number to display the number in black text. +# If you return anything else it will display in red. + +# You can change the image files in lib/images to anything you like, but they have to be .gif +# and have the names snake.gif, badger.gif, and mushroom.gif + + +def fizzbuzz(number): + + # Put your fizzbuz code here. + + return 'mushroom' # Always show a snake + + +fb = FizzBuzzer(fizzbuzz) +fb.run() diff --git a/lessons/20_Types_and_Logic/lib/__init__.py b/lessons/20_Types_and_Logic/lib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/lessons/20_Types_and_Logic/lib/badgers.py b/lessons/20_Types_and_Logic/lib/badgers.py new file mode 100644 index 00000000..e60cf3ae --- /dev/null +++ b/lessons/20_Types_and_Logic/lib/badgers.py @@ -0,0 +1,75 @@ +import tkinter as tk +from tkinter import PhotoImage +from pathlib import Path + +class FizzBuzzer(): + + """Run a user defined function on a sequence of numbers and display the result in a Tkinter window""" + + def __init__(self): + self.current_number = 0 + + + + # Function to update the display based on the current number + def update_display(self): + + result = self.cb(self.current_number) + + def isnumber(x): + try: + int(x) + return True + except: + return False + + if result == 'snake': + self.display_label.config(image=self.snake_img) + self.display_label.image = self.snake_img + elif result == 'badger': + self.display_label.config(image=self.badger_img) + self.display_label.image = self.badger_img + elif result == 'mushroom': + self.display_label.config(image=self.both_img) + self.display_label.image = self.both_img + elif not isnumber(result): + self.display_label.config(text=result, image='', fg='red') + else: + self.display_label.config(text=result, image='', fg='black') + + self.current_number+= 1 + + def __init__(self, cb=None): + + self.cb=cb + + # Initialize the Tkinter window + self.root = tk.Tk() + self.root.title("FizzBuzz with Tkinter") + + self.root.geometry("300x300") + + # Load images + image_dir = Path(__file__).parent / 'images' + + + self.snake_img = PhotoImage(file=image_dir/"snake.gif") + self.badger_img = PhotoImage(file=image_dir/"badger.gif") + self.both_img = PhotoImage(file=image_dir/"mushroom.gif") # Create a combined image for both + + # Create label to display the result + self.display_label = tk.Label(self.root, font=("Helvetica", 48)) + + # Create button to update the display + next_button = tk.Button(self.root, text="Next", command=self.update_display, font=("Helvetica", 24)) + + # Configure the display label to be at the top + self.display_label.pack(side=tk.TOP) + + # Configure the next button to be at the bottom + next_button.pack(side=tk.BOTTOM) + + self.current_number = 1 + + def run(self): + self.root.mainloop() \ No newline at end of file diff --git a/lessons/20_Types_and_Logic/lib/images/badger.gif b/lessons/20_Types_and_Logic/lib/images/badger.gif new file mode 100644 index 00000000..bd3b68c5 Binary files /dev/null and b/lessons/20_Types_and_Logic/lib/images/badger.gif differ diff --git a/lessons/20_Types_and_Logic/lib/images/mushroom.gif b/lessons/20_Types_and_Logic/lib/images/mushroom.gif new file mode 100644 index 00000000..9b8447d1 Binary files /dev/null and b/lessons/20_Types_and_Logic/lib/images/mushroom.gif differ diff --git a/lessons/20_Types_and_Logic/lib/images/snake.gif b/lessons/20_Types_and_Logic/lib/images/snake.gif new file mode 100644 index 00000000..80f23eca Binary files /dev/null and b/lessons/20_Types_and_Logic/lib/images/snake.gif differ diff --git a/lessons/30_Loops/010_Iteration.ipynb b/lessons/30_Loops/010_Iteration.ipynb new file mode 100644 index 00000000..b14d9644 --- /dev/null +++ b/lessons/30_Loops/010_Iteration.ipynb @@ -0,0 +1,112 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Loops and Iteration\n", + "\n", + "We've already used loops a lot. They look like this: \n", + "\n", + "```python \n", + "for i in range(10):\n", + " print(i)\n", + "```\n", + "\n", + "Like ``if`` statements, loops have parts that we can understand individually.\n", + "All of the loops start with ``for``, then have a variable name, then have\n", + "``in``. The last part is called an \"iterable\". \n", + "\n", + "So, the form of the loop line is always:\n", + "\n", + "```\n", + " for in :\n", + "```\n", + "\n", + "We call it an \"iterable\" because ... we can iterate it, and \"iterate\" just\n", + "means \"take one thing after another\".\n", + "\n", + "Here are some things that are iterable:\n", + "\n", + "* a list: ['a','b','c','d']\n", + "* a tuple: (1,2,3,4,5)\n", + "* a string: \"hello world\"\n", + "* range: range(10)\n", + "* many others!\n", + "\n", + "You can put any of those things into a loop and get one part of them at a time. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "# Iterate over range()\n", + "\n", + "for i in range(5):\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Iterate a list\n", + "for i in ['a','b','c','d']:\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Iterate over a string\n", + "for c in \"Hello World!\":\n", + " print(c)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the next lessons we'll learn about each of these iterable types. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + }, + "syllabus": { + "uid": "ITpqcvxv" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/30_Loops/020_Loops_with_Range.ipynb b/lessons/30_Loops/020_Loops_with_Range.ipynb new file mode 100644 index 00000000..b72e68ed --- /dev/null +++ b/lessons/30_Loops/020_Loops_with_Range.ipynb @@ -0,0 +1,173 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The Range Object\n", + "\n", + "We've used `range()` a lot so far, so let's finally learn all of the details about it. \n", + "\n", + "As we've seen, `range()` is a way of creating a series of numbers:\n", + "\n", + "```python\n", + "for i in range(10):\n", + " print(i)\n", + "```\n", + "\n", + "But, `range()` doesn't actually *have* the number inside of it. It just creates them. For instance, \n", + "see what happens if we print it, or ask for its type:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "\n", + "a = range(10)\n", + "\n", + "print(type(a))\n", + "print(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Range doesn't store numbers because if you had a really big range, like `range(1_000_000_000_000)` you'd run out of memory. \n", + "\n", + "However, there is a way to get the numbers inside of it: convert it to a list: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(list(range(10)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will explain more about `list()` later, for now we will just use it to find out what numbers `range()` is producing. \n", + "\n", + "The `range()` actually can have one, two or three arguments. Here are the options: \n", + "\n", + "* `range(end)`: produces numbers from 0 to `end`\n", + "* `range(start, end)`: produces numbers from `start` to `end`\n", + "* `range(start, end, skip)`: produces numbers from `start` to `end`, skipping by `skip`\n", + "\n", + "So, here is how we can create odd numbers from 101 to 120:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "list(range(101, 120, 2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What `range(101, 120, 2)` means is \"Start at 101 and skip numbers by 2 until 120`\n", + "\n", + "Notice that ``range()`` does not include the number you put at the end; it stops one before it. There is a good reason for this, but we'll have to explain later. \n", + "\n", + "## Test Yourself\n", + "\n", + "Print out all of the odd years between the year you were born and today." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test yourself\n", + "\n", + "..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Badgers!\n", + "\n", + "[These Badgers](https://youtu.be/pzagBTcYsYQ?si=xr4QQ7ZkZBGow2j1) really like a program called Fizz Buzz, but they want their own version\n", + "\n", + "The normal rules for FizzBuzz are: \n", + "\n", + " Write a function to list the integers from 1 to 30, but for every multiple of\n", + " 3, write “Fizz”, and for every multiple of 5, write “Buzz”. For numbers which\n", + " are multiples of both 3 and 5, it should write “FizzBuzz”; for every other\n", + " number, it should print the number unchanged.\n", + "\n", + "Instead, here are the Badger rules: \n", + "\n", + "For the numbers from 1 to 30:\n", + "\n", + "* If the number is evenly divisible by 5, print '🦡 badger'\n", + "* If the number is evenly divisible by 3, print '🍄 mushroom'\n", + "* If the number is evenly divisible by both 3 and 5, print '🐍 snake!'\n", + "* If it is divisible by neither, print the number.\n", + "\n", + "Bonus: write the program without using the ``or`` operator." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Badgers!\n", + "\n", + "for i in range(1, 31):\n", + " ..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + }, + "syllabus": { + "uid": "WcGpR3Xg" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/30_Loops/030_Lists.ipynb b/lessons/30_Loops/030_Lists.ipynb new file mode 100644 index 00000000..62244960 --- /dev/null +++ b/lessons/30_Loops/030_Lists.ipynb @@ -0,0 +1,428 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "5a4acb70", + "metadata": {}, + "source": [ + "# First Look at Lists\n", + "\n", + "A list in Python is a lot like the lists that you already know about, like a grocery list:\n", + "\n", + "```\n", + "Things To Buy\n", + " - apples\n", + " - oranges\n", + " - bread \n", + " - milk\n", + "```\n", + "\n", + "But in Python we would write it like this: \n", + "\n", + "```python \n", + "things_to_buy = [ 'apples','oranges','bread','milk']\n", + "```\n", + "\n", + "The brackets, `[` and `]` are most often used to mean that something is a list. \n", + "\n", + "There are a lot of neat things we can do with a list.\n", + "\n", + "First, you can get a specific item from a list, using the `[]` with a number inside. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9280847b", + "metadata": { + "lines_to_next_cell": 0 + }, + "outputs": [], + "source": [ + "# Indexing a list\n", + "\n", + "things_to_buy = [ 'apples','oranges','bread','milk']\n", + "\n", + "a = things_to_buy[1]\n", + "print(a)\n", + "\n", + "# Try changing the number in the [] and see what happens. " + ] + }, + { + "cell_type": "markdown", + "id": "c07ad6f5", + "metadata": {}, + "source": [ + "\n", + "Getting values out of a list like this is called \"indexing\".\n", + "\n", + "\n", + "Like most programming languages, the first item in a list is 0, not 1, so if\n", + "you wanted to get `apples` from the list, you would write `things_to_get[0]`\n", + "\n", + "Another important thing about lists is you can _iterate_ them, which means 'do\n", + "something repeatedly'. Here is how we would print out all of the items in the\n", + "list: \n" + ] + }, + { + "cell_type": "markdown", + "id": "2b5a515a", + "metadata": { + "lines_to_next_cell": 2 + }, + "source": [ + "## Using Lists\n", + "\n", + "Loops and lists could be very useful for our turtle programs. For instance, we could make a square with \n", + "a different color on each side: \n", + "\n", + "```python\n", + "import turtle\n", + "tina = turtle.Turtle()\n", + "tina.shape(\"turtle\")\n", + "\n", + "forward = 50\n", + "left = 90\n", + "colors = [ 'red', 'blue', 'black', 'orange']\n", + "\n", + "for color in colors:\n", + " tina.color(color)\n", + " tina.forward(forward)\n", + " tina.left(left)\n", + "```\n", + "\n", + "Or, we could change the angle that tina turns: \n", + "\n", + "```python\n", + "import turtle\n", + "tina = turtle.Turtle()\n", + "tina.shape(\"turtle\")\n", + "\n", + "forward = 50\n", + "\n", + "for left in [ 45, 60, 90, 45, -90, 60, 22 , -45, 90]:\n", + " tina.forward(forward)\n", + " tina.left(left)\n", + "```\n", + "\n", + "Here is a way that we could change two variables at once, using array indexes:\n", + "\n", + "```python\n", + "import turtle\n", + "tina = turtle.Turtle()\n", + "tina.shape(\"turtle\")\n", + "\n", + "forward = 50\n", + "lefts = [ 45, -60, 90, 45, -90, 60, 22 , -45 ]\n", + "colors = [ 'red', 'blue', 'black', 'orange', 'red', 'blue', 'black', 'orange']\n", + "\n", + "for i in range(8):\n", + " left = lefts[i]\n", + " color = colors[i]\n", + "\n", + " tina.color(color)\n", + " tina.forward(forward)\n", + " tina.left(left)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "183089f2", + "metadata": { + "lines_to_next_cell": 2, + "title": "[python]" + }, + "outputs": [], + "source": [ + "things_to_buy = [ 'apples','oranges','bread','milk']\n", + " \n", + "for item in things_to_buy:\n", + " print(item)" + ] + }, + { + "cell_type": "markdown", + "id": "bc85d21a", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "# Iterating over Iterables\n", + "\n", + "Here is the first simple list that you learned about earlier. \n", + "\n", + "```python \n", + "things_to_buy = [ 'apples','oranges','bread','milk']\n", + "```\n", + "\n", + "This variable, `things_to_buy` is interesting, because it is a list of\n", + "strings, but the strings are also a list, a list of letters. And in Python, \n", + "lists and strings are a lot a like. So, let's learn more about them both. \n", + "\n", + "Both lists and strings are \"iterables\". Iteration means taking things one at a\n", + "time, and \"iterating\" a list means that we will get the first thing in the\n", + "list, then the second, and on, until there is nothing left in the list. We have\n", + "seen iteration before, with loops. Here are two loops, \n", + "one iterating over a list, and another iterating over a string. \n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "15a2f38b", + "metadata": { + "title": "[python]" + }, + "outputs": [], + "source": [ + "things_to_buy = [ 'apples','oranges','bread','milk']\n", + " \n", + "print(\"Things to buy:\")\n", + "\n", + "for things in things_to_buy:\n", + " print(things)\n", + " \n", + "print()\n", + "for i in 'Hello World':\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "id": "65625cd0", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "## Iterables\n", + "\n", + "The for loop, which looks like `for in ` works by taking\n", + "each one of the things in the iterable, assigning it to the variable, then\n", + "running the code in the body of the loop. \n", + "\n", + "But, then you wonder, what does the code we first used for loops do? The one\n", + "with `range()` in it?\n", + "\n", + "Well, `range()` is an iterable! But it isn't a string or a list. It doesn't\n", + "have anything in it. It just gives you the next number. And as we learned\n", + "earlier, we can turn it into a list that does have things in it. Here is how: \n", + "\n", + "```python\n", + "# Turn a range() into a list:\n", + "\n", + "l = list(range(5, 10))\n", + "```\n", + "\n", + "When you put something inside `list()`, list will try to iterate the thing, and\n", + "then take each item and put it into a list. A string, like 'Hello World' is not\n", + "a list, but we can turn it into a list. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d63d5efe", + "metadata": {}, + "outputs": [], + "source": [ + "# Turn a string into a list:\n", + "\n", + "l = list(\"Hello World!\")\n", + "print(l)\n", + "\n", + "# That code above works the same as this code below:\n", + "l = list()\n", + "for c in \"Hello World!\":\n", + " l.append(c) # Adding to a list, more on this later\n", + "\n", + "print(l)" + ] + }, + { + "cell_type": "markdown", + "id": "d450eafd", + "metadata": {}, + "source": [ + "There is another way to turn a string into a list, by breaking the string at a\n", + "specific character using the `.split()` method." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f82ddae", + "metadata": {}, + "outputs": [], + "source": [ + "# split a string at spaces, the default\n", + "s = 'One Two Three Four'\n", + "l = s.split()\n", + "print(l)\n", + "\n", + "# split a string at the comma character\n", + "s = 'One,Two,Three,Four'\n", + "l = s.split(',')\n", + "print(l)" + ] + }, + { + "cell_type": "markdown", + "id": "9f66003c", + "metadata": {}, + "source": [ + "We'll learn more about how to work with lists later; right now we just want to\n", + "show that it is an easy way to make a list. \n", + "\n", + "## Sorting\n", + "\n", + "Sorting, putting a list of items into a predictable order, is one of the most common\n", + "tasks in a program, and like most other things, there is more than one way to do\n", + "it. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7bd259e4", + "metadata": {}, + "outputs": [], + "source": [ + "# Run me!\n", + "l = list('adefibhgc')\n", + "l.sort() # This sorts the list in place\n", + "print(l)\n", + "print()\n", + "\n", + "l = list('adefibhgc')\n", + "sl = sorted(l) # This creates a new list & doesn't change the original\n", + "print(sl)" + ] + }, + { + "cell_type": "markdown", + "id": "0578ffed", + "metadata": {}, + "source": [ + "\n", + "## Adding To Lists\n", + "\n", + "You can add items to lists with `.append()`, and concatenate lists ( put them\n", + "together) with `+`:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6550d5f", + "metadata": { + "title": "[python]" + }, + "outputs": [], + "source": [ + "l = []\n", + "\n", + "# Add to the list using append\n", + "l.append('item 1')\n", + "l.append('item 2')\n", + "l.append('item 3')\n", + "\n", + "# You can also use = with an empty list to create a new list\n", + "l = l + ['item 4', 'item 5']\n", + "\n", + "print(l)" + ] + }, + { + "cell_type": "markdown", + "id": "ee522118", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "\n", + "Try adding more items to the list!\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17a599ca", + "metadata": { + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Try adding more items to the list l\n" + ] + }, + { + "cell_type": "markdown", + "id": "c8f4a193", + "metadata": {}, + "source": [ + "## Test Yourself \n", + "\n", + "Show Us Your Lists!\n", + "\n", + "Now, you can write a program. Here is what your program should do. \n", + "\n", + "* Start with a string that has friend names, with spaces between the friend names, like\n", + "this, but with real names: `'foo bar baz'`. Split the list into a string.\n", + "* Ask the user for new friend names three times, and add those names to the list, using the `input()` function.\n", + "* Sort the list\n", + "* Print out each name on a seperate line. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c51bbf8", + "metadata": { + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Test yourself\n", + "\n", + "# Here is how to get a name from the user.\n", + "# name = input(\"What is your friend's name? \")\n", + "# Look at the ^^^^ top of the window ^^^ for the prompt\n", + "\n" + ] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "title,-all", + "main_language": "python", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + }, + "syllabus": { + "uid": "7zsKa84X" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/lessons/30_Loops/040_Crazy_Tina.py b/lessons/30_Loops/040_Crazy_Tina.py new file mode 100644 index 00000000..0ca78c00 --- /dev/null +++ b/lessons/30_Loops/040_Crazy_Tina.py @@ -0,0 +1,35 @@ +""" +Create a program that will draw a crazy pattern using the turtle. + +Create lists for the path that Tina will take, the angles +she will turn, and the colors she will use. The access those +lists to draw the pattern. + +hint: all of your lists should have the same number of elements. +Review the ' Using Lists' section of the previous lesson if you need +more help +""" + +import turtle # Tell Python we want to work with the turtle +turtle.setup(600,600,0,0) # Set the size of the window + +tina = turtle.Turtle() # Create a turtle named tina + +tina.shape('turtle') # Set the shape of the turtle to a turtle +tina.speed(2) # Make the turtle move as fast, but not too fast. + +forwards = [ ... ] +lefts = [ ... ] +colors = [ ... ] + +for i in range(8): + + forward = ... + left = ... + color = ... + + tina.color(color) + tina.forward(forward) + tina.left(left) + +turtle.exitonclick() \ No newline at end of file diff --git a/lessons/30_Loops/050_Tuples.ipynb b/lessons/30_Loops/050_Tuples.ipynb new file mode 100644 index 00000000..d3888cd1 --- /dev/null +++ b/lessons/30_Loops/050_Tuples.ipynb @@ -0,0 +1,110 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tuples — Lists You Can't Change\n", + "\n", + "Tuples are a kind of sequence and collection, like a list, with one really important difference: they can't be changed, they are \"immutable.\" What's the point of not being able to change them? Well, they are actually very useful, so let's learn about them. \n", + "\n", + "You can create a tuple in a similar way to creating a list, but using `()` instead of `[]`\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Tuples and Lists\n", + "\n", + "l = [1, 2, 3, 4, 5] # List\n", + "\n", + "print(l)\n", + "\n", + "t = (1, 2, 3, 4, 5) # Tuple\n", + "\n", + "print(t)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One difference from a list is that when creating a tuple, there must be a comma\n", + "inside the parentheses, so if you have only one item, you have to follow it with\n", + "a comma, or it won't be a tuple." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "l = [1] # List\n", + "t = (1,) # Tuple\n", + "nt = (1) # Not a tuple\n", + "\n", + "print('l',l,type(l))\n", + "print('t',t,type(t))\n", + "print('nt',nt,type(nt))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are a lot of cases where you want to make a sequence that you can iterate over, but you don't need to add or remove items from the collection. Because tuples can't be changed, they can be optimized to be fast and small in ways that lists cannot be optimized. \n", + "\n", + "You can do a lot of the same things with tuples that you can do with lists, using the same syntax. For instance, indexing and slicing works the same way. \n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "t = (1, 2, 3, 4, 5) \n", + "\n", + "print(t[0]) # Accessing elements in a tuple\n", + "print(t[2:4]) # Slicing a tuple" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + }, + "syllabus": { + "uid": "9zTQza2e" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/30_Loops/060_Indexing_and_Slicing.ipynb b/lessons/30_Loops/060_Indexing_and_Slicing.ipynb new file mode 100644 index 00000000..253f052d --- /dev/null +++ b/lessons/30_Loops/060_Indexing_and_Slicing.ipynb @@ -0,0 +1,177 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Indexing and Slicing\n", + "\n", + "Because lists and strings are a sequence of things, you can do some interesting\n", + "things with them: you can get a specific item from the list, or you can get\n", + "a range of items. \n", + "\n", + "# Indexing\n", + "\n", + "Indexing is when you get a single item from a list or string by its position (index)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Indexing ( Run Me! )\n", + "\n", + "colors = [ 'red', 'blue', 'black', 'orange'] # define a list of colors\n", + "\n", + "print(colors[0]) # print the first item\n", + "print(colors[1]) # print the second item \n", + "\n", + "print(colors[-1]) # print the last item. Negative numbers are counted from the end" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Slicing\n", + "\n", + "A \"slice\" is a portion of a list, starting at one list item and ending with another. A slice is\n", + "defined by numbers in side brackets after a list. There are many forms, but they all follow the \n", + "pattern of `[start:stop:skip]` where any of those can be left out. \n", + "\n", + "Here are some examples of slicing:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Slicing lists (Run Me!)\n", + "\n", + "colors = [ 'red', 'blue', 'black', 'orange'] # define a list of colors\n", + "\n", + "print('[1:3]', colors[1:3]) # print the second to third items, but not including the third item\n", + "print('[:2]', colors[:2]) # print the first two items. Nothing before the ':' means 'from the start'\n", + "print('[2:]', colors[2:]) # print the third and subsequent items. Nothing after the ':' means 'to the end'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So, some of patterns you can use are: \n", + "\n", + "| Syntax | Description |\n", + "|--------------------|-----------------------------------------------|\n", + "| `l[start:stop]` | from `start` to `stop` |\n", + "| `l[start:stop:skip]` | from `start` to `stop`, skipping every `skip` |\n", + "| `l[start:]` | from `start` to the last |\n", + "| `l[:end]` | from the first to `end` |\n", + "| `l[::skip]` | from the first to the last, skipping by `skip` |\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also use negative numbers in slicing, which means \"from the end\"." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Slicing with negative ( Run me!)\n", + "\n", + "nums = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", + "\n", + "print('[-3:]', nums[-3:]) # print the last three items\n", + "print('[:-3]', nums[:-3]) # print all but the last three items\n", + "print('[-6:-3]', nums[-6:-3]) # print the fourth to sixth items, but not including the sixth item\n", + "\n", + "# And we can mix negative and positives\n", + "\n", + "print('[2:-2]', nums[2:-2]) # print the third to the third last items, but not including the third last item\n", + "print('[-6:8]', nums[-6:8]) # print the fourth to the eighth items, but not including the eighth item\n", + "\n", + "# However, the most important use of negative indexes is to get the last item,\n", + "# or the last few items\n", + "\n", + "print('[-1]', nums[-1]) # print the last item\n", + "print('[-3:]', nums[-3:]) # print the last three items" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Skipping can also be positive or negative. A negative skip means to reverse the list." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Skipping items\n", + "\n", + "nums = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", + "\n", + "print('[::2]', nums[::2]) # print every second item\n", + "print('[1::2]', nums[1::2]) # print every second item starting from the second item\n", + "\n", + "# This third argument can also be negative, which means to go backwards\n", + "# This is a common way to reverse a list\n", + "\n", + "print('[::-1]', nums[::-1]) # print the list in reverse order. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The most frequent use of skip is to reverse the list, using:\n", + "\n", + "```python \n", + "l[::-1]\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.6" + }, + "syllabus": { + "uid": "P27f2L8k" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/30_Loops/070_List_Story.py b/lessons/30_Loops/070_List_Story.py new file mode 100644 index 00000000..85d9ece2 --- /dev/null +++ b/lessons/30_Loops/070_List_Story.py @@ -0,0 +1,16 @@ +""" +Use the words in the list to create a story. + +Use indexing to get words from the list, then +append them to the story +""" + +words = ['Once', '👦', 'upon', '🐕', 'park', 'met', 'with', 'a', 'the', + 'time', 'to', 'who', '🐈', '👧', 'and', 'went', 'had', 'play', '⚽.', 'they'] + +story = [] + +# Create a story using the words in the list + +# Display the story to the user +print(' '.join(story)) \ No newline at end of file diff --git a/lessons/30_Loops/080_Strings.ipynb b/lessons/30_Loops/080_Strings.ipynb new file mode 100644 index 00000000..9eea876d --- /dev/null +++ b/lessons/30_Loops/080_Strings.ipynb @@ -0,0 +1,487 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Strings\n", + "\n", + "We've already seen strings, so let's take some time to understand them better. Here is a really basic string\n", + "assignment:\n", + "\n", + "```python \n", + "message = \"Hello World!\"\n", + "```\n", + "\n", + "You can create strings with different kinds of quotes. These are all basically the same, but each has a slightly different purpose: \n", + "\n", + "```python \n", + "message = \"Hello World!\"\n", + "message = 'Hello World!'\n", + "message = \"\"\"Hello World!\"\"\"\n", + "```\n", + "\n", + "The reason for single and double quotes is so you can \n", + "put the other kind of quote inside. \n", + "\n", + "```python \n", + "message = \" You're allowed to put single quotes inside double quotes\"\n", + "message = ' He said \"You can use double quotes inside single quotes.\" '\n", + "```\n", + "\n", + "You've seen the triple quote form at the top of your assignments, \n", + "where it gives you the instructions about how to complete the lesson. The \n", + "really important part of triple quotes is that it can span multiple lines, \n", + "and you can also have single and double quotes inside. \n", + "\n", + "```python \n", + "\n", + "message = \"\"\"\n", + "“Hope” is the thing with feathers -\n", + "That perches in the soul -\n", + "And sings the tune without the words -\n", + "And never stops - at all -\n", + "\"\"\"\n", + "```\n", + "\n", + "## Escaping\n", + "\n", + "There are some special characters that are hard to put into strings; they require a\n", + "special prefix character, and adding that character is called \"escaping\" or \"quoting\". \n", + "\n", + "For instance, you can put a double quote inside of a double quote string, but\n", + "you have put a slash in front of it. \n", + "\n", + "```python\n", + "message = ' You\\'re allowed to put single quotes inside single quotes, if you escape it '\n", + "message = \" He said \\\"You can use double quotes inside single quotes, if you escape\\\" \"\n", + "```\n", + "\n", + "Notice the `\\'` and `\\\"` characters in the strings. There are a lot of other characters\n", + "that you might escape, but there are only two that you will use most of the time:\n", + "\n", + "* `\\n` ends a line and starts a new one. \n", + "* `\\t` is a tab. It moves the next character to the next tab stop (usually every 4 or 8 characters).\n", + "\n", + "Here is an example of using `\\n` and `\\t` in a string." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Tabs and Newlines\n", + "\n", + "s = \"a\\tb?\\tc!!\\t\\n1\\t2\\t3\\t\\n\"\n", + "print(s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that the 1,2,3 line up with the a,b?,c!!, even though the strings are\n", + "different lengths. Using the `\\t` the first time makes the next character always\n", + "start at column 8, and the second one makes it always start at column 16. You\n", + "can use this for basic formatting.\n", + "\n", + "\n", + "# Test Yourself\n", + "\n", + "Create two strings and print them out. \n", + "The first string will have multiple line and have a 'Roses are Red' poem. Use triple quotes\n", + "\n", + "The second string will use double quotes and have a list of your friends first names and their ages, \n", + "with their ages lined up in the second column. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test Yourself\n", + "\n", + "poem = \"\"\"\n", + "\"\"\"\n", + "\n", + "print(poem)\n", + "\n", + "friends = \"\"\n", + "\n", + "print(friends)\n", + "\n", + "# Hint: you will need \\t and \\n in the friends string, but not in the poem." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Fancy Formatting\n", + "\n", + "Python has several different ways to format a string; we are going to practice\n", + "the newest, and most important one. These are called 'f strings' and here is what\n", + "they look like: \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# f-strings\n", + "\n", + "age = 14\n", + "name = \"John\"\n", + "\n", + "print(f\"{name} is {age} years old.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The important parts of the `f` string is \n", + "\n", + "* It starts with 'f'\n", + "* You can insert variables inside it by surrounding them with curly braces, `{}`\n", + "\n", + "Here are some more important things you can do with f-strings. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# More F-Strings\n", + "\n", + "# You can put lots of expressions inside the curly braces, not just variable names\n", + "\n", + "print(f\"{name.upper()} is {age} years old. In 5 years, he will be {age + 5} years old.\")\n", + "\n", + "# You can add a colon after the variable name to format the output\n", + "# For instance, to make a number appear with commas as thousands separators, you can write {number:,}\n", + "# or to make it have only 2 decimal places, you can write {number:.2f}\n", + "\n", + "number = 1234567.890123\n", + "\n", + "print(f\"With a separator: {number:,}\")\n", + "print(f\"Rounded to 2 places: {number:.2f}\")\n", + "\n", + "# You can make a string appear in a certain number of spaces by writing {string:10}\n", + "# This will make the string appear in a space of 10 characters, padding it with spaces if necessary\n", + "\n", + "print(f\"{'Hello':10}{'World':10}!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can combine f-strings and triple quotes for a very powerful method of formatting. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me\n", + "\n", + "name = \"John\"\n", + "age = 14\n", + "prize = \"a unicorn\"\n", + "\n", + "letter = f\"\"\"\n", + "Dear {name},\n", + "\n", + "Congratulations! You have won {prize} in our prize draw. \n", + "You are only {age} years old, so you must be very lucky!\n", + "\n", + "Yours sincerely,\n", + "The Prize Draw Team\n", + "\"\"\"\n", + "\n", + "print(letter)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There is a lot more you can do with f-strings, but this will get you started. \n", + "\n", + "## Test Yourself\n", + "\n", + "In the loop, print out:\n", + "\n", + "* start each line with \"!\"\n", + "* The line number, formatted to 3 spaces\n", + "* The string \"equations\" followed by a math equation showing the number times 2\n", + "* the last number is formatted to 5 spaces\n", + "\n", + "For instance, one of the lines should look like\n", + "\n", + "```python \n", + "! 6 equation: 6 * 2 = 12\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test Yourself\n", + "\n", + "for i in range(1, 9):\n", + " ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Turning Strings to List\n", + "\n", + "Let's review how to strings into lists. There are two important ways. \n", + "\n", + "First, you can turn it directly into a list with `list()`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(list(\"Hello World\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Second, you can break it up on a character with `split()`:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Split on spaces\n", + "m = \"Python is fun to learn\"\n", + "l = m.split()\n", + "print(l)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `.split()` method splits on spaces by default, but you can specify a\n", + "different character to split on by passing it as an argument to the method." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# split on commas\n", + "\n", + "m = 'a,b,c,d,e'\n", + "l = m.split(',')\n", + "print(l)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After you have split a string, you can rejoin it. There is a funny way to do it,\n", + "which we will have to explain later; for now just use this method." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "# Join with spaces\n", + "l = ['Python', 'is', 'fun', 'to', 'learn']\n", + "s = ' '.join(l) # Doesn't that look weird?\n", + "print(s)\n", + "\n", + "# Join with commas\n", + "l = ['a', 'b', 'c', 'd', 'e']\n", + "s = ','.join(l)\n", + "print(s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So, if you wanted to change the third word of a sentence, you might do:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "m = \"Python is fun to learn\"\n", + "l = m.split() # Turn it into a list of words\n", + "l[2] = 'amazing' # Change the third word\n", + "s = ' '.join(l) # Join the words back together\n", + "\n", + "print(s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you wanted to add a word in the middle you might do:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run Me!\n", + "m = \"Python is fun to learn\"\n", + "l = m.split() # Turn it into a list of words\n", + "\n", + "first_half = l[:2] # Get the first two words\n", + "second_half = l[2:] # Get the rest of the words\n", + "\n", + "l = first_half + ['really'] + second_half # Add 'really' in the middle, using + to combine lists\n", + "\n", + "s = ' '.join(l) # Join the words back together\n", + "\n", + "s" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test Yourself\n", + "\n", + "Use the strings and lists, along with `+`, `.split()`, slicing and indexing, to assemble and print out phrases.\n", + "\n", + "Hints:\n", + "\n", + "* You might need to use the string methods `.lower()` or `.capitalize()`\n", + "* You can extract words using either a slice on a string, or convert the string to a list first. \n", + "\n", + "First, here is an example:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Example\n", + "\n", + "s1 = \"Pythons are constrictors!\"\n", + "s2 = \"John is funny\"\n", + "\n", + "# Print \"Python is fun\" \n", + "\n", + "space = s1[7]\n", + "s = s1[:6] + space + s2[5:-2] + s1[-1]\n", + "print(s)\n", + "\n", + "# or\n", + "\n", + "words1 = s1.split()\n", + "pythons = words1[0]\n", + "python = pythons[:-1]\n", + "words2 = s2.split()\n", + "is_word = words2[1] # 'is' is a reserved word in Python, so we can't use it as a variable name\n", + "funny = words2[2]\n", + "fun = funny[:-2]\n", + "exclaim = s1[-1]\n", + "\n", + "print(python + space + is_word + space + fun + exclaim)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now you try it:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test yourself \n", + "\n", + "s1 = \"The train in Spain.\"\n", + "s2 = \"makes passengers complain\"\n", + "s3 = [\"flowers\", \"grow\", \"again\" ]\n", + "s4 = \"to\"\n", + "s5 = \" \" \n", + "\n", + "# Print \"The train in Spain makes passengers complain.\"\n", + "\n", + "# Print \"The rain in Spain makes flowers grow again\"\n", + "\n", + "# Print \"The passengers grow flowers in Spain\n", + "\n", + "# Print \"The flowers in Spain train passengers to complain.\"\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + }, + "syllabus": { + "uid": "Tmg4QRhJ" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/30_Loops/090_Fizz_Buzz_Badgers.py b/lessons/30_Loops/090_Fizz_Buzz_Badgers.py new file mode 100644 index 00000000..243c6400 --- /dev/null +++ b/lessons/30_Loops/090_Fizz_Buzz_Badgers.py @@ -0,0 +1,31 @@ +""" +Below is the FizzBuzz Program from the earlier lesson. +The rules for the program are: + +For the numbers from 1 to 30: + +* If the number is evenly divisible by 5, print '🦡 badger' +* If the number is evenly divisible by 3, print '🍄 mushroom' +* If the number is evenly divisible by 15, print '🐍 snake!' +* If it is divisible by neither, print the number. + +Your job is to modify only one line -- the one with range() +-- so that the program only prints '🦡 badger' + +Your program should print 4 badgers. +""" + +for i in range(1, 31): # Change only this line + + # Don't change anything below this line + if i % 15 == 0: + print(i, '🐍 snake!') + elif i % 5 == 0: + print(i, '🦡 badger') + elif i % 3 == 0: + print(i, '🍄 mushroom') + else: + print(i) + +# hint: run the program once and look at the numbers that are printed. +# Maybe iterate over those numbers. \ No newline at end of file diff --git a/lessons/30_Loops/100_For_Loop_Gauntlet.ipynb b/lessons/30_Loops/100_For_Loop_Gauntlet.ipynb new file mode 100644 index 00000000..19ee75eb --- /dev/null +++ b/lessons/30_Loops/100_For_Loop_Gauntlet.ipynb @@ -0,0 +1,363 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "539e9340", + "metadata": {}, + "source": [ + "# For Loop Gauntlet\n", + "\n", + "The goal of this assignment is to make you a master of utilizing for loops.\n", + "Complete all the for loop challenges on the paper. Please read each challenge\n", + "carefully and make sure that your for loops display exactly what is asked. If\n", + "you finish them all, try the bonus challenge.\n", + "\n", + "## Single for-loops\n", + "\n", + "Write a for loop to do each of the following\n" + ] + }, + { + "cell_type": "markdown", + "id": "d0b568dc", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "Display all numbers from 0 to 100 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0752dd4", + "metadata": { + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Display all numbers from 0 to 100 \n" + ] + }, + { + "cell_type": "markdown", + "id": "8b92e611", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "Display all numbers from 100 to 0 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aec8cf23", + "metadata": { + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Display all numbers from 100 to 0 \n" + ] + }, + { + "cell_type": "markdown", + "id": "8942605e", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "Display all even numbers from 2 to 100 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ed3d8616", + "metadata": { + "lines_to_next_cell": 0, + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Display all even numbers from 2 to 100 \n" + ] + }, + { + "cell_type": "markdown", + "id": "c3501380", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "Display all odd numbers from 1 to 99 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "038f48bf", + "metadata": { + "lines_to_next_cell": 0, + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Display all odd numbers from 1 to 99\n" + ] + }, + { + "cell_type": "markdown", + "id": "f750c8e2", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "Display all numbers from 1 to 40. if the number is odd, print \"odd\" next to the number. if the number is even, print \"even\" next to the number (see example below). \n", + "\n", + " 1 is odd \n", + " 2 is even \n", + " 3 is odd \n", + " 4 is even \n", + " 5 is odd...etc. \n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "174bdcd9", + "metadata": {}, + "outputs": [], + "source": [ + "# Display all numbers from 1 to 500.\n" + ] + }, + { + "cell_type": "markdown", + "id": "969e00f1", + "metadata": {}, + "source": [ + "Display all multiples of 7 from 0 to 70" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "620b3886", + "metadata": { + "lines_to_next_cell": 0, + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Display all multiples of 7 from 0 to 777\n" + ] + }, + { + "cell_type": "markdown", + "id": "b468e701", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "Print all the years you were alive and how old you were in each. e.g. \"in 1979, i was 2 years old.\" (for a really old person) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6db862fd", + "metadata": { + "lines_to_next_cell": 0, + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Your Code Here\n" + ] + }, + { + "cell_type": "markdown", + "id": "571b7e8d", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "## Nested for-loops\n", + "\n", + "Write nested for loops (a for loop inside another for loop). Here is an example of nested loops. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "beb062f6", + "metadata": { + "lines_to_next_cell": 0, + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Examples of Nested Loops\n", + "\n", + "for i in range(8):\n", + " for j in range(8):\n", + " print(f\"({i},{j})\", end= ' ')\n", + " print()" + ] + }, + { + "cell_type": "markdown", + "id": "3605a476", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "For your first nested loop, display this output: \n", + "\n", + "```\n", + "0 0 \n", + "0 1 \n", + "0 2 \n", + "1 0 \n", + "1 1 \n", + "1 2 \n", + "2 0 \n", + "2 1 \n", + "2 2\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c847ed3", + "metadata": { + "lines_to_next_cell": 0, + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Display the output shown above\n" + ] + }, + { + "cell_type": "markdown", + "id": "c6a9c592", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "Display the numbers 1 through 9 in a 3x3 square grid like this: \n", + "\n", + "```\n", + "1 2 3 \n", + "4 5 6 \n", + "7 8 9 \n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bb0a4a5b", + "metadata": { + "lines_to_next_cell": 0, + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Display the numbers 1 through 9 in a 3x3 square grid\n" + ] + }, + { + "cell_type": "markdown", + "id": "3265fddb", + "metadata": { + "lines_to_next_cell": 0 + }, + "source": [ + "Display the numbers 1 through 100 in a 10x10 square grid. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ced82638", + "metadata": { + "lines_to_next_cell": 0, + "title": "[python]" + }, + "outputs": [], + "source": [ + "# Display the numbers 1 through 100 in a 10x10 square grid. \n" + ] + }, + { + "cell_type": "markdown", + "id": "9434b500", + "metadata": { + "lines_to_next_cell": 2 + }, + "source": [ + "Display the following output: \n", + "\n", + "```\n", + "* \n", + "* * \n", + "* * * \n", + "* * * * \n", + "* * * * * \n", + "* * * * * *\n", + "``` " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3b81fd1e", + "metadata": {}, + "outputs": [], + "source": [ + "# Display the asterisk pattern shown above\n" + ] + }, + { + "cell_type": "markdown", + "id": "5a40192d", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "title,-all", + "main_language": "python", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + }, + "syllabus": { + "uid": "8yGSkBgV" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/lessons/30_Loops/110_FizzBuzz_Gui_Grid.py b/lessons/30_Loops/110_FizzBuzz_Gui_Grid.py new file mode 100644 index 00000000..20d1fb85 --- /dev/null +++ b/lessons/30_Loops/110_FizzBuzz_Gui_Grid.py @@ -0,0 +1,46 @@ +""" +FizzBuzz Grid + +We're going to use a Windowing library, guizero, to create a 10x10 grid of +numbers, with each number in a separate cell, but we're also going to set the +color of the number based on the following rules: + +* If the number is evenly divisible by 5, print '🦡' +* If the number is evenly divisible by 3, print '🍄' +* If the number is evenly divisible by 15, print '🐍' +* If it is divisible by neither, print the number. + +Additionally, If you are displaying a number color the numbers as follows: + +* If the sum of the digits of the number is even, color the number blue +* If the sum of the digits of the number is odd, color the number red + +Here is how you can display a number in your grid. Call this function in your loop +to display the number in the grid cell at the row and column you specify. + + Text(app, text=str(number), grid=[col, row], color=color) + +Or to display a badger: + + Text(app, text='🦡', grid=[col, row], color=color) + +HINT: You can use % and // to get the first and last digit of a number, +or you can convert the number to a string and iterate over the digits +""" + +from guizero import App, Box, Text + +app = App("Numbers Grid", layout="grid") + +# Create a 10x10 grid using nested loops +# Or you can use a single loop and calculate the row and column + +# In the loop, calculate or increment the number + +# Use % determining the display, using FizzBuzz rules + +# If you are displaying a number, calculate the sum of the digits and determine the color + +# Call Text(app, text='...', grid=[col, row], color=...) to display something. + +app.display() \ No newline at end of file diff --git a/lessons/30_Loops/120_More_Iterables.ipynb b/lessons/30_Loops/120_More_Iterables.ipynb new file mode 100644 index 00000000..a8deec7c --- /dev/null +++ b/lessons/30_Loops/120_More_Iterables.ipynb @@ -0,0 +1,332 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Iteration Functions\n", + "\n", + "Python has some very important iteration functions that you can use in your programs. \n", + "\n", + "* ``enumerate()`` iterates over an iterable and returns it with an index. \n", + "* ``zip()`` combines two iterables, iterating through them side-by-side. \n", + "* ``cycle()`` goes through an iterable, then starts over and keeps going. \n", + "* ``islice()`` only takes a few of an iterable. \n", + "\n", + "Let's try some of these out. ( We'll work on ``enumerate()`` and ``zip()`` and leave\n", + "the others for later. )\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Enumerate\n", + "\n", + "colors = [ 'red', 'blue', 'black', 'orange']\n", + "\n", + "for i in enumerate(colors):\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that each iteration, ``enumerate()`` returns a _tuple_. The first item in\n", + "the tuple is its number in the list, and the second is the item in the list.\n", + "Usually, we will _unpack_ the tuple. In Python you can write code like this: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "t = (1,2,3)\n", + "a,b,c = t\n", + "print(t)\n", + "print(a,b,c)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Do you see what happened? When we wrote:\n", + "\n", + "```python \n", + "a,b,c = t\n", + "```\n", + "\n", + "The first item in ``t`` was assigned to ``a``, the second to ``b``, etc. That means when we use ``enumerate()`` we can write this instead:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Enumerate with Unpacking\n", + "\n", + "colors = [ 'red', 'blue', 'black', 'orange']\n", + "\n", + "for index, color in enumerate(colors): # Unpacking the tuple from enumerate()\n", + " print(\"#\", index, \"color is\", color)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another thing you should notice about our `enumerate()` example is that there\n", + "is more than one variable in the `for` loop. This is called \"unpacking\" and it\n", + "also works in assignment, where you can write:\n", + "\n", + "```python \n", + "a,b = 1,2\n", + "```\n", + "\n", + "That code will be equivalent to:\n", + "\n", + "```python\n", + "a = 1\n", + "b = 1\n", + "```\n", + "\n", + "What is really going on is that on the left side of the assignment is a tuple,\n", + "and on the right is an iterable, so you can put any iterable on the right. Most\n", + "of the time, you should have the same number of variables on the left as on the\n", + "right, but you can also use `*` to indicate that one variable should \"suck up\"\n", + "every thing left in the list. \n", + "\n", + "One more thing; you will sometimes use parentheses in the unpacking, such as when we\n", + "write:\n", + "\n", + "```python\n", + "pairs = [\n", + " ('a', 1),\n", + " ('b', 2),\n", + " ('c', 3)\n", + "],\n", + "\n", + "for color, (item1, item2) in enumerate(colors, pairs):\n", + " ...\n", + "```\n", + "\n", + "This one is more complex. It means that `enumerate()` is returning a tuple\n", + "for its second element, and that tuple should also be unpacked. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Unpack a range\n", + "a,b,c = range(3)\n", + "print(a,b,c)\n", + "\n", + "# use *rest to capture all the rest of the values\n", + "a,b,*rest = range(5)\n", + "print(a,b,rest)\n", + "\n", + "# the * doesn't have to go at the end\n", + "a,*b,c = range(5)\n", + "print(a,b,c)\n", + "\n", + "# Unpacking multiple levels\n", + "l1 = [1,2,3]\n", + "t1 = ('x','y','z')\n", + "\n", + "t2 = [ l1, t1 ] # two levels deep!\n", + "\n", + "# Unpack all of the levels\n", + "(a,b,c), (d,e,f) = t2\n", + "\n", + "print(a,b,c,d,e,f)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will study unpacking in a lot more detail later for now you mostly need to understand how it works with iterator functions." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Zip \n", + "\n", + "Zip is another really important iteration tool. It lets you iterate over two lists at the same time. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Zip \n", + "\n", + "list1 = ['a','b','c','d']\n", + "list2 = ['1','2','3','4']\n", + "\n", + "for l1, l2 in zip(list1, list2): # <- Ok, look, unpacking!\n", + " print(l1, l2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice what ``zip()`` did: For each iteration of the loop, it took the first item from both lists, then the second item from both lists, then the third, etc. How could we use this in a turtle program? What if we had instructions about where the turtle should go and what colors it should draw lines?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Use zip to iterate over two lists at once\n", + "\n", + "colors = [ 'red', 'blue', 'black', 'orange']\n", + "\n", + "# Each tuple in the directions is first, how far to turn, then how far to go\n", + "directions = [\n", + " (0, 10),\n", + " (90, 20),\n", + " (0, 40),\n", + " (270, 10)\n", + "]\n", + "\n", + "for color, (angle, distance) in zip(colors, directions):\n", + " print(f\"Move {distance} units in direction {angle} degrees and color {color}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# islice\n", + "\n", + "The ``islice()`` function works like the slice notation on a list: it lets you\n", + "decide where to start and stop iteration. For instance, if you wanted to only\n", + "take the first 10 items of a list, you could use ``islice(l, 10)``\n", + "\n", + "For a normal list, you could just do that with `l[:10]`, so why would you need `islice()`?\n", + "The reason is that a list has a finite number of items, but an iterator can go on forever, \n", + "and like `range()` the iterator doesn't need to store the data ( it can generate it ) so \n", + "you need something more flexible. \n", + "\n", + "For example:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from itertools import islice # Important! \n", + "\n", + "N = 1_000_000 \n", + "r = range(N)\n", + "\n", + "# range( iterator, stop ) or\n", + "# range( iterator, start, stop, step)\n", + "l = list( islice( r,N-5, N) )\n", + "\n", + "l" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Demonstrate islice\n", + "\n", + "from itertools import islice # Important! \n", + "\n", + "l = [0,1,2,3,4,5,6,7,8,9]\n", + "\n", + "for i in islice(l, 5): # Stop at 5\n", + " print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# cycle\n", + "\n", + "The `cycle()` iterator function repeats its input iterator over and over, infinitely, \n", + "so it is exactly the kind of thing you want to use `islice()` for\n", + "\n", + "What if you had four colors, in a list: \n", + "\n", + "```python \n", + "colors = [ 'red', 'blue', 'black', 'orange']\n", + "```\n", + "\n", + "But you wanted to use the colors for a hexagon? You'd run out of colors. The ``cycle()`` iterator makes a list repeat infinitely. But, we don't want it \n", + "to be infinite, we want it to got six times. We can use ``islice()`` and ``cycle()`` to solve that problem:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Use cycle and islice\n", + "\n", + "from itertools import cycle, islice\n", + "\n", + "colors = [ 'red', 'blue', 'black', 'orange']\n", + "\n", + "for color in islice(cycle(colors), 25):\n", + " print(color, end=' ')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + }, + "syllabus": { + "uid": "PrKwTywv" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/30_Loops/130_Iterable_Turtle.ipynb b/lessons/30_Loops/130_Iterable_Turtle.ipynb new file mode 100644 index 00000000..e3ac97e7 --- /dev/null +++ b/lessons/30_Loops/130_Iterable_Turtle.ipynb @@ -0,0 +1,46 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "Programmable turtle graphics\n", + "\n", + "Use what you've learned about lists, loop, cycle, slice and zip to draw a pattern\n", + "\"\"\"\n", + "\n", + "t = ... # Create a turtle like in previous programs, like 04_Crazy_Tina.py\n", + "\n", + "colors = ... # Make a list of colors\n", + "\n", + "directions = [ # Create a list of directions and angles\n", + " ( , ),\n", + " ( , ), ... # Add more\n", + "]\n", + "\n", + "# Zip the colors and directions together, then unpack them. THere is a good example of this\n", + "# in 10_More_iterables.ipynb in the discussion of zip()\n", + "\n", + "for ... in zip( ... , ...):\n", + " t.color( ... )\n", + " t.forward( ... )\n", + " t.left( ... )\n", + "\n", + "# Don't forget the special way to end a turtle program. " + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + }, + "syllabus": { + "uid": "vTyp2WhX" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/30_Loops/140_More_Loops.ipynb b/lessons/30_Loops/140_More_Loops.ipynb new file mode 100644 index 00000000..adfc5526 --- /dev/null +++ b/lessons/30_Loops/140_More_Loops.ipynb @@ -0,0 +1,240 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# More Loops\n", + "\n", + "## While Loops\n", + "\n", + "While loops are similar to for loops. Both repeat the code inside the loop.\n", + "The for loop repeats code for a specified number of times.\n", + "The while loop repeats code for as long as a condition is True.\n", + "\n", + "A while loop looks like this:\n", + "\n", + "```python\n", + "while :\n", + " Code to repeat\n", + "```\n", + "\n", + "Where `condition` is a boolean variable or something that evaluates to a boolean\n", + "(True or False). This is similar to an if or elif statement. Here is an example\n", + "of a while loop:\n", + "\n", + "```python \n", + "s = 0\n", + "while s < 55:\n", + " s = s +1\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break and Continue\n", + "\n", + "To recap: \n", + "\n", + "* A `for` loop runs until the iterator runs out of items\n", + "* A `while` loop runs until the condition is false. \n", + "\n", + "But there is another way to cause a loop to exit: the `break` key word will\n", + "cause a loop to exit immediately." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# count() is an infinite iterator that returns numbers sequentially, 0,1,2,3 ...\n", + "\n", + "from itertools import count\n", + "\n", + "for i in count():\n", + "\n", + " print(i, end = ' ')\n", + "\n", + " if i >= 5: # break if i is greater than or equal to 5\n", + " print() # print a newline\n", + " break\n", + "\n", + " # Another way to do the same thing\n", + "\n", + "i = 0\n", + "while True:\n", + " \n", + " print(i, end = ' ')\n", + " \n", + " if i >= 5:\n", + " break\n", + "\n", + " i = i + 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Sometimes you want to skip the rest of the loop and go back to the start, which you can do with `continue`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from itertools import count\n", + "\n", + "for i in count():\n", + "\n", + " if i % 3 == 0: # skip printing the number if it is divisible by 3\n", + " continue \n", + "\n", + " print(i, end = ' ')\n", + "\n", + " if i >= 10: # break if i is greater than or equal to 5\n", + " print() # print a newline\n", + " break" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python has another loop feature that most languages do not have, the else clause\n", + "in a loop. The else clause is executed when the loop terminates normally (the\n", + "condition is false). It is not executed if the loop is terminated by a break\n", + "statement.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Complete the loop and run the else block\n", + "\n", + "for i in range(10):\n", + " print(i, end = ' ')\n", + "else:\n", + " print('else block') \n", + "\n", + "# Break and do not execute the else block\n", + "for i in range(10):\n", + " print(i, end = ' ')\n", + "\n", + " if i > 5:\n", + " print('breaking, skip the else')\n", + " break\n", + "\n", + "else:\n", + " print('else block') " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is a method of finding prime numbers, from the [Python documentation](https://docs.python.org/3/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops). " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for n in range(2, 15):\n", + " for x in range(2, n):\n", + " if n % x == 0:\n", + " print(n, 'equals', x, '*', n//x)\n", + " break\n", + " else:\n", + " # loop fell through without finding a factor\n", + " print(n, 'is a prime number')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For a `while` block, the else block is executed when then condition is met. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Exit the loop when the condition is met, and run the else block\n", + "i = 0\n", + "while i < 5:\n", + " \n", + " print(i, end = ' ')\n", + "\n", + " i = i + 1\n", + "\n", + "else:\n", + " print('else block')\n", + "\n", + "# Exit with break, and do not execute the else block\n", + "i = 0\n", + "while True:\n", + " \n", + " print(i, end = ' ')\n", + " if i >= 5:\n", + " print('breaking, skip the else')\n", + " break\n", + "\n", + " i = i + 1\n", + "\n", + "else:\n", + " print('else block')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It's actually very rare to need an `else` block on a `for` or `while` loop, but you will use `break` and `continue` a lot. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + }, + "syllabus": { + "uid": "RMSFNtMb" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/30_Loops/150_Number_Guess.py b/lessons/30_Loops/150_Number_Guess.py new file mode 100644 index 00000000..93fdd3ca --- /dev/null +++ b/lessons/30_Loops/150_Number_Guess.py @@ -0,0 +1,55 @@ +""" +Number Guess Game + +Pick a random number between 1 and 100. If the random number is divisible by 7, +pick another number and continue picking new numbers until the random number is +not divisible by 7. ( hint: use a loop! ) + +Ask the user to guess the number. If the user's guess is higher than the random +number, tell the user the guess is too high. If the user's guess is lower than +the random number, tell the user the guess is too low. If the user guesses the +number, tell the user the guess is correct and stop the game. If the user does +not guess the number, allow the user to keep guessing until the user gets the +right answer. + + +Write the main part of your program as a loop. If the user guesses the number, +break out of the loop. If the user does not guess the number, continue the loop. + +If the user guesses a number that is divisible by 7, tell the user "that is a +very bad number, starting over " and pick another number and continue picking +new numbers until the number is not divisible by 7. + +Get a random number: + n = random.randint(1, 100) + +Use the ask_integer function to get the user's guess, like this: + guess = ask_integer("Guess a number between 1 and 100: ") + +Note: The prompts and output for your program will be in the teminal +at the bottom of the editor screen; this program does not use the GUI. +""" + +import random + +def ask_integer(prompt): + """Function to ask the user for an integer""" + while True: + try: + return int(input(prompt)) + except ValueError: + print("Please enter a valid number!") + +# Pick the random number + +# In your loop: + + # Get the user's guess + + # If the user's guess is divisible by 7, tell the user to start over + + # If the user's guess is too high, tell the user + + # If the user's guess is too low, tell the user + + # If the user's guess is correct, tell the user and break out of the loop \ No newline at end of file diff --git a/lessons/30_Loops/160_Extras.ipynb b/lessons/30_Loops/160_Extras.ipynb new file mode 100644 index 00000000..0c0ea2f0 --- /dev/null +++ b/lessons/30_Loops/160_Extras.ipynb @@ -0,0 +1,91 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Extras\n", + "\n", + "Here are some interesting things related to the lessons, very advanced and completely optional. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Yet More FizzBuzz\n", + "\n", + "It is possible to write a version of FizzBuzz that is even shorter than the one we wrote in the previous lesson. This version uses a list comprehension to generate the list of strings. Here is the code:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fb = ['fizz'*(i%3==0) + 'buzz'*(i%5==0) or str(i) for i in range(1,101)]\n", + "print(fb)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This version is very peculiar because it uses $n^4 \\mod 15$. See this [page](http://philcrissman.net/posts/eulers-fizzbuzz/) for an explanation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fb = [(lambda n: { 1: n, 6: \"Fizz\", 10: \"Buzz\", 0: \"FizzBuzz\" }[n**4%15])(n) for n in range(1,101)]\n", + "print(fb)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(list(set(\"Once upon a time a 👦 with a 🐕 met a 👧 who had a 🐈 and they went to the park to play with a ⚽.\".split())))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(list()))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" + }, + "syllabus": { + "uid": "VJSgvOr5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/30_Loops/README.md b/lessons/30_Loops/README.md new file mode 100644 index 00000000..ba6fd1b3 --- /dev/null +++ b/lessons/30_Loops/README.md @@ -0,0 +1,32 @@ +--- +uid: TzgRqJlw +--- + +# PCEP Alignment + +* PCEP-30-01 3.2 – Perform Different Types of Loops + * The `pass` Instruction + * Building Loops with `while`, `for`, `range()`, and `in` + * Iterating Through Sequences + * Expanding Loops with `while-else` and `for-else` + * Nesting Loops and Conditional Statements + * Controlling Loop Execution with `break` and `continue` + +* PCEP-30-01 4.1 – Collect and Process Data Using Lists + * Constructing Vectors + * Indexing and Slicing + * The `len()` Function + * List Methods: `append()`, `insert()`, `index()`, etc. + * Functions: `len()`, `sorted()` + * The `del` Instruction + * Iterating Through Lists with the `for` Loop + * Initializing Loops + * The `in` and `not in` Operators + * List Comprehensions + * Copying and Cloning + * Lists in Lists: Matrices and Cubes + +* PCEP-30-01 4.2 – Collect and Process Data Using Tuples + * Tuples: Indexing, Slicing, Building, Immutability + * Tuples vs. Lists: Similarities and Differences + * Lists Inside Tuples and Tuples Inside Lists \ No newline at end of file diff --git a/lessons/40_Data_Structures_Func/10_Functions.ipynb b/lessons/40_Data_Structures_Func/10_Functions.ipynb new file mode 100644 index 00000000..cb8aee1c --- /dev/null +++ b/lessons/40_Data_Structures_Func/10_Functions.ipynb @@ -0,0 +1,509 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Functions and Data Structures\n", + "\n", + "## Functions\n", + "\n", + "We've seen functions a few times, but haven't explained how they work in detail. Let's explore functions. \n", + "\n", + "A function looks like this:\n", + "\n", + "```python \n", + "def add_ten(x):\n", + " return x + 10\n", + "```\n", + "\n", + "Then we can use the function like this:\n", + "\n", + "```python \n", + "y = add_ten(5)\n", + "```\n", + "\n", + "The important parts of a function are: \n", + "\n", + "* It has a name, which comes right after \"def\"\n", + "* It has argument, or input values, that come right after the name. \n", + "* The body of the function is an indented block\n", + "* The function returns a value, which py default is `None`\n", + "\n", + "The simplest function you can write is:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def do_nothing():\n", + " pass\n", + "\n", + "y = do_nothing()\n", + "print(y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `pass` key word means \"do nothing\"; it just takes up space so the function\n", + "will have a body that is properly indented. This function does not have a\n", + "`return` statement, so it returns the empty value `None`.\n", + "\n", + "The important uses of functions is that they make parts of your program\n", + "reusable, and properly breaking a program into functions makes the program\n", + "easier to understand, use and test, especially if the function and it's\n", + "arguments have names that indicate what the function and arguments do or\n", + "what data they hold. \n", + "\n", + "By the way, have you checked in your code? Take a look at this [documentation](https://curriculum.jointheleague.org/howto/checkin_restart.html) if you forgot how it's done!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Function Arguments\n", + "\n", + "Function argument are the values you pass into the function so it can compute the value it returns. \n", + "You name the arguments on the argument list, and there are a few ways to assign values to arguments when you\n", + "call the function: you can specify the arguments by position, or by name. \n", + "\n", + "For instance:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Demonstrate function arguments\n", + "\n", + "def greet_user(name, greeting):\n", + " print(f\"{greeting}, {name}!\")\n", + "\n", + "# Call function with \"positional\" arguments. He first argument\n", + "# is assigned `name`, the second is assigned `greeting`.\n", + "\n", + "greet_user(\"Alice\", \"Bounjour\")\n", + "\n", + "# We can also call the function with \"keyword\" arguments. This\n", + "# allows us to specify the arguments in any order.\n", + "\n", + "greet_user(greeting=\"Hello\", name=\"Alice\") # greeting and name are in opposite order!\n", + "\n", + "# You can mix positional and keyword arguments, but all positional\n", + "# arguments must come first.\n", + "\n", + "greet_user(\"Bob\", greeting=\"Hello\")\n", + "\n", + "\n", + "# You can't have a positional argument after a keyword argument.\n", + "# This will cause an error ( uncomment and run to see )\n", + "# greet_user(name = \"Bob\", greeting)\n", + "\n", + "# You also can't specify an argument more than once. This will also\n", + "# cause an error ( uncomment and run to see )\n", + "# greet_user(\"Bob\", name=\"Bob\")\n", + "\n", + "\n", + "# And, you can't skip an argument ( if it doesn't have a default value.)\n", + "# This will also cause an error ( uncomment and run to see )\n", + "# greet_user(\"Bob\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also specify default values for arguments. If an argument has a default value, it is optional, \n", + "but the default arguments must go at the end of the list. \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def greet_user(name, greeting='Hello', punct=\"!\"):\n", + " print(f\"{greeting}, {name}{punct}\")\n", + "\n", + "# Use the default value for punct and hello\n", + "greet_user(\"Alice\")\n", + "\n", + "# Or, override the default value\n", + "greet_user(\"Alice\", \"Hello\", \".\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another important point is that the variables you use in your function have to be declared, \n", + "such as by including the variable in the argument list. So this will throw an error:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def greet_user(name, greeting='Hello'):\n", + " print(f\"{greeting}, {name}{punct}\")\n", + "\n", + "greet_user(\"Alice\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python didn't know what the variable `punct` is, so it could not run the function. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test Yourself\n", + "\n", + "Write a function that will take two strings. The first is a character, and the second\n", + "is a longer string. The function will iterate over the second string and return the\n", + "position that the character has in the string.\n", + "\n", + "If the chracter is not in the string, return -1\n", + "\n", + "For instance: \n", + "\n", + "```python \n", + "find_char('x', 'My fox likes bricks') == 5\n", + "find char('z', 'There is a zebra in the garden') == 11\n", + "find char('w', \"I've lost my shoes\") == -1\n", + "```\n", + "\n", + "We will use `assert` to check your function. Assert will raise an error if the expression \n", + "is not True. \n", + "\n", + "Hint: you can `enumerate()` your string to get all of the characters and their positions. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test yourself\n", + "\n", + "# Write your own find_char function that takes a character and a string\n", + "\n", + "assert find_char('x', 'My fox likes bricks') == 5\n", + "assert find_char('z', 'There is a zebra in the garden') == 11\n", + "assert find_char('w', \"I've lost my shoes\") == -1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Composition\n", + "\n", + "You aren't limited to putting numbers and strings into function arguments; you\n", + "get put in anything that has a value ( which we call an `expression` )\n", + "\n", + "For instance, suppose we have the functions\n", + "\n", + "```python \n", + "def f(a,b):\n", + " pass\n", + "\n", + "def g(c,d):\n", + " pass\n", + "```\n", + "\n", + "The w can pass the output of f() directly into g()\n", + "\n", + "```python \n", + "g( f(1,2), f(3,4))\n", + "```\n", + "\n", + "Or put expressions in the argument list: \n", + "\n", + "```python \n", + "g( f(1,2)*f(3,4), f(5,6)-f(7,8))\n", + "```\n", + "\n", + "# Test Yourself\n", + "\n", + "Test yourself by writing functions. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test Yourself\n", + "\n", + "# Write a function to add two numbers and return the result\n", + "\n", + "# Write a function to subtract two numbers and return the result \n", + "\n", + "# Write a function to print \"Same\" if two numbers are the same, otherwise print \"Different\"\n", + "\n", + "# Use your functions to show that 2 + 2 = 4\n", + "\n", + "# Use your functions to show that ( 5 + 3) - 2 = 6\n", + "\n", + "# Use your functions to show that 2 + 2 != 3 + 3 = 6\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Oh No Closures\n", + "\n", + "Here is a warning, and also an exciting new feature, about functions. This function will work, but maybe not\n", + "the way you expect:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "name = 'Bob'\n", + "\n", + "def greet_user(greeting):\n", + " print(f\"{greeting}, {name}\")\n", + "\n", + "greet_user(\"Hello\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Are you surprised that worked? If not, go read it again ...\n", + "\n", + "The `name` variable is not in the argument list of the function, so the function should not have been able to run. But it did ... because it\n", + "got the variable from outside the function. This behavior is called a `closure`, and it is very, very useful. But it will also cause problems if \n", + "you aren't careful. \n", + "\n", + "The lessons is: always include the variables you use in your function in your argument list, unless you know why you want a closure. ( And you don't yet! ) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exceptions\n", + "\n", + "Sometimes, things go wrong. You can call these problems \"errors\" but they are\n", + "often known as \"exceptional conditions\" because they aren't the usual thing that happens. \n", + "For instance, what if we try to make an iteger of something that can't be an integer?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "int(\"This is not an integer\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The 'ValueError' part of the message is called an exception. It isn't just a message, its a thing we can use in our program to handle errors. For instance, suppose we have a list of things to convert to integers: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for e in [0,1, 65, 'Bob', 23,'larry']:\n", + " i = int(e)\n", + " print(f\"Converting {e} to an integer {i}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Well, we didn't get very far through the list. But, we can \"catch\" the exception and do something with it. It works like this:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for e in [0,1, 65, 'Bob', 23,'larry']:\n", + "\n", + " try:\n", + " i = int(e)\n", + " print(f\"Converting {e} to an integer {i}\")\n", + " except ValueError:\n", + " print(f\"Could not convert {e} to an integer\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using the `try/except` structure, we can do something different if an error is\n", + "raised. This is a very advanced feature, and there is a lot you can do with it,\n", + "but for now, remember this structure, and remember that the part that goes after\n", + "the `except` is the name of the exception that you see in the error. Other types\n", + "of errors have other types of exceptions. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run me! Uncomment one of the code lines to see the error it produces\n", + "# Put the comment back to see another error\n", + "# Index a list with a string\n", + "\n", + "my_list = [1,2,3,4,5]\n", + "\n", + "#print(my_list['Bob']) # TypeError: list indices must be integers or slices, not str\n", + "\n", + "#print(my_list[20]) # IndexError: list index out of range\n", + "\n", + "# assert False # AssertionError ( Although you don't usually catch assertions ) \n", + "\n", + "# x = 10 / 0 # ZeroDivisionError: division by zero\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you want to catch multiple exceptions ways to do it, and if you do, you will usually also want to name the exception. We've provided an exception name in the example below; each exceptino is named `e`.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# You can list the different types of different `except` clauses:\n", + "\n", + "try:\n", + " pass# do something\n", + "except ValueError as e:\n", + " print(f\"Got a value error {e}\")\n", + "except TypeError as e:\n", + " print(f\"Got a type error {e}\")\n", + "except ZeroDivisionError as e:\n", + " print(f\"Got a zero division error {e}\")\n", + "\n", + "# Or, you can use the \"superclass\" Exception to catch all exceptions\n", + "# But there are a lot of reasons to *not* do this\n", + "\n", + "try:\n", + " pass# do something\n", + "except Exception as e:\n", + " # Get all types of exceptions. \n", + " print(f\"Got an exception {e}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test Yourself\n", + "\n", + "Write a program that runs in a endless loop. Get a string from the user using\n", + "`input()` and convert it to an integer. If the user's input cannot be converted\n", + "to an integer ( and the user didn't enter 'q' ) check to see if the number is\n", + "in the list. If it is, print \"You got one!\". Exit the loop if the user enters\n", + "'q'. Report an error if the user's string cannot be converted to a number. \n", + "\n", + "If the user's number is not in the list, tell the user what the n'th number is\n", + "in the list is. That is, if the user enters `7`, and `7` is not in the list,\n", + "then tell the user '7 is not in the list, but the 7th number is the list is X',\n", + "where X is the 7th number. Be sure to handle the case where the list is shorter\n", + "than 7 elements, using an exception. \n", + "\n", + "You can check if something is in a list with `in`, like this:\n", + "\n", + "```python \n", + "if 5 in [1,2,3,4,5]:\n", + " print(\"It's In!\")\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test Yourself\n", + "\n", + "# Check if the user's numbers are in this list:\n", + "\n", + "l = [5,10,45, 56]\n", + "\n", + "# Forever loop until the user enters a number in the list\n", + "\n", + " # Get a number from the user. \n", + "\n", + " # If the user enteres 'q', exit the loop\n", + "\n", + " # If the user's number is in the list, print \"Found it!\" and contine the loop\n", + "\n", + " # If the user's number is not in the list, find the n'th number in the list. Print it and continue the loop\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" + }, + "syllabus": { + "uid": "4LyScnS5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/40_Data_Structures_Func/20_Dicts_Sets.ipynb b/lessons/40_Data_Structures_Func/20_Dicts_Sets.ipynb new file mode 100644 index 00000000..9c36766a --- /dev/null +++ b/lessons/40_Data_Structures_Func/20_Dicts_Sets.ipynb @@ -0,0 +1,563 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Data Structures\n", + "\n", + "We've seen a lot of data structures so far, but we haven't put them all together. So far we've seen: \n", + "\n", + "* Lists. A list of items. \n", + "* Tuples. Like a list, but can't be changed after it is created. ( it's \"immutable\" )\n", + "* Strings. Like a list, but always made of characters, and is also \"immutable\"\n", + "\n", + "Lets introduce a new one: the `set`. A set is important because it works a bit\n", + "like a list, except:\n", + "\n", + "* You create a set with \"{}\" instead of \"[]\"\n", + "* Each item can only be in a set once. \n", + "* The items in a set are not ordered. \n", + "\n", + "If you put multiple items into a set, it will only store one of each, and if you\n", + "iterate over the items in a list, they aren't guaranteed to be in the same order\n", + "you put them in. Let's compare a set and a list. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "l = ['a','a','b','b','c','c']\n", + "print(l)\n", + "\n", + "s = { 'a','a','b','b','c','c'}\n", + "print(s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that the list kept all of the items we put into it, and they are in the\n", + "same order, but the set removed the duplicates, and they are in a different\n", + "order. \n", + "\n", + "The formal name of these objects, string, set, list and tuple, are \"Collections\".\n", + "\n", + "# Creating Sets, Lists, Tuples\n", + "\n", + "So far we've seen one way for creating collections, using the braces, parentheses and quotes: \n", + "\n", + "```python\n", + "c = \"123\"\n", + "t = (1,2,3)\n", + "l = [1,2,3]\n", + "s = {1,2,3}\n", + "```\n", + "\n", + "But, there is another way! You can also use the 'constructor' function. Here is how we can create empty collections :\n", + "\n", + "```python \n", + "c = str()\n", + "t = tuple()\n", + "l = list()\n", + "s = set()\n", + "```\n", + "\n", + "These functions all can take one argument, an iterator, and that iterator can be\n", + "another set, list tuple. This means that you can easily convert between them. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "c = \"Hello\"\n", + "l = ['a','a','b','b','c','c']\n", + "\n", + "# Make a tuple from a list\n", + "t = tuple(l)\n", + "print(t)\n", + "\n", + "# Make a set from a list\n", + "s = set(l)\n", + "print(s)\n", + "\n", + "# Make a list from a string\n", + "a = list(c)\n", + "print(a)\n", + "\n", + "# Get the unique items from a list, by converting it to a set\n", + "# and then back to a list\n", + "print(list(set(l)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you create an empty collection, you can sometimes add items to the\n", + "collection. Lists and sets are \"mutable\", which means they can be changed.\n", + "Tuples and strings are immutable, they cannot be changed after they are created.\n", + "However, you can \"concatenate\" to immutable objects to create new ones. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Adding to mutable collections\n", + "\n", + "l = list()\n", + "l.append('a')\n", + "l.append('b')\n", + "l.append('c')\n", + "print(l)\n", + "\n", + "s = set()\n", + "s.add('a')\n", + "s.add('b')\n", + "s.add('c')\n", + "print(s)\n", + "\n", + "# Concatenating immutable collections to create new objects\n", + "\n", + "t = tuple()\n", + "t = t + ('a',) # Note the comma, this is a tuple with one element\n", + "t = t + ('b',)\n", + "t = t + ('c',)\n", + "print(t)\n", + "\n", + "s = \"\"\n", + "s = s + \"a\"\n", + "s = s + \"b\"\n", + "s = s + \"c\"\n", + "print(s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When we write `s = s + 'a'` this means:\n", + "\n", + "1. Combine `s` and \"a\" to get a new string\n", + "2. Assign that new string back to s\n", + "\n", + "This operation will destroy the old `s` and create a new one with the same name.\n", + "This is very different that using `list.append()` or `set.add()` because those\n", + "methods keep the same list and set and just add to it. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dictionaries\n", + "\n", + "You know what a dictionary is, right? It has words and definitions, and you look\n", + "up the words to find the definitions. Here is how we create a dictionary in\n", + "Python: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Dictionary example\n", + "\n", + "# A dictionary of words for superior people\n", + "\n", + "superior_words = {\n", + " \"abecedarian\": \"a person who is learning the alphabet\",\n", + " \"blandishment\": \"flattering speech or actions designed to persuade\",\n", + " \"cacophony\": \"a harsh, discordant mixture of sounds\",\n", + " \"defenestration\": \"the act of throwing someone out of a window\",\n", + " \"egregious\": \"outstandingly bad; shocking\",\n", + " \"flagitious\": \"criminal; villainous\",\n", + " \"grandiloquent\": \"pompous or extravagant in language, style, or manner\",\n", + " \"hirsute\": \"hairy\",\n", + " \"ignominious\": \"deserving or causing public disgrace or shame\",\n", + " \"juxtapose\": \"to place side by side for contrast or comparison\",\n", + " \"sesquipedalian\": \"given to using long words\",\n", + " \"xerebrose\": \"dry, uninteresting\"\n", + "}\n", + "\n", + "# one way to look up a word, using the key and \"[]\"\n", + "word = \"cacophony\"\n", + "definition = superior_words[word]\n", + "print(f\"{word}: {definition}\")\n", + "\n", + "# another way to look up a word, using `.get()`\n", + "word = \"xerebrose\"\n", + "definition = superior_words.get(word)\n", + "print(f\"{word}: {definition}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The \"{}\" curly braces are used to create both `dict` and `set` objects. The difference is that the `dict` definition has pairs separated by `:`, which the set does not. So this is a set: \n", + "\n", + "```python\n", + "s = { 1, 2, 3, 4}\n", + "```\n", + "\n", + "but this is a dict:\n", + "\n", + "```python \n", + "d = { \n", + " 'a': 1, \n", + " 'b': 2,\n", + " 'c': 3\n", + " }\n", + "```\n", + "\n", + "And like the other containers, you can also use a constructor function and then add items:\n", + "\n", + "```python \n", + "d = dict()\n", + "d['a'] = 1\n", + "d['b'] = 2\n", + "d['c'] = 3\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The dictionary has a feature like the set: its keys ( the word part of the word/definition pair ) is also unique. So if you add\n", + "a key twice, it will only be stored once:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d = { \n", + " \"one\": 1, \n", + " \"one\": 10, \n", + " \"two\": 2,\n", + " \"two\": 20,\n", + " \"three\": 3,\n", + " \"three\": 30\n", + " }\n", + "\n", + "print(d) # Only stores the last value for the key" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hmmm ... we could use constructor functions to convert between other containers ... what happens if you try to convert a dict to another\n", + "container type?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d = { \n", + " 'a': 1, \n", + " 'b': 2,\n", + " 'c': 3\n", + " }\n", + "\n", + "l = list(d)\n", + "print(l)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hmmm ... it just used the keys? What happened to the values ( the \"definitions\" ) ? Well, you\n", + "need to use other methods to get those. Here are some of the access methods: \n", + "\n", + "* `dict.keys()`: Get only the keys.\n", + "* `dict.values()`: Get only the values. \n", + "* `dict.items()`: Get the keys and values as a collection of tuples. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Accessing dict keys and values\n", + "\n", + "d = { \n", + " 'a': 1, \n", + " 'b': 2,\n", + " 'c': 3\n", + "}\n", + "\n", + "print(d.keys())\n", + "print(d.values())\n", + "print(d.items())\n", + "\n", + "print()\n", + "\n", + "# Iterate over items in a dictionary\n", + "\n", + "for key, value in d.items():\n", + " print(f\"{key} = {value}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pay attention to this idiom: \n", + "\n", + "```python \n", + "for key, value in d.items():\n", + " print(f\"{key} = {value}\")\n", + "```\n", + "\n", + "This is one of the very common operations with a dict, iterating over keys and\n", + "values. You should also know how to get an index for the iteration, using\n", + "`enumerate()`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Enumerate keys and values\n", + "\n", + "for index, (key, value) in enumerate(d.items()):\n", + " print(f\"#{index} {key} = {value}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Removing items\n", + "\n", + "You can also remove items from collections:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "l = list(\"abcd\") # Make a list of characters from a string\n", + "\n", + "# Remove 'c' from the list\n", + "l.remove('c')\n", + "print(l)\n", + "\n", + "s = set(\"abcd\")\n", + "# Remove 'c' from the set\n", + "s.remove('c')\n", + "print(s)\n", + "\n", + "d = {\n", + " 'a': 1,\n", + " 'b': 2,\n", + " 'c': 3\n", + "}\n", + "\n", + "# To remove from a dict, use `del`\n", + "del d['c']\n", + "print(d)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Is it in there?\n", + "\n", + "You can use `in` to see if an item is in a collection. Use `not in` to check if it is not in the collection. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Check and see if something is in a collection\n", + "\n", + "l = list(\"abcd\")\n", + "print('a' in l, 'f' in l, 'g' not in l) # 'a' is in, but 'f' is not\n", + "\n", + "s = set(l)\n", + "print('a' in s, 'f' in s, 'g' not in s)\n", + "\n", + "d = {\n", + " 'a': 1,\n", + " 'b': 2,\n", + " 'c': 3\n", + "}\n", + "\n", + "# For dicts, 'in' checks for the existence of a key\n", + "print('a' in d, 'f' in d, 'g' not in d)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test Yourself\n", + "\n", + "Write a function, `check_funny_words(sentence)` to check if any of these words are in a sentence:\n", + "\n", + "* snollygoster\n", + "* skedaddle\n", + "* lollygag\n", + "* collywobble\n", + "\n", + "If the sentence has funny words, return \"Funny\" and a list of the funny word.\n", + "If not, return \"not funny\"\n", + "\n", + "Write a loop to call your function on each of the sentences in `funny_sentences`\n", + "and print the return value of the function " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "funny_sentences = [\n", + " \"The snollygoster tried to skedaddle before anyone noticed his mischief.\",\n", + " \"After a day of lollygagging, the children suddenly got the collywobbles from all the candy.\",\n", + " \"A kerfuffle broke out when the gobbledygook in the instructions confused everyone.\",\n", + " \"The politician was such a snollygoster that he could bamboozle anyone without breaking a sweat.\",\n", + " \"The nincompoop tried to bamboozle everyone with his ridiculous story.\",\n", + " \"We decided to skedaddle from the park when we saw the kids starting to lollygag near the mud puddles.\",\n", + " \"The sudden collywobbles made him want to skedaddle from the roller coaster line.\",\n", + " \"The teacher was flummoxed by the students' whippersnapper antics during the lesson.\"\n", + "]\n", + "\n", + "def check_funny_words(sentence):\n", + " \"\"\"\n", + " Checks if any funny words are present in the given sentence.\n", + "\n", + " Args:\n", + " sentence (str): The sentence to check for funny words.\n", + "\n", + " Returns:\n", + " str: If funny words are found, returns a string with the funny words separated by commas.\n", + " If no funny words are found, returns \"Not funny\".\n", + " \"\"\"\n", + " \n", + " # IMPLEMENT ME!\n", + "\n", + "for s in funny_sentences:\n", + " print(check_funny_words(s))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# How big is it?\n", + "\n", + "Use `len()` to see how many items are in a collection.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "c = \"Hello\"\n", + "l = list(c) # Make a list of characters from a string\n", + "\n", + "print(len(c), len(l))\n", + "\n", + "d = { \n", + " 'a': 1, \n", + " 'b': 2,\n", + " 'c': 3\n", + " }\n", + "\n", + "print(len(d))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Sorting collections\n", + "\n", + "Sorting puts the items in the collection into order. For numbers, that means\n", + "numerical order, and for string, alphabetic order. You can sort lists, but for\n", + "immutable collections you will produce a new collection that is sorted, while\n", + "the original collection will remain unsorted. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "l = list(\"gqycprc\")\n", + "\n", + "# Sort the list\n", + "l.sort()\n", + "print(l)\n", + "\n", + "# Use the sorted function to return a new sorted list\n", + "l = list(\"gqycprc\")\n", + "sorted_l = sorted(l)\n", + "print(l)\n", + "print(sorted_l)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.11" + }, + "syllabus": { + "uid": "VXQdZcqg" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lessons/40_Data_Structures_Func/30_Funny_Words_Db.py b/lessons/40_Data_Structures_Func/30_Funny_Words_Db.py new file mode 100644 index 00000000..d7b57f86 --- /dev/null +++ b/lessons/40_Data_Structures_Func/30_Funny_Words_Db.py @@ -0,0 +1,167 @@ +from guizero import App, Box, Text, TextBox, PushButton, ListBox, error + +""" +Funny Words Dictionary + +This program provides a graphical user interface (GUI) for managing a dictionary +of funny words and their definitions. Users can add new definitions, delete +existing definitions, and view the list of definitions in a listbox. + +The module uses the guizero library to create the GUI components and handle user +interactions. It defines several functions for adding and deleting definitions, +as well as checking if a definition is funny. The definitions are stored in a +global dictionary called 'db'. To use the application, run the script and a +window will appear with input fields for entering a word and its definition. +Clicking the 'Add' button will add the definition to the dictionary and update +the listbox. Selecting a definition from the listbox and clicking the 'Delete +Selected' button will remove the definition from the dictionary. + +The module has a limit of storing up to 5 definitions. If the limit is reached, +an error message will be displayed and new definitions will not be added. +""" + +# Implement the functions below + +def add_definition(db, key, value): + """ + Add a new definition to the database. + + Parameters: + - db (dict): The database to add the definition to. + - key (str): The key for the new definition. + - value (str): The value for the new definition. + + Returns: + - None + + If there are already 5 items in the database, an error message is displayed and the new item is not added. + """ + + # Check the limit + + # Set the item in the database + + pass + + +def delete_definition(db, key): + """ + Deletes the definition associated with the given key from the database. + + Args: + db (dict): The database containing the key-value pairs. + key: The key to be deleted from the database. + + Returns: + None + """ + + # Delete the item from db if it is present + + pass + + +def is_funny(definition): + """ + Check if the definition is funny, which means it contains one of the words: + + 'fun', 'funny', 'hilarious', 'amusing', 'pants', 'spleen' + + Args: + definition (str): The definition to check. + + Returns: + bool: True if the definition contains any of the funny words, False otherwise. + """ + + # Return True if the definition contains any of the funny words, False otherwise + + return False + +def update_listbox(db): + """ + Update the listbox with the current definitions in the database. + + Returns: + list of str: A list of strings containing the definitions to be displayed in the listbox. + """ + + # This function will return a list of definitions to be displayed in the listbox, like + # the one below. (For your function, you should set this list to the empty list) + l = [ + "Item 1: Fake Definition 1", + "Item 2: Fake Definition 2", + "Item 3: fake Definition 3" + ] + + # Add each definition to a string + # iterate over the dict's key-value pairs and turn them into + # strings, then add the strings to the list with .append() + + return l + +# ================================================================ + +# Function to add a definition + +def _add_definition(): + word = word_entry.value.strip() + definition = definition_entry.value.strip() + + + if word and definition: + if is_funny(definition): + definition = "😂 " + definition + " 🤡" + add_definition(db, word, definition) + _update_listbox(db) + word_entry.clear() + definition_entry.clear() + else: + error("Input Error", "Both fields must be filled out.") + +# Global dictionary to store definitions +db = {} + +# Function to update the listbox with current definitions +def _update_listbox(db): + listbox.clear() + for i in update_listbox(db): + listbox.append(i) + +# Function to delete a definition +def _delete_definition(): + selected_item = listbox.value + if selected_item: + word = selected_item.split(":", 1)[0].strip() + if word in db: + del db[word] + _update_listbox(db) + +# Main app +app = App(title="Funny Definitions", width=600, height=300) + +# Top pane for input +top_pane = Box(app, align="top", width="fill", border=True) + +Text(top_pane, text="Word:", align="left") +word_entry = TextBox(top_pane, width="10", align="left") +Text(top_pane, text="Definition:", width="10" , align="left") +definition_entry = TextBox(top_pane, width="25", align="left") +PushButton(top_pane, text="Add", width="5", align="bottom", command=_add_definition) + +# Bottom pane for displaying definitions +bottom_pane = Box(app, align="bottom", width="fill", height="fill", border=True) +listbox = ListBox(bottom_pane, items=[], width="fill", height="fill") +PushButton(bottom_pane, text="Delete Selected", command=_delete_definition) + +# Function to handle enter key press +def handle_enter(event): + if event.tk_event.keysym == "Return": + _add_definition() + +# Bind enter key press event to handle_enter function +app.when_key_pressed = handle_enter + +_update_listbox(db) # Initial update of listbox + +app.display() \ No newline at end of file diff --git a/lessons/40_Data_Structures_Func/40_Splat_Comprehension.ipynb b/lessons/40_Data_Structures_Func/40_Splat_Comprehension.ipynb new file mode 100644 index 00000000..06f40ad2 --- /dev/null +++ b/lessons/40_Data_Structures_Func/40_Splat_Comprehension.ipynb @@ -0,0 +1,632 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tic Tac Toe\n", + "\n", + "In the nex project, you will implemement a Tic Tac Toe game, but to write a Tic Tac Toe game, we will need to learn about multi-dimensional\n", + "arrays. A multidimensional array in Python is really just a list of lists:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# A 2 dimensional array is an array of arrays. Here is an example:\n", + "\n", + "row1 = [1, 2, 3]\n", + "row2 = [4, 5, 6]\n", + "row3 = [7, 8, 9]\n", + "\n", + "two_dimensional_array = [\n", + " row1, \n", + " row2, \n", + " row3\n", + " ]\n", + "\n", + "print(two_dimensional_array)\n", + "\n", + "# Or , The more compact usual way: \n", + "\n", + "two_dimensional_array = [\n", + " [1, 2, 3],\n", + " [4, 5, 6],\n", + " [7, 8, 9]\n", + " ]\n", + "\n", + "# Now we can use '[][]' to access the elements of the 2D array.\n", + "\n", + "print(two_dimensional_array[0][0]) # 1\n", + "print(two_dimensional_array[1][2]) # 6\n", + "print(two_dimensional_array[2][0]) # 7" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "THe `[][]` construct is for indexing in two dimensions. To understand the two\n", + "dimensional access, think about what the first and second access return. \n", + "\n", + "Can you guess what the first index on the array will return? What do you think this will print out?\n", + "\n", + "```python \n", + "\n", + "print( two_dimensional_array[1] )\n", + "\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Try it! \n", + "# See what print( two_dimensional_array[1] ) produces\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you have a multi-dimensional array, the first index operation returns a list, which is the row. Then, the second index operations works on the row to return a column, so `[][]` expands to :\n", + "\n", + "```python\n", + "l = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]\n", + "row_num = 2\n", + "col_num = 1\n", + "\n", + "# The typical way:\n", + "v = l[row_num][col_num]\n", + "\n", + "# Expand it out\n", + "row = l[row_num]\n", + "v = row[col_num]\n", + "\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Who Won ?\n", + "\n", + "When implementing Tic Tac Toe the important thing we have to do is figure out who won. Who is the winner? It's the player who has 3 of the players tokens in any tow, column or diagonal. How do we get a row? Well, that's easy, it is just a single index on the board:\n", + "\n", + "```python \n", + "board = [\n", + " [1, 2, 3],\n", + " [4, 5, 6],\n", + " [7, 8, 9]\n", + " ]\n", + "\n", + "first_row = board[0]\n", + "\n", + "```\n", + "\n", + "That was easy .. but how do we get the first column, with all three values? You\n", + "can probably come up with a manual way, but we'll show you the most Pythonic\n", + "way: you transpose the board and take a row. Transposing a matrix means swapping\n", + "rows an columns, so if you transpose, accessing a row will actually get you a\n", + "column, and in Python we can do this with `zip()`\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def pretty_print_2d(a):\n", + " \"\" \"Prints a 2D array in a pretty way\" \"\"\n", + " for row in a:\n", + " print(row)\n", + "\n", + "board = [\n", + " [1, 2, 3],\n", + " [4, 5, 6],\n", + " [7, 8, 9]\n", + " ]\n", + "\n", + "pretty_print_2d(board)\n", + "print()\n", + "\n", + "transposed = list(zip(*board)) # <--- HERE IS THE MAGIC\n", + "pretty_print_2d(transposed)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "See, the zip operation turned rows into columns, and columns into rows: in the\n", + "original, \"[1,2,3]\" is across the top in in the bottom \"(1,2,3)\" is down the\n", + "side. But ... one difference, the top has \"[]\", so it is an array of lists, but\n", + "the bottom has '()', so it is an array of tuples. We'll fix that later, for now\n", + "let's learn how `zip()` transposes. \n", + "\n", + "Here is the line of code: \n", + "\n", + "```python \n", + "list(zip(*board))\n", + "```\n", + "\n", + "The first thing to talk about is the `*`. In this usage, it is known as the\n", + "'splat operator', and it is unpacking `board` into the argument list of the zip\n", + "function. The `board` variable is iterable, and the splat takes each item of \n", + "`board` and makes a seperate argument for it. So, this line of code is equavalent to:\n", + "\n", + "```python \n", + "list(zip(board[0],board[1],board[2])))\n", + "```\n", + "\n", + "And that is equivalent to:\n", + "\n", + "```python \n", + "list(zip([1, 2, 3],[4, 5, 6],[7, 8, 9])))\n", + "```\n", + "\n", + "Now what does `zip()` do? It takes all of the first items of it's aguments, then all of the second, then all of the third, etc. \n", + "Let's try that: \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for e in zip([1, 2, 3],[4, 5, 6],[7, 8, 9]):\n", + " print(e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " See, the first tuple we get is the first item of each of the lists in the `zip()` arguments, the second item is the second, etc. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If that is hard to see, lets color the numbers: \n", + "\n", + "code:\n", + "
\n",
+        "for e in zip([1, 2, 3], [4, 5, 6],[7, 8, 9]):\n",
+        "    print(e)\n",
+        "
\n", + "\n", + "output:\n", + "
\n",
+        "(1, 4, 7)\n",
+        "(2, 5, 8)\n",
+        "(3, 6, 9)\n",
+        "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "But, we don't want a tuple of tuples, we want a list of lists, so we have to do some converstion. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# First transpose:\n", + "t = zip(*board)\n", + "\n", + "l = []\n", + "# convert each row from tuple to list\n", + "for e in t:\n", + " l.append(list(e))\n", + "\n", + "pretty_print_2d(l)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Introducing Comprehensions\n", + "\n", + "That conversion code is kinda ugly, but we can make it much prettier and more Pythonic with a list comprehension. Here is what that looks like: \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "l = [list(e) for e in zip(*board)]\n", + "pretty_print_2d(l)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You certainly recognize \"[]\" for making a list, but what's the code inside???? The basic syntax here is just a for loop, with an extra expression: \n", + "\n", + "```python \n", + "[ for item in list ]\n", + "```\n", + "\n", + "We know what the `for item in list` is, so we are really just adding the\n", + "`` part, and all that is doing is being added to a list. So these\n", + "two bits of code are the same: \n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# The old way to square every number:\n", + "\n", + "nums = [1, 2, 3, 4, 5]\n", + "\n", + "squared = []\n", + "for n in nums:\n", + " expression = n * n\n", + " squared.append(expression)\n", + "\n", + "print(squared)\n", + "\n", + "# The comprehension way:\n", + "\n", + "squared = [n * n for n in nums]\n", + "print(squared)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So, the comprehension is really just a nicer syntax for a certain kind of `for` loop that appends items to a list. Thre is a lot more to comprehensions, of course, but this is enough to get started. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Yes, but Who Won?\n", + "\n", + "So now we know an easy way to find the columns to check who won: you write a\n", + "function to figure out who won by row, then you use that function first to chech\n", + "all of the rows, then transpose the board to check all of the columns. \n", + "\n", + "But, we still have to check the two diagonals. Let's look at the coordinates of the diagonals.\n", + "if your board is:\n", + "\n", + "```\n", + "[1, 4, 7]\n", + "[2, 5, 8]\n", + "[3, 6, 9]\n", + "```\n", + "\n", + "Then the two diagonals are: `[1,5,9]', and '[7,5,1]'. Let's try to use a comprehension to \n", + "find the diagonals: \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Text Yourself\n", + "# In the comprehensions below, replace the ...\n", + "# with code that will produce the expected output.\n", + "\n", + "board = [\n", + " [1, 2, 3],\n", + " [4, 5, 6],\n", + " [7, 8, 9]\n", + " ]\n", + "\n", + "# Uncomment below and replace the ... with code that will produce the expected output.\n", + "#d1 = [ board[...][...] for i in range(3) ]\n", + "#assert d1 == [1, 5, 9]\n", + "\n", + "#d2 = [ board[...][...] for i in range(3) ]\n", + "#assert d2 == [3, 5, 7]\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hint: three of the `...` are all replaced by the same thing. It will help if\n", + "you list out the coordinates of the diagonals, which are (0,0), (1,1) .... If\n", + "you can't get the right comprehension, you can also construct a new 3 item\n", + "list from getting each dialgonal cell from the board with 2d indexing, \n", + "like ` l = [ board[0][0],board[1][1], ...]`\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ok, now we have explained: \n", + "\n", + "* How to get each row as a list\n", + "* How top get each column as a list\n", + "* How to get both diagonals. \n", + "\n", + "Now let's look as some Pythonic ways to figure out who won. What things are true\n", + "about a row where 'X' won? Let's look as some example code that will maybe given you some ideas. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x_won = ['x','x','x']\n", + "o_won = ['o','o','o']\n", + "r1 = ['x','x','o']\n", + "r2 = ['x','o','o'] \n", + "r3 = ['x','o','x'] \n", + "r4 = ['o','x','x'] \n", + "\n", + "# The all() function returns True if all elements of the iterable are true.\n", + "print('\\n1 ===')\n", + "print( all([e == 'x' for e in x_won]) ) \n", + "print( all([e == 'o' for e in x_won]) ) \n", + "print( all([e == 'x' for e in r1]) ) \n", + "\n", + "print('\\n2 ===')\n", + "print(set(x_won))\n", + "print(set(o_won))\n", + "print(set(r1))\n", + "print(set(r2))\n", + "\n", + "print('\\n3 ===')\n", + "print(len(set(x_won)))\n", + "print(len(set(o_won)))\n", + "print(len(set(r1)))\n", + "print(len(set(r2)))\n", + "\n", + "print('\\n4 ===')\n", + "print(set(x_won) == {'x'})\n", + "print(set(o_won) == {'o'})\n", + "print(set(r1) == {'x'})\n", + "print(set(r2) == {'x'})\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Does that give you any ideas? Read the code carefully and then select a way to figure out which play won for a row. \n", + "\n", + "# Test Yourself\n", + "\n", + "Write the functions described below, then test your functions on the provided test code. \n", + "\n", + "Hint: The logic value of `None` is `False`, but the logic value of 'x' and 'o' are both `True`\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x_wins_boards = [\n", + " # x wins in row 1\n", + " [\n", + " ['o','' ,'o'],\n", + " ['x','x','x'],\n", + " ['o','' ,''],\n", + " ],\n", + " # x wins in col 2\n", + " [\n", + " ['o','' ,'x'],\n", + " ['' ,'o','x'],\n", + " ['o','' ,'x'],\n", + " ],\n", + " # x wins in the first diagonal\n", + " [\n", + " ['x','' ,'o'],\n", + " ['' ,'x','o'],\n", + " ['o','' ,'x'],\n", + " ]\n", + "]\n", + "\n", + "o_wins_boards = [\n", + " # o wins in row 0\n", + " [\n", + " ['o','o','o'],\n", + " ['' ,'x',''],\n", + " ['x','' ,'x'],\n", + " ],\n", + " # o wins in col 1\n", + " [\n", + " ['x','o','x'],\n", + " ['' ,'o',''],\n", + " ['' ,'o','x'],\n", + " ],\n", + " # o wins in the second diagonal\n", + " [\n", + " ['x','' ,'o'],\n", + " ['' ,'o',''],\n", + " ['o','x','x'],\n", + " ]\n", + "]\n", + "\n", + "no_winner_boards = [\n", + " # No winner example 1\n", + " [\n", + " ['x','o','x'],\n", + " ['o','x','o'],\n", + " ['o','x','o'],\n", + " ],\n", + " # No winner example 2\n", + " [\n", + " ['x','o','x'],\n", + " ['x','o','o'],\n", + " ['o','x','x'],\n", + " ],\n", + " # No winner example 3\n", + " [\n", + " ['x','o','x'],\n", + " ['x','x','o'],\n", + " ['o','x','o'],\n", + " ]\n", + "]\n", + "\n", + "\n", + "# First, write a function to check if a player has won on a row, column, or diagonal.\n", + "# Ths function takes a 3 element iterable and returns the winner. \n", + "\n", + "\n", + "def check_row(l):\n", + " \"\"\"Check if a player won on a row\n", + " Args:\n", + " l: a 3 element iterable\n", + " \n", + " Returns:\n", + " The winner's token ( x or o ) if there is one, otherwise None\n", + " \"\"\"\n", + " \n", + " return None\n", + "\n", + "\n", + "# Now, write a function that takes a 2D array and checks if there is a winner.\n", + "# This function should call the check_winner function for each row, column, and diagonal.\n", + "\n", + "def check_board(board):\n", + " \"\"\"Check if a player has won on a board\n", + " Args:\n", + " board: a 3x3 2D array\n", + " \n", + " Returns:\n", + " The winner's token ( x or o ) if there is one, otherwise None\n", + " \"\"\"\n", + "\n", + " return None\n", + "\n", + "\n", + "# Next, write some test code to test your functions. You should start by testing rows, like this\n", + "# \n", + "\n", + "# board = x_wins_boards[0]\n", + "# check_row( board[0]) # Should be None\n", + "# check_row( board[1]) # Should be 'x'\n", + "#\n", + "# Test the rows to determine if your check_rows() function works. \n", + "# \n", + "# Then, do the same checks with check_board()\n", + "#\n", + "# Finally,write a loop to check that the winner of all of the x_wins_boards is 'x', \n", + "# the winner of all of the o_wins_boards is 'o', and the winner of all of the no_winner_boards is None.\n", + "# You might use a comprehension, like [ check_board(board) for board in x_wins_boards ] \n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Final Test\n", + "# If all of your functions are working this code should pass:\n", + "\n", + "assert all([ check_board(board) == 'x' for board in x_wins_boards ] )\n", + "assert all([ check_board(board) == 'o' for board in o_wins_boards ] )\n", + "assert all([ check_board(board) is None for board in no_winner_boards ] )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Make It Better!\n", + "\n", + "Once you get the `check_board(board)` function working, lets try to make it better. See if you can run just one loop through all of the rows, columns and diagonal and have just one return. Here is some code that will give you a hint: \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "l = [\n", + " [1, 2, 3],\n", + " [4, 5, 6],\n", + " [7, 8, 9]\n", + " ]\n", + "\n", + "def transpose(a):\n", + " return list(zip(*a))\n", + "\n", + "m = l[:] # Copy the whole list \n", + "m.extend(transpose(l)) # Add all of the items from transpose to m, a bit like m += transpose(l)\n", + "\n", + "for e in m:\n", + " print(e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You've done a lot of work! So it is definitely time to [check in your code.](https://curriculum.jointheleague.org/howto/checkin_restart.html)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + }, + "syllabus": { + "uid": "mU94qia6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/lessons/40_Data_Structures_Func/50_Tic_Tac_Toe.py b/lessons/40_Data_Structures_Func/50_Tic_Tac_Toe.py new file mode 100644 index 00000000..9c90264b --- /dev/null +++ b/lessons/40_Data_Structures_Func/50_Tic_Tac_Toe.py @@ -0,0 +1,107 @@ +#imports +from guizero import App, Box, PushButton, Text, info + +X_MARK = "X" +O_MARK = "O" + +# Implement check_row() and check_win() to allow the game to check if a player has won +# IMPORTANT! In your code, you should use the constants X_MARK and O_MARK instead of the strings "x" and "o" + +def check_row(l): + """Check if a player won on a row + Args: + l: a 3 element iterable + + Returns: + The winner's token ( x or o ) if there is one, otherwise None + """ + + return None + +def check_win(board): + """Check if a player has won on a board + Args: + board: a 3x3 2D array + + Returns: + The winner's token ( x or o ) if there is one, otherwise None + """ + + return None + +# The following code is the main part of the program. It creates a GUI for the +# game and handles the game logic. Implement the functions above first, then +# after your program is working you can try chaning the code below. + +class TicTacToe: + """A Simple Tic Tac Toe game""" + + app = None + board = None # The storage for user's markers + buttons = None # Holds UI elements for the board + board_pane = None # + message = None + turn_n = 0 + turn = X_MARK + + def __init__(self, win_func=check_win): + self.board = None # The stoage for user's markers + + self.app = App('Tic Tac Toe Game', bg='burlywood') + self.board_pane = Box(self.app, layout='grid') # Holds UI elements for the board + self.message = Text(self.app, text="It is your turn, " + self.current_turn) + + self.reset_button = PushButton(self.app, text='Reset', command=self.reset) + + self.message.text_color = "green" + + self.win_func = win_func + + self.reset() + + def reset(self): + """Reset the game state""" + self.turn_n = 0 + self.turn = X_MARK + self.message.value = "It's your turn, " + self.current_turn + + self.board = [[None for _ in range(3)] for _ in range(3)] + self.buttons = [[None for _ in range(3)] for _ in range(3)] + + # generate a 3x3 grid + for x in range(3): + for y in range(3): + self.buttons[x][y] = PushButton(self.board_pane, text='', grid=[x, y], width=3, command=self.do_turn, args=[x,y]) + + def start(self): + """Start the game""" + self.app.display() + + @property + def current_turn(self): + """Return the current player's marker, based on the current turn number""" + return [X_MARK, O_MARK][self.turn_n % 2] + + def do_turn(self, x, y): + """Handle one player turn, and return a marker if one of the players won""" + self.board[x][y] = self.current_turn + self.buttons[x][y].text = self.current_turn + self.buttons[x][y].disable() + + self.turn_n += 1 + self.message.value = f"It's your turn, {self.current_turn}" + + winner = self.win_func(self.board) + + if winner: + self.message.value = f"Player {winner} won!" + info("Tic-tac-toe",f"Player {winner} won!") + for row in self.buttons: + for button in row: + button.disable() + elif self.turn_n == 9: + self.message.value = "It's a draw!" + info("Tic-tac-toe","It's a draw!") + +ttt = TicTacToe(check_win) +ttt.start() diff --git a/lessons/40_Data_Structures_Func/README.md b/lessons/40_Data_Structures_Func/README.md new file mode 100644 index 00000000..b9668e38 --- /dev/null +++ b/lessons/40_Data_Structures_Func/README.md @@ -0,0 +1,11 @@ +--- +uid: fDPxSid0 +--- + +# PCEP Alignment + + * PCEP-30-02 4.3 – Collect and Process Data Using Dictionaries + * Dictionaries: Building, Indexing, Adding and Removing Keys + * Iterating Through Dictionaries and Their Keys and Values + * Checking the Existence of Keys + * Methods: `keys()`, `items()`, and `values()` \ No newline at end of file diff --git a/lessons/50_Projects/10_Hotel_Management.md b/lessons/50_Projects/10_Hotel_Management.md new file mode 100644 index 00000000..e32106c2 --- /dev/null +++ b/lessons/50_Projects/10_Hotel_Management.md @@ -0,0 +1,49 @@ +# Hotel Management + +The purpose of this program is to make sure you have an understanding of the +topics you learned in Python Apprentice. This is going to be your 1st program +you write all by yourself, imagine someone hired you to create a hotel +management program. + +## Getting Started: +* Under projects create a new file and name it hotel_management.py +* Create a docstring (it's the triple quotes “”” stuff goes inside “””) +* Take some time to organize your thoughts on how the program will be laid out + and what you will need (functions, imports, loops, etc.) +* Write down your thoughts as a list or instructions to yourself inside the docstring +* Add your imports (Tkinter or whatever you need) +* Code away, make sure to keep it organized so you know where things are and + what they do. + * Separate different functionalities into their own functions. + + +## Requirements: +* Should run in 1 While Loop +* Nearly all functionality should be in functions which are called from a + `main()` function. +* The functions should, mostly, return something + * For instance if I had a function called add, it should return the sum rather + than just doing the operation or printing it. + * Remember, with Python you can set a variable to a return value of a + function, so: my_age = add(10, 5) +* Add arguments to your functions as needed +* Must contain and iterate over these data structures: + * List + * Dictionary + * Tuple + +## Functionality Requirements: +* Must be interactive, either in the command line with print() and input() or + with Tkinter +* Check guests in and out +* Charge guests for their room(s) +* Multiple room check in +* Multiple Night Check in +* Add 1 new feature of your choice + * Ex. Upgrade room, room service, spa package, etc. + + +Have Fun!!! + + + diff --git a/lessons/50_Projects/20_Random_Walk.py b/lessons/50_Projects/20_Random_Walk.py new file mode 100644 index 00000000..51c445e7 --- /dev/null +++ b/lessons/50_Projects/20_Random_Walk.py @@ -0,0 +1,70 @@ +""" A simple turtle program that moves the turtle randomly in the grid + +This program will perform a "random walk" by moving the turtle randomly in the grid. + +Implement the random_walk function that will move the turtle randomly in the grid. + +""" + +import turtle +import random + +# Set up the screen +screen = turtle.Screen() +screen.setup(width=600, height=600) +screen.bgcolor("white") + +# Set up the turtle +walker = turtle.Turtle() +walker.shape("turtle") +walker.penup() +walker.speed(0) # Set to the maximum speed +walker.goto(0, 0) # Start in the middle of the grid +walker.pendown() + +# Function to move the turtle randomly in the grid +def random_walk(walker, steps): + """ Implement a random walk for the turtle + + The turtle will move on a grid, taking a random step in one of the four directions + + For each of the steps, the turtle will move in a random direction (N, E, S, W) + a fixed number of steps. Fur instance, the turtle should move 10 pixels each time, but + in a random, direction. + + Args: + walker (turtle.Turtle): The turtle object + steps (int): The number of steps to take + + """ + + # You can make the turle move randomly in either of two ways: randomly choosing a direction + # or randomly choosing a angle to turn. You can use random.choice() to select a random element + # from a list, like this: + # direction = random.choice(["N", "E", "S", "W"]) + # or + # angle = random.choice([0, 90, 180, 270]) + # + # Or you can use random.randint() to generate a random integer between two values, like this: + # angle_index = random.randint(0, 4) + # directions = ["N", "E", "S", "W"] # or directions = [0, 90, 180, 270] + # direction = directions[angle_index] + # + # To set the turtle's heading, you can use the setheading() method, like this: + # walker.setheading(angle) # North + # + # you can use the right() or left() methods to turn the turtle, like this: + # walker.right(angle) # Go straight + # + # + # Read one of the past turtle programs to see how to use these methods. + + # Your code here + + + +# Start the random walk +random_walk(walker, 200) + +# Close the turtle window on click +screen.exitonclick() diff --git a/lessons/50_Projects/README.md b/lessons/50_Projects/README.md new file mode 100644 index 00000000..5fb04ced --- /dev/null +++ b/lessons/50_Projects/README.md @@ -0,0 +1,9 @@ + +--- + +uid: rLq5eVeW + +--- + +# Projects + diff --git a/lessons/README.md b/lessons/README.md new file mode 100644 index 00000000..7fd50a0b --- /dev/null +++ b/lessons/README.md @@ -0,0 +1,11 @@ +--- +uid: 283c41e4-8abe-49bd-9335-e19ba693277b +--- + +# Python Apprentice + +The League's Python Apprentice curriculum introduces students to the core feature +of Python using professional tools like Github and Visual Studio Code. The +course is aligned with the [PCEP™ – Certified Entry-Level Python Programmer](https://pythoninstitute.org/pcep) +exam from the Python Institute, so students who have completed this course +will be familiar with all of material on the test. \ No newline at end of file