{ "cells": [ { "cell_type": "markdown", "id": "9965f1b0", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-3b587ecf818e3119", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Exercises\n", "\n", "For the exercises on this page, you will need to use NaNoPy package.\n", "\n", "Each exercise carries the difficulty level indication:\n", "- [*] Easy\n", "- [**] Moderate" ] }, { "cell_type": "markdown", "id": "97601eca", "metadata": {}, "source": [ "`````{exercise} [*] Diagonal red line pixel by pixel\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/01_Diagonal_line.py>`\n", "\n", "Write a program that draws a diagonal red line by using the writer's `drawPixel` function.\n", "`````" ] }, { "cell_type": "markdown", "id": "f6ef0c34", "metadata": {}, "source": [ "`````{exercise} [*] Diagonal red line with drawLine\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/02_Diagonal_line_2.py>`\n", "\n", "Drawing lines pixel by pixel is not the most efficient way of doing so. Write a program that draws a \n", "diagonal line using the writer’s `drawLine` function.\n", "\n", "```\n", "pen.drawLine (x1, y1, x2, y2, c)\n", "```\n", "\n", "The first two arguments (`x1` and `y1`) indicate the origin of the line. The next two arguments (`x2` and `y2`) \n", "are the coordinates of the end of the line. The last argument (`c`) is the colour of the line. \n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "b7ed7212", "metadata": {}, "source": [ "`````{exercise} [*] Changing colours\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/AI_integration/Miyase/01_Coloured_lines.py>`\n", "\n", "The following code gives an error, try to ask AI to review and correct it for you. \n", "Then answer the following questions:\n", "\n", "```\n", "from NaNoPy import *\n", "\n", "# Set up canvas\n", "xSize = 400\n", "ySize = 400\n", "screen = canvas(\"Crossing Diagonals\", xSize, ySize)\n", "pen = writer(screen)\n", "\n", "# Draw first diagonal: top-left to bottom-right (pink)\n", "for i in range(min(xSize, ySize)):\n", " pen.drawPixel(i, i, color().pink)\n", "\n", "# Draw second diagonal: top-right to bottom-left (orange)\n", "for i in range(min(xSize, ySize)):\n", " pen.drawPixel(xSize - i - 1, i, color().orange)\n", "\n", "# Update the display\n", "screen.update()\n", "\n", "# Keep the window open\n", "screen.keepwindow()\n", "```\n", "\n", "1. Was AI able to correct it for you?\n", "\n", "2. Now try and solve it yourself (Hint: the error mentions a problem with the \n", "\"color\" object, check the definition of `color()` in the NaNoPy package).\n", "\n", "3. What was the issue? Why do you think AI might be unable to solve it for you? \n", "\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "041f83a2", "metadata": {}, "source": [ "`````{exercise} [*] Random lines\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/03_Random_lines.py>`\n", "\n", "Write a program that draws several lines with random beginning and end points. Make sure each line starts \n", "and ends within the screen. \n", "\n", "Hint: Make use of the **random package** in your code. Two examples are shown below: \n", "\n", "```\n", "import random as rnd \n", " \n", "# Return random number between 0.0 and 1.0: \n", "rnd.random() \n", " \n", "# Return an integer between -2 and 2 (both included): \n", "rnd.randint(-2,2) \n", "```\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "b0854956", "metadata": {}, "source": [ "`````{exercise} [*] Blue circle\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/04_Blue_circle.py>`\n", "\n", "Write a program that draws, centred on the screen, a blue circle with a radius of 50 pixels using the \n", "writer’s `drawCircle` function:\n", "\n", "```\n", "pen.drawCircle (x, y, r, c, f)\n", "```\n", "\n", "The first two arguments (`x` and `y`) specify the centre of the circle. The third argument is the radius of \n", "the circle. The fourth argument specifies the colour, and the last argument is a Boolean to specify \n", "whether the circle should be filled or not. \n", "\n", "Five seconds after drawing the circle, the screen should be cleared. The code below shows you how \n", "to how **delay** (pause in milliseconds) and **then clear** the screen: \n", "\n", "```\n", "screen.pause(5000) \n", "screen.clear() \n", "screen.update() # The screen needs to be updated to see the effect of the clearing \n", "screen.keepwindow()\n", "```\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "5240041d", "metadata": {}, "source": [ "`````{exercise} [*] Yellow flashing light\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/05_Yellow_flashing_light.py>`\n", "\n", "Write a program that simulates a yellow flashing light in the middle of the graphical window that \n", "flashes until you stop the program. \n", "\n", "Hint: use an infinite `while` loop (`while screen.running(): . . . `), this will stop the program from running \n", "when the window is closed. A `while` loop will perform its code as long as the condition you state is true. \n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "3163ad22", "metadata": {}, "source": [ "`````{exercise} [**] Moving particles\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/06_Moving_particles.py>`\n", "\n", "**Exercise A:**\n", "Write a program, using the writer tool, that draws a red circle with a radius of 25 pixels at a random \n", "position on the graphical window. Each time you re-run the program, the position should be different (random). Make sure the circle always fits completely within the screen.\n", "\n", "**Exercise B:**\n", "Extend your code from exercise A such that it draws 100 red circles with radiuses of 5 pixels at random positions on the \n", "graphical window. Your program should incorporate: \n", "• Lists for the `x` and `y` coordinates. \n", "• A loop to fill the list with random coordinates.\n", "• A second loop to draw the circles.\n", "\n", "**Exercise C:**\n", "Extend your code from exercise B such that it draws a 100 red circles. Every 100 ms a new circle should be added at a random position within the graphical window. \n", "\n", "**Exercise D:**\n", "Extend your code from exercise C such that it draws 100 red circles one by one with 100 ms intervals at random positions on the graphical window, but now each time when a new circle is drawn, all previous circles should move \n", "one pixel down. \n", "\n", "You can use a nested `for` loop: the outer loop determines the number of circles to be drawn and in the inner \n", "loop those circles will be drawn. \n", "`````" ] }, { "cell_type": "markdown", "id": "1196400f", "metadata": {}, "source": [ "`````{exercise} [**] Simulation of moving objects\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/07_Moving_objects.py>`\n", "\n", "In this exercise, you'll be simulating the movement of objects through 2D space, such\n", "as a bouncing ball as well as random diffusion.\n", "\n", "The code below simulates a ball moving from the left to the right side of the graphical window:\n", "\n", "```\n", "xSize = 800 \n", "ySize = 600 \n", "ballx = 1 \n", "bally = 300 \n", "dx = 1.0 \n", "nsteps = 1000 \n", " \n", "c = color().green \n", " \n", "screen = canvas(\"title\", xSize, ySize) \n", "pen = writer(screen) \n", " \n", "for i in range(nsteps): \n", " ballx = ballx + dx \n", " pen.drawCircle(ballx, bally, 5, c, True) \n", " screen.update() \n", " screen.pause(5) \n", " screen.clear() \n", "\n", "screen.keepwindow() \n", "```\n", "\n", "**Exercise A:**\n", "Run the code above and observe the result. \n", "Then increase and decrease the speed at which the ball moves by modifying the value for `dx`.\n", "\n", "**Exercise B:**\n", "Extend the code such that the ball initially moves very fast, then gradually slows down before finally \n", "stopping at the right border of the graphical window, by making `dx` depend on the position of the ball \n", "within the graphical window. \n", "\n", "**Exercise C:**\n", "Extend the code such that the ball moves from top to bottom. Add a variable named `dy`.\n", "\n", "**Exercise D:**\n", "Extend the code such that the ball moves in a diagonal line over the graphical window. \n", "`````" ] }, { "cell_type": "markdown", "id": "7aa0cb84", "metadata": {}, "source": [ "`````{exercise} [**] Keeping an object within the screen\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/08_Object_within_screen.py>`\n", "\n", "In the previous exercise, you made the ball move over the screen, but the code was written in such a \n", "way that the ball moved from left to right, then stopped at the end of the graphical window. When \n", "simulating a less regulated movement of a ball, the path is less predictable or even unpredictable, so \n", "containing the ball inside the graphical window should be programmed in a different way. \n", "\n", "**Exercise A:**\n", "The algorithm for bouncing is very simple: when the ball reaches the top or bottom border of the \n", "graphical window, change the sign of the displacement in vertical direction (`dY = -dY`). When the ball \n", "bounces to the left or right side of the window, change the sign of the horizontal displacement (`dX`). \n", " \n", "Write a Python program in which a ball moves in a diagonal line at constant speed and bounces when it \n", "reaches one of the borders of the graphical window. The ball should keep moving until the graphical \n", "window is closed. Try different angles of movement. \n", "\n", "**Exercise B:**\n", "Extend your code from exercise A such that it simulates the bouncing of a ball in the \n", "presence of gravity: decrease the ball displacement in the vertical direction when the ball is moving \n", "upwards, and increase the ball displacement in the vertical direction when the ball is moving \n", "downwards by subtracting a small value from `dY` (e.g., `dY = dY - 0.1`). \n", "If the ball bounces higher each step, adjust the program so that the peaks are lower each time the \n", "ball bounces.\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "6399011e", "metadata": {}, "source": [ "`````{exercise} [**] Random particle diffusion\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/09_Particle_diffusion.py>`\n", "\n", "In this exercise, you will simulate the random movement of a particle.\n", "\n", "**Exercise A:**\n", "Generate random values for `dX` and `dY` between, for instance, -5 and 5. The particle should not be \n", "allowed to move outside the graphical window. You can change the speed at which the particle moves \n", "by varying the range of your random values.\n", "\n", "**Exercise B:**\n", "Extend your code such that instead of one particle,your program works with 100 particles and \n", "makes them move randomly. \n", "\n", "Hints: \n", "- You’ll need a list with the `x` coordinates for the particles, and a list with the `y` coordinates for the \n", "particles. \n", "- Perform separate tasks in separate loops. \n", "- When you update your graphical window for every particle individually, your program will slow \n", "down. To avoid this, first change the coordinates of all particles and draw them to the graphical \n", "window before updating it.\n", "`````" ] }, { "cell_type": "markdown", "id": "cb5480cd", "metadata": {}, "source": [ "`````{exercise} [**] Particle collision\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/10_Collision.py>`\n", "\n", "**Exercise A:**\n", "Write a program where two different types of particles diffuse randomly within the graphical window. \n", "Use ten particles of each type, where each type has its own colour, size, and speed. \n", " \n", "Hint: Store the properties of each particle in a list. Because the properties are different types of \n", "variables, create a list for each property. For instance, one list to store the sizes of all 20 particles, another list \n", "to store the colors of all the 20 particles, etc.\n", "\n", "**Exercise B:**\n", "Extend your code such that the particles seize to move when they meet/collide with a particle of the other type. We define meeting/collision as the distance of less than 15 coordinate units. Use the following equation of Pythagoras to calculate the distance `d` between two particles `P` and `Q`: \n", "\n", "$d = \\sqrt{(Px - Qx)^2 + (Py - Qy)^2}$\n", " \n", "Hints: \n", "- In case it takes too long before particles stop, increase the distance for collision. \n", "- In exercise A, you’ve created multiple lists in which you store the different properties of each \n", "particle. In that exercise it might seem convenient to create a different lists per particle type, but would \n", "that still be convenient if you had, e.g., 300 different types of particles, all interacting with each other? \n", "Instead, try to see the type of a particle as a \"property\" of being of a different type. So, you can create a list in \n", "which you store the type of each particle (particle type list), a list to store the sizes of all the particles (particle size list), a list to store the shapes of all the particles (particle shape list), a list to store colours (particle colour list), etc. \n", "\n", "**Exercise C:**\n", "Extend your code such that it only stops particles from moving when they meet a particle of the other type \n", "that is moving as well (with a distance less than 5 coordinate units). Increase the number of particles \n", "and change the ratio between the two types to 40:60. \n", "\n", "Hint: use an extra list in which you store the property of whether a particle is moving. \n", "\n", "**Exercise D:**\n", "Extend your program such that if a particle binds (meets) a particle of the other type, \n", "it should change colour, stop moving, and stay bound for 50 \n", "timesteps. After those 50 timesteps, the particles should \n", "again change colour and start moving again, but remain \n", "unable to bind again for another 20 timesteps. After those \n", "20 timesteps, the particles should go back to their original \n", "color and be able to bind again.\n", "\n", "```{figure} images/exercise10.png\n", "---\n", "height: 400px\n", "name: collision\n", "---\n", "```\n", "\n", "Hint: Create an extra variable (list) containing a property of the particle keeping track of the passed\n", "runs of the `while` loop. This will help to keep track of the timesteps in which the particle is bound or unable to\n", "bind.\n", "\n", "**Exercise E:**\n", "Extend your code such that it lets particles bind with a probability of 0.1 per timestep and release with a probability of 0.01 per timestep. Notice that you will need to know which particles are bound together to release them both at\n", "the same time step.\n", "\n", "Hint: Use `random` function to create a probability to test.\n", "\n", "`````" ] }, { "cell_type": "markdown", "id": "d914c809", "metadata": {}, "source": [ "`````{exercise} [**] Escape the container and monitor the situation\n", ":class: dropdown\n", "{download}`Download this exercise.<../Coding_exercises/Week_5/11_Escape.py>`\n", "\n", "**Exercise A:**\n", "In this exercise, you will build upon your code from Random particle diffusion, Exercise B. \n", "There, you were able to keep the particles inside the graphical window. In this exercise, you're asked to adjust the borders in\n", "such a way that 100 particles are now contained in a specified area. This container should be\n", "smaller than the screen. Make 3 versions with a square, a rectangular, and finally with a round\n", "container.\n", "\n", "Hint: testing whether a particle is inside a square or rectangular container is similar to testing if it stays\n", "within the screen, like you did before. However, testing whether a particle is inside a circle is a bit\n", "different. A circle is made up of a sine and a cosine function, centred on the middle and is as big as its\n", "radius. If the distance between a particle and the centre of a circle is larger than the radius of that\n", "circle, the particle is not inside the circle anymore. Use this information to think of a test to keep the\n", "particles within the round container.\n", "\n", "**Exercise B:**\n", "Extend your program from exercise A such that instead of a single round container you make three round containers and let there be 100 moving\n", "particles in each container. The particles should not escape the containers.\n", "\n", "Hint: the particles should get a location within one of the three containers before starting the\n", "simulation. All particles should be tested for all containers even if they are not inside that particular\n", "container. If a displacement leads to the future location of a particle outside of any container, this\n", "displacement should not be made.\n", "\n", "**Exercise C:**\n", "In exercise B we tested if particles were inside any of three containers. The code to check if particles\n", "are inside a container is very similar for each container, with just some changes in the location of the container and the\n", "size of the container. When there are many similar sections of code, you will recall from a [previous book section](../chapter10/functions.ipynb) that it's useful to define a Python function.\n", "\n", "In this exercise, you're asked to rewrite the code to check if a particle is in a container using a function. The inputs should be the `X` and `Y` location of the particle, and the `X` and `Y` location and radius of a container. The output should\n", "be a Boolean returning `True` if the particle is in the container and `False` if it is outside. For example,\n", "\n", "```\n", "def incircle(x, y, x_container, y_container, r_container):\n", " output = # code to test if x and y are inside container\n", " return output\n", "```\n", "\n", "Now you can check if a particle is inside the container using:\n", "\n", "```\n", "if incircle(x,y,x_c,y_c,r):\n", " # code to do if particle is in the container\n", "```\n", "\n", "**Exercise D:**\n", "Extend your program from exercise A, use the round container and the function from exercise C.\n", "When a particle tries to escape the container, introduce a chance of 25 % that it will succeed. See what\n", "happens when you vary the chance.\n", "\n", "Hint: Use the `random` function to create a probability.\n", "\n", "**Exercise E:**\n", "Extend your code from exercise D such that if a particle escapes the container, make it change colour and size.\n", "\n", "**Exercise F:**\n", "Extend your program from exercise E such that you keep track of the number of particles inside and outside of the container. Plot these numbers\n", "against time in a graph in a new graphical window positioned next to the graphical window with the\n", "moving particles. Therefore, another screen is required. Define this directly after the original screen:\n", "\n", "```\n", "chart = canvas(\"charttitle\", xSize, ySize, xpos=50, ypos=50)\n", "```\n", "\n", "The last two arguments define the location of the chart, in this case at 50 pixels outside of the left\n", "upper corner of your screen.\n", "\n", "Hint: Think about how you would draw a dynamic graph using the NaNoPy package and what type of\n", "graph you want to plot.\n", "`````" ] } ], "metadata": { "jupytext": { "formats": "ipynb,md" }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 5 }