├── .vscode └── settings.json ├── .gitignore ├── netlify.toml ├── src ├── computational-thinking │ └── reduced_phil.png ├── basic │ ├── empty.jl │ ├── Basic.jl │ ├── moon.jl │ ├── Markdown.jl │ ├── Getting started.jl │ ├── Basic mathematics.jl │ ├── turtles-art.jl │ ├── turtles.jl │ └── Pluto for Jupyter users.jl ├── pluto_export_configuration.json ├── puzzles-games │ ├── Tower of Hanoi.jl │ └── Traveling Salesman Game.jl └── web │ ├── CSS.jl │ └── Interactivity with HTML.jl ├── pluto-deployment-environment ├── Project.toml ├── PlutoDeployment.toml └── Manifest.toml ├── .github └── workflows │ ├── KeepCacheFresh.yml │ ├── UpdatePluto.yml │ └── Export.yml ├── tools └── update_notebook_packages.jl ├── LICENSES └── Unlicense ├── README.md └── CONTRIBUTING.md /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": false 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | pluto_state_cache/ 3 | output/ 4 | .vscode/ 5 | .DS_Store 6 | *.history 7 | *.sqlite -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [[headers]] 2 | for = "/*" 3 | [headers.values] 4 | Access-Control-Allow-Origin = "*" -------------------------------------------------------------------------------- /src/computational-thinking/reduced_phil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JuliaPluto/featured/HEAD/src/computational-thinking/reduced_phil.png -------------------------------------------------------------------------------- /pluto-deployment-environment/Project.toml: -------------------------------------------------------------------------------- 1 | [deps] 2 | Pluto = "c3e4b0f8-55cb-11ea-2926-15256bba5781" 3 | PlutoSliderServer = "2fc8631c-6f24-4c5b-bca7-cbb509c42db4" 4 | -------------------------------------------------------------------------------- /pluto-deployment-environment/PlutoDeployment.toml: -------------------------------------------------------------------------------- 1 | [Export] 2 | baked_notebookfile=false 3 | baked_state=false 4 | create_index=true 5 | create_pluto_featured_index=true 6 | slider_server_url="https://fonsi.armada.silentech.gr" 7 | exclude = [ 8 | "src/math/ZombieAttackWithMTK.jl", 9 | "math/ZombieAttackWithMTK.jl", # because i dont know which one 10 | ] 11 | number_of_parallel_tasks=8 12 | # more parameters can go here 13 | 14 | [SliderServer] 15 | exclude = [ 16 | "src/math/ZombieAttackWithMTK.jl", 17 | "math/ZombieAttackWithMTK.jl", 18 | ] 19 | -------------------------------------------------------------------------------- /.github/workflows/KeepCacheFresh.yml: -------------------------------------------------------------------------------- 1 | name: Keep caches fresh 2 | on: 3 | schedule: 4 | - cron: "5 4 1/4 * *" # every 4 days 5 | 6 | jobs: 7 | build-and-deploy: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Set up notebook state cache 11 | uses: actions/cache@v4 12 | with: 13 | path: pluto_state_cache 14 | key: ${{ runner.os }}-pluto_state_cache-v3-${{ hashFiles('**/Project.toml', '**/Manifest.toml') }}-${{ github.run_id }} 15 | restore-keys: | 16 | ${{ runner.os }}-pluto_state_cache-v3-${{ hashFiles('**/Project.toml', '**/Manifest.toml') }} 17 | -------------------------------------------------------------------------------- /src/basic/empty.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | using Markdown 5 | using InteractiveUtils 6 | 7 | # ╔═╡ 2a2b1a9c-c6a9-11ee-0fb7-2746d3703649 8 | 9 | 10 | # ╔═╡ 00000000-0000-0000-0000-000000000001 11 | PLUTO_PROJECT_TOML_CONTENTS = """ 12 | [deps] 13 | """ 14 | 15 | # ╔═╡ 00000000-0000-0000-0000-000000000002 16 | PLUTO_MANIFEST_TOML_CONTENTS = """ 17 | # This file is machine-generated - editing it directly is not advised 18 | 19 | julia_version = "1.11.3" 20 | manifest_format = "2.0" 21 | project_hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709" 22 | 23 | [deps] 24 | """ 25 | 26 | # ╔═╡ Cell order: 27 | # ╠═2a2b1a9c-c6a9-11ee-0fb7-2746d3703649 28 | # ╟─00000000-0000-0000-0000-000000000001 29 | # ╟─00000000-0000-0000-0000-000000000002 30 | -------------------------------------------------------------------------------- /tools/update_notebook_packages.jl: -------------------------------------------------------------------------------- 1 | if !isdir("pluto-deployment-environment") || length(ARGS) != 1 2 | error(""" 3 | Run me from the root of the repository directory, using: 4 | 5 | julia tools/update_notebook_packages.jl 6 | 7 | Where is one of: PATCH, MINOR, MAJOR 8 | """) 9 | end 10 | 11 | if !(v"1.11.0-aaa" < VERSION < v"1.12.0") 12 | error("Our notebook package environments need to be updated with Julia 1.11. Go to julialang.org/downloads to install it.") 13 | end 14 | 15 | import Pkg 16 | Pkg.activate("./pluto-deployment-environment") 17 | Pkg.instantiate() 18 | 19 | import Pluto 20 | 21 | flatmap(args...) = vcat(map(args...)...) 22 | 23 | 24 | all_files_recursive = flatmap(walkdir("src")) do (root, _dirs, files) 25 | joinpath.((root,), files) 26 | end 27 | 28 | all_notebooks = filter(Pluto.is_pluto_notebook, all_files_recursive) 29 | 30 | level = getfield(Pkg, Symbol("UPLEVEL_$(ARGS[1])")) 31 | 32 | for n in all_notebooks 33 | @info "Updating" n 34 | ENV["JULIA_PKG_PRECOMPILE_AUTO"] = 0 35 | Pluto.update_notebook_environment(n; backup=false, level) 36 | end 37 | 38 | @info "All notebooks done!" 39 | -------------------------------------------------------------------------------- /LICENSES/Unlicense: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to -------------------------------------------------------------------------------- /src/basic/Basic.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://github.com/JuliaPluto/featured/blob/2a6a9664e5428b37abe4957c1dca0994f4a8b7fd/LICENSES/Unlicense" 6 | #> author_url = "https://github.com/JuliaPluto" 7 | #> tags = ["debug", "classic"] 8 | #> author_name = "Pluto.jl" 9 | #> license = "Unlicense" 10 | 11 | using Markdown 12 | using InteractiveUtils 13 | 14 | # ╔═╡ b2d786ec-7f73-11ea-1a0c-f38d7b6bbc1e 15 | md""" 16 | # The Basel problem 17 | 18 | _Leonard Euler_ proved in 1741 that the series 19 | 20 | ```math 21 | \frac{1}{1} + \frac{1}{4} + \frac{1}{9} + \cdots 22 | ``` 23 | 24 | converges to 25 | 26 | ```math 27 | \frac{\pi^2}{6}. 28 | ``` 29 | """ 30 | 31 | # ╔═╡ b2d79330-7f73-11ea-0d1c-a9aad1efaae1 32 | n = 1:100000 33 | 34 | # ╔═╡ b2d79376-7f73-11ea-2dce-cb9c449eece6 35 | seq = n .^ -2 36 | 37 | # ╔═╡ b2d792c2-7f73-11ea-0c65-a5042701e9f3 38 | sqrt(sum(seq) * 6.0) 39 | 40 | # ╔═╡ 00000000-0000-0000-0000-000000000001 41 | PLUTO_PROJECT_TOML_CONTENTS = """ 42 | [deps] 43 | """ 44 | 45 | # ╔═╡ 00000000-0000-0000-0000-000000000002 46 | PLUTO_MANIFEST_TOML_CONTENTS = """ 47 | # This file is machine-generated - editing it directly is not advised 48 | 49 | julia_version = "1.11.3" 50 | manifest_format = "2.0" 51 | project_hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709" 52 | 53 | [deps] 54 | """ 55 | 56 | # ╔═╡ Cell order: 57 | # ╟─b2d786ec-7f73-11ea-1a0c-f38d7b6bbc1e 58 | # ╠═b2d792c2-7f73-11ea-0c65-a5042701e9f3 59 | # ╠═b2d79330-7f73-11ea-0d1c-a9aad1efaae1 60 | # ╠═b2d79376-7f73-11ea-2dce-cb9c449eece6 61 | # ╟─00000000-0000-0000-0000-000000000001 62 | # ╟─00000000-0000-0000-0000-000000000002 63 | -------------------------------------------------------------------------------- /src/pluto_export_configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "title": "Featured Notebooks", 4 | "description": "These notebooks from the Julia community show off what you can do with Pluto. Give it a try, you might learn something new!", 5 | 6 | "collections": [ 7 | { 8 | "title": "Getting started", 9 | "description": "Learn the basics of Pluto in just 10 minutes!", 10 | "tags": ["basic"] 11 | }, 12 | { 13 | "title": "Mathematics", 14 | "description": "Math is cool!!", 15 | "tags": ["math"] 16 | }, 17 | { 18 | "title": "Course preview: computational thinking", 19 | "description": "The free online course \"Computational Thinking\" from MIT is a great way to learn about programming and problem solving. Here are some lectures from the course, you can find the full course on computationalthinking.mit.edu", 20 | "tags": ["track_julia", "track_math", "track_climate", "track_data"] 21 | }, 22 | { 23 | "title": "Visualisation", 24 | "description": "Pluto is a great tool to visualise your results! Here are some examples.", 25 | "tags": ["visualisation", "plotting"] 26 | }, 27 | { 28 | "title": "Machine learning", 29 | "description": "Learn about using ML in Julia with these examples.", 30 | "tags": ["machine learning"] 31 | }, 32 | { 33 | "title": "Language", 34 | "description": "Learn about working with natural language in Julia.", 35 | "tags": ["language"] 36 | }, 37 | { 38 | "title": "Puzzles & Games", 39 | "description": "Have fun with some recreational programming!", 40 | "tags": ["puzzle", "game"] 41 | }, 42 | { 43 | "title": "Pluto and the Web", 44 | "description": "Pluto is a fantastic tool for connecting Julia to the web! Learn more about using HTML, CSS and JavaScript in Pluto to take your visualization skills to the next level.", 45 | "tags": ["web"] 46 | } 47 | ] 48 | 49 | } 50 | -------------------------------------------------------------------------------- /.github/workflows/UpdatePluto.yml: -------------------------------------------------------------------------------- 1 | name: Update Pluto version 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | plutocommitsha: 7 | description: 'Commit SHA or version number' 8 | required: true 9 | default: '3df8390a or 0.19.36' 10 | 11 | concurrency: 12 | group: updatepluto 13 | cancel-in-progress: false 14 | 15 | jobs: 16 | trigger: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v6 20 | # We use that PAT token instead of GITHUB_TOKEN because we are triggering another github action on the commit event. 21 | # Triggering a workflow from a workflow is only allowed if the relaying event is signed with a PAT. 22 | # See https://docs.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token 23 | with: 24 | token: ${{ secrets.PAT_TOKEN }} 25 | - uses: fregante/setup-git-user@v1 26 | 27 | - name: Install Julia 28 | uses: julia-actions/setup-julia@v2 29 | with: 30 | # note: this version should match the version in the other actions in this repo 31 | version: "1.11" 32 | 33 | - name: Update Pkg environment 34 | run: | 35 | julia -e ' 36 | import Pkg 37 | Pkg.activate("pluto-deployment-environment") 38 | Pkg.instantiate() 39 | Pkg.resolve() 40 | Pkg.rm("Pluto") 41 | input = "${{ github.event.inputs.plutocommitsha }}" 42 | if occursin(".", input) 43 | Pkg.add([Pkg.PackageSpec(name="Pluto", version=parse(VersionNumber, input))]) 44 | else 45 | Pkg.add([Pkg.PackageSpec(name="Pluto", rev=input)]) 46 | end 47 | Pkg.update() 48 | ' 49 | 50 | - name: Push changes to main 51 | working-directory: pluto-deployment-environment 52 | run: | 53 | git add Project.toml Manifest.toml 54 | git commit -m "$GITHUB_WORKFLOW" -m "Pluto version set to ${{ github.event.inputs.plutocommitsha }}" 55 | git push origin main 56 | -------------------------------------------------------------------------------- /.github/workflows/Export.yml: -------------------------------------------------------------------------------- 1 | ### 2 | # HELLO 3 | # Interested in setting up a cool github action like this one? Take a look at: https://github.com/JuliaPluto/static-export-template 4 | 5 | name: Export Pluto notebooks 6 | on: 7 | push: 8 | branches: 9 | - main 10 | workflow_dispatch: 11 | 12 | # When two jobs run in parallel, cancel the older ones, to make sure that the website is generated from the most recent commit. 13 | concurrency: 14 | group: pluto-export 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | build-and-deploy: 19 | runs-on: ubuntu-24.04 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v6 23 | 24 | 25 | - name: Install Julia 26 | uses: julia-actions/setup-julia@v2 27 | with: 28 | # note: this version should match the version in the other actions in this repo 29 | version: "1.11" 30 | 31 | - name: Cache Julia artifacts & such 32 | uses: julia-actions/cache@v2 33 | with: 34 | cache-registries: "true" 35 | 36 | 37 | # We set up a folder that Pluto can use to cache exported notebooks. If the notebook file did not change, then Pluto can take the exported file from cache instead of running the notebook. 38 | - name: Set up notebook state cache 39 | uses: actions/cache@v4 40 | with: 41 | path: pluto_state_cache 42 | key: ${{ runner.os }}-pluto_state_cache-v3-${{ hashFiles('**/Project.toml', '**/Manifest.toml') }}-${{ github.run_id }} 43 | restore-keys: | 44 | ${{ runner.os }}-pluto_state_cache-v3-${{ hashFiles('**/Project.toml', '**/Manifest.toml') }} 45 | 46 | - name: install GL dependencies 47 | run: sudo apt-get update && sudo apt-get install -y xorg-dev mesa-utils xvfb libgl1 freeglut3-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev xsettingsd x11-xserver-utils 48 | 49 | - name: Run & export Pluto notebooks 50 | run: | 51 | DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24' julia -e ' 52 | import Pkg 53 | Pkg.activate("pluto-deployment-environment") 54 | Pkg.instantiate() 55 | 56 | import PlutoSliderServer, Pluto 57 | 58 | isdir("output") && rm("output"; recursive=true) 59 | 60 | # run PlutoSliderServer 61 | PlutoSliderServer.github_action("src"; 62 | Export_output_dir="output", 63 | Export_cache_dir="pluto_state_cache", 64 | # more parameters can go here 65 | ) 66 | 67 | # custom index 68 | index_html_contents = Pluto.generate_index_html(; 69 | version=PlutoSliderServer.try_get_exact_pluto_version(), 70 | featured_direct_html_links=true, 71 | featured_sources_js="""[ 72 | // notebooks from this repo 73 | { 74 | url:`./pluto_export.json` 75 | }, 76 | // additional: plutojl.org website 77 | { 78 | id: "pluto website", 79 | url: "https://plutojl.org/pluto_export.json", 80 | // this is one month before the expiry date of our domain registration at njal.la 81 | valid_until: "2025-10", 82 | }, 83 | ]""", 84 | ) 85 | write(joinpath("output", "index.html"), index_html_contents) 86 | cp("netlify.toml", joinpath("output", "netlify.toml"))' 87 | 88 | 89 | - name: Deploy to dist 90 | uses: JamesIves/github-pages-deploy-action@releases/v4 91 | with: 92 | branch: dist 93 | folder: output 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `featured` 2 | 3 | [**You can read all the featured notebooks here!**](https://featured.plutojl.org/) 4 | 5 | This repository contains Pluto's *featured* notebooks! Learn more about our featured notebook system [here](https://github.com/fonsp/Pluto.jl/pull/2048). 6 | 7 | ## Submit your notebook! 8 | 9 | Consider **submitting your notebook**! This is not just for expert Julia users, beginners are especially welcome to submit! 10 | 11 | Take a look at [`CONTRIBUTING.md`](https://github.com/JuliaPluto/featured/blob/main/CONTRIBUTING.md) to learn more about submitting your notebook! 12 | 13 | ## Contributing to existing notebooks 14 | 15 | If you find a typo, bug, or another issue with an existing notebook, feel free to open a PR! 16 | 17 | # What is a featured notebook? 18 | 19 | Pluto's *featured* notebooks is a collection of notebooks from the Julia community and the Pluto developers to **showcase what you can do with Julia and Pluto**, and to help you get started. Featured notebooks are intended to **get people excited**, and to **teach new skills**. We want to reach a diverse audience, with different backgrounds and skill levels, but we have a special interest in notebooks that might improve the accessibility of scientific computing. This might include notebooks that are accessible to Julia beginners, to high school students, or notebooks that are just really flashy and beautiful. 20 | 21 | Take a look at [`CONTRIBUTING.md`](https://github.com/JuliaPluto/featured/blob/main/CONTRIBUTING.md) to learn more about what makes a good notebook! 22 | 23 | # Where can people read my notebook? 24 | 25 | Featured notebooks have a large audience! People can find them in three different places: 26 | 27 | ## 1. In Pluto 28 | 29 | When people start Pluto on their computer, featured notebooks will be listed directly on the main menu. It is the first thing new users will see! 30 | 31 | You can read and interact with featured notebooks in Pluto without having to run the notebooks on your own computer. But if you want, you can! The "Edit or run" button will open the notebook locally, and you can start making edits. 32 | 33 | Screenshot of the Pluto.jl IDE main menu, where featured notebooks are listed. 34 | 35 | ## 2. On the plutojl.org website 36 | When you visit Pluto's website: [plutojl.org](https://plutojl.org), you can click **Featured notebooks** on the top. This sends you to [featured.plutojl.org](https://featured.plutojl.org), the online website with all of our featured notebooks. You can read notebooks on this website without having to install Julia or Pluto, and it also works on your phone. 37 | 38 | We use [PlutoSliderServer.jl](https://github.com/JuliaPluto/PlutoSliderServer.jl) for this website, which means that people can interact with `@bind` interactions instantly on our website, without having to run the notebook! 39 | 40 | Screenshot of featured.plutojl.org. 41 | 42 | 43 | ## 3. On julialang.org/learning 44 | On Julia's [official *learning* page](https://julialang.org/learning/), we included a section about Pluto.jl. This includes a couple screenshots of featured notebooks, which will send people to our website with all featured notebooks. 45 | 46 | Screenshot of the learning page on the julialang website 47 | 48 | # Interactivity 49 | The current *featured* system distributes notebook *statefiles*, which work the same way as Pluto's HTML export: people can read the notebook instantly, without having to wait for it to run. There is a button to *Edit and Run* a notebook that users can press to use the featured notebook as a template. 50 | 51 | This means that sliders, buttons, etc don't immediately work, so notebooks that rely heavily on interactivity to tell a story are not a good fit. In the future, we plan to run a [PlutoSliderServer](https://github.com/JuliaPluto/PlutoSliderServer.jl) for sample notebooks, allowing instant interaction like https://computationalthinking.mit.edu/, but until then, keep this in mind. 52 | 53 | # Contributing 54 | Take a look at [`CONTRIBUTING.md`](https://github.com/JuliaPluto/featured/blob/main/CONTRIBUTING.md) to learn more about submitting your notebook! 55 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Hello! Nice to hear that you are thinking about contributing a featured notebook. Before submitting your notebook, let's discuss what type of notebook we are looking for, and whether it would be a good fit. 2 | 3 | 4 | # Can I write a notebook? 5 | 6 | You don't need to be an expert to write a featured notebook! The notebooks are designed to help beginning Pluto users get underway with their own ideas; as such, short tutorials on basic Julia concepts, or short examples of neat ideas, are very much welcome, and are a great way to contribute to the Julia community when you're still learning yourself. 7 | 8 | That said, we also very much welcome experienced Julia programmers to share their work. Featured notebooks can highlight how you use Julia in your domain, bring attention to a neat package, or share exercises that you created for a course. 9 | 10 | ![Motivational image – you got this!!](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExOWwwOHV4bXg5bDBoamo2NG55OGhmZzkyM2lsNjN1emc5bzFubms2MCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/6VriQO3GFRwwBVPbi4/giphy.gif) 11 | 12 | 13 | # What is a good fit? 14 | Pluto's *featured* notebooks is a collection of notebooks from the Julia community and the Pluto developers to **showcase what you can do with Julia and Pluto**, and to help you get started. Featured notebooks are intended to **get people excited**, and to **teach new skills**. 15 | 16 | 17 | ## Suitable topics 18 | If you have an idea that you want to share, something that you think others would be excited about, then it's probably a good fit! That being said, here are some suggestions for suitable topics, and some things you might not have thought about. 19 | 20 | Some examples of great topics: 21 | - Tutorials about core Julia programming concepts, like arrays. 22 | - A visualisation that you are proud of. 23 | - You are a teacher, and you wrote exercises for a course. 24 | - An example of how Julia is used in your specific academic domain. 25 | - A notebook to showcase a Julia package. This could be a package you like, or a package you develop yourself (although *featured* is not the right place to host your package documentation). 26 | 27 | 28 | 29 | 30 | Things that might not be a good topic: 31 | - Something very similar to an existing featured notebook. *(If this is your situation, consider contacting the author of the existing notebook to collaborate, or get in touch with us.)* 32 | - Industry-specific knowledge that might not be understandable to the public. 33 | - Notebooks that promote environmental or social harm. 34 | 35 | 36 | 37 | ## Thing we like to see 38 | There are some things that make a featured notebook work extra well! Some examples: 39 | - Many interactive elements using `@bind`. When reading featured notebooks, `@bind` will be interactive instantly, while editing takes some time. 40 | - Pictures! Especially at the top of the notebook. Many people will quickly scroll through the notebook looking for cool visuals before deciding to read the text. 41 | - Text! Explain what your code and interactions do, using simple language. Also think about labeling plots and interactive elements. 42 | - Links! If your notebook uses difficult concepts, consider adding links to resources online where people can learn more about it. 43 | - Code! Some featured notebooks have no visible code (the "magic demos"), but also consider showcasing your code! Can you make code part of the story? Perhaps you can put more technical code in helper functions that are hidden in the bottom. 44 | - Clear code! Write code comments and descriptive variable names. Try splitting your code into more cells and functions with a descriptive name. 45 | 46 | 47 | Things to avoid: 48 | - Long cell runtimes or heavy memory usage. *(For example: training a machine learning model)* 49 | - Importing large packages when smaller alternatives exist. *(For example: if you are using Makie.jl to create a simple plot, then consider using PlutoPlotly.jl or Plots.jl instead. Are you using Makie.jl for an awesome visualisation, then great!)* 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | # Technical information 58 | The information below describes the technical details for making a notebook work well in our _featured_ system. If this is intimidating or unclear, don't worry! You can skip all of this and just make a Pull Request, and we will figure it out together ☺️ 59 | 60 | If you are experienced with these topics, you can also work through this list yourself, and make your own choices about the license, etc. 61 | 62 | ## Frontmatter 63 | If you take a look at [featured.plutojl.org](https://featured.plutojl.org), you will notice that all notebooks have a nice title, description, image and author. This data is called *frontmatter*, which can be written using Pluto's [Frontmatter GUI](https://github.com/fonsp/Pluto.jl/pull/2104). To open it from the Pluto editor, click the share button ( ), and then the frontmatter button in the top right. ( ). You need to fill in the following fields: 64 | 65 | - `description` 66 | - `date`: the creation date 67 | - `license` 68 | - `license_url` (see below) 69 | - `image`: should be a URL starting with `https://`. The image can be `.jpg`, `.png` or `.svg`, and about 600x400 pixels large. *(To use your own image, create a new issue in this repository, paste the image in the text to upload it to github and to get the URL. You can cancel creating the issue.)* 70 | - At least one author, with: 71 | - `name`: your name to display 72 | - `url`: your user page URL, like `https://github.com/fonsp`. This is where people will go when they click on your name. If it's a github user URL, then it will also be used for the image. 73 | - `image` *(optional)*: if you did *not* provide a github `url` that can be used for the image, or if you want to choose another image, use this for a custom avatar URL. 74 | - `tags`: fill in as many tags as you wish! This is where you choose in which category the notebook is listed, include at least one existing tag from [the collections configuration](https://github.com/JuliaPluto/featured/blob/main/src/pluto_export_configuration.json). *(lowercase, spaces allowed)* 75 | - `order` *(optional)*: this can be a number that is used to sort notebooks within a collection. Notebooks with lower orders show up first. 76 | 77 | All notebook files in this repository will be rendered by PlutoSliderServer, but they will only show up in Pluto's main menu if they belong to a collection. 78 | 79 | 80 | ## Licensing 81 | 82 | All notebooks MUST have an [OSI-approved licence](https://opensource.org/licenses/) or a [creative commons licence](https://creativecommons.org/share-your-work/cclicenses/). Whether a software licence or a creative licence is more appropriate for your notebook is up to you. 83 | 84 | We like to use the [Unlicense](https://opensource.org/license/unlicense/) for featured notebooks, but you're free to pick a different one! 85 | 86 | ### Adding licence info to your notebook 87 | 88 | First, specify the license in the frontmatter of your notebook. Add a `license` field with the name of your licence, and a `license_url` field with a link to the full text. 89 | 90 | If the full text is already listed in [LICENSES](LICENSES/), you can link to that file. If not, we recommend that you add it to LICENSES yourself, so it will always be availalbe with the notebook, but you can also link to an external URL. 91 | 92 | The Unlicense is a *public domain-equivalent* license, which means gives permission to share and reuse the code without any restrictions. There are a few other licenses like this, such as MIT No Attribution and CC-0. If you're using a license that isn't like this, add a clear paragraph in the content of your notebook to say this. 93 | 94 | 95 | ## Versions 96 | 97 | Use Pluto's integrated package manager. *(If you are using an unregistered package, consider just registering it. Using it in a featured notebook is reason enough for registration!)* 98 | 99 | [Update all package versions](https://plutojl.org/en/docs/packages/#updating-packages) before submitting the notebook. 100 | 101 | Your notebook should be written in **Julia 1.6**. If you wrote it in another version, then start Pluto in Julia 1.6 and open and run your notebook. *(Since Pluto is designed for Julia 1.6 and above, we want the featured notebooks to work for the same versions. We also found that an embedded Manifest.toml generated with Julia 1.6 has the highest chance of working directly on other Julia versions.)* 102 | 103 | 104 | 105 | # Future maintenance 106 | Once a notebook is published 107 | 108 | Here, we make a distinction between two types of notebooks: notebooks authored by JuliaPluto, and others. 109 | 110 | TODO 111 | 112 | ## Notebooks authored by JuliaPluto 113 | The purpose of 114 | TODO 115 | 116 | ## Notebooks authored by others 117 | 118 | TODO 119 | 120 | 121 | # Site maintenance 122 | 123 | Check out [these instructions](https://github.com/JuliaPluto/pluto-developer-instructions/blob/main/How%20to%20update%20the%20featured%20notebooks.md) to learn more about maintenance. 124 | 125 | -------------------------------------------------------------------------------- /src/basic/moon.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://github.com/JuliaPluto/featured/blob/2a6a9664e5428b37abe4957c1dca0994f4a8b7fd/LICENSES/Unlicense" 6 | #> author_image = "https://www.s-ccs.de/assets/icn/title_logo.svg" 7 | #> author_url = "https://github.com/s-ccs/" 8 | #> image = "https://github.com/JuliaPluto/featured/assets/6933510/f8bec040-bb45-45c5-bedc-b2528e175c4c" 9 | #> title = "Fun with 🌒Emojis and Julia" 10 | #> date = "2023-07-25" 11 | #> tags = ["PlutoUI", "animation", "visualisation", "clock", "Unicode"] 12 | #> description = "Making use of 🌒 emojis and PlutoUI.clock for a simple animation" 13 | #> license = "Unlicense" 14 | #> author_name = "Maanik, Boshra, Benedikt" 15 | 16 | using Markdown 17 | using InteractiveUtils 18 | 19 | # This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). 20 | macro bind(def, element) 21 | #! format: off 22 | return quote 23 | local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end 24 | local el = $(esc(element)) 25 | global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) 26 | el 27 | end 28 | #! format: on 29 | end 30 | 31 | # ╔═╡ 74aee166-2ae3-11ee-2eae-03b413b9e6d9 32 | using PlutoUI, HypertextLiteral 33 | 34 | # ╔═╡ 2e148e61-8090-483c-b52c-0b1a4631e51a 35 | # Authors: Boshra, Maanik, Benedikt from https://www.s-ccs.de/ 36 | 37 | # ╔═╡ 37acb7bc-0045-4515-b770-94960ddb7cba 38 | moonphases = '🌑':'🌘' 39 | 40 | 41 | # ╔═╡ 5f5b8de0-096f-4546-a7f0-0d468f3a73e4 42 | @bind clock PlutoUI.Clock(;start_running=true,interval=0.5) 43 | 44 | # ╔═╡ 09070d82-f05f-4829-b403-873a51867582 45 | index = Int(mod(clock,length(moonphases))+1) 46 | 47 | # ╔═╡ 467aad45-8708-41bb-a916-5a795bce960d 48 | @htl """ 49 | $(moonphases[index]) 50 | """ 51 | 52 | # ╔═╡ 00000000-0000-0000-0000-000000000001 53 | PLUTO_PROJECT_TOML_CONTENTS = """ 54 | [deps] 55 | HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" 56 | PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" 57 | 58 | [compat] 59 | HypertextLiteral = "~0.9.5" 60 | PlutoUI = "~0.7.62" 61 | """ 62 | 63 | # ╔═╡ 00000000-0000-0000-0000-000000000002 64 | PLUTO_MANIFEST_TOML_CONTENTS = """ 65 | # This file is machine-generated - editing it directly is not advised 66 | 67 | [[AbstractPlutoDingetjes]] 68 | deps = ["Pkg"] 69 | git-tree-sha1 = "6e1d2a35f2f90a4bc7c2ed98079b2ba09c35b83a" 70 | uuid = "6e696c72-6542-2067-7265-42206c756150" 71 | version = "1.3.2" 72 | 73 | [[ArgTools]] 74 | uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" 75 | version = "1.1.2" 76 | 77 | [[Artifacts]] 78 | uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" 79 | version = "1.11.0" 80 | 81 | [[Base64]] 82 | uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" 83 | version = "1.11.0" 84 | 85 | [[ColorTypes]] 86 | deps = ["FixedPointNumbers", "Random"] 87 | git-tree-sha1 = "b10d0b65641d57b8b4d5e234446582de5047050d" 88 | uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" 89 | version = "0.11.5" 90 | 91 | [[CompilerSupportLibraries_jll]] 92 | deps = ["Artifacts", "Libdl"] 93 | uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" 94 | version = "1.1.1+0" 95 | 96 | [[Dates]] 97 | deps = ["Printf"] 98 | uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" 99 | version = "1.11.0" 100 | 101 | [[Downloads]] 102 | deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] 103 | uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" 104 | version = "1.6.0" 105 | 106 | [[FileWatching]] 107 | uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" 108 | version = "1.11.0" 109 | 110 | [[FixedPointNumbers]] 111 | deps = ["Statistics"] 112 | git-tree-sha1 = "05882d6995ae5c12bb5f36dd2ed3f61c98cbb172" 113 | uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" 114 | version = "0.8.5" 115 | 116 | [[Hyperscript]] 117 | deps = ["Test"] 118 | git-tree-sha1 = "179267cfa5e712760cd43dcae385d7ea90cc25a4" 119 | uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91" 120 | version = "0.0.5" 121 | 122 | [[HypertextLiteral]] 123 | deps = ["Tricks"] 124 | git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653" 125 | uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" 126 | version = "0.9.5" 127 | 128 | [[IOCapture]] 129 | deps = ["Logging", "Random"] 130 | git-tree-sha1 = "b6d6bfdd7ce25b0f9b2f6b3dd56b2673a66c8770" 131 | uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" 132 | version = "0.2.5" 133 | 134 | [[InteractiveUtils]] 135 | deps = ["Markdown"] 136 | uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" 137 | version = "1.11.0" 138 | 139 | [[JSON]] 140 | deps = ["Dates", "Mmap", "Parsers", "Unicode"] 141 | git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" 142 | uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" 143 | version = "0.21.4" 144 | 145 | [[LibCURL]] 146 | deps = ["LibCURL_jll", "MozillaCACerts_jll"] 147 | uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" 148 | version = "0.6.4" 149 | 150 | [[LibCURL_jll]] 151 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] 152 | uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" 153 | version = "8.6.0+0" 154 | 155 | [[LibGit2]] 156 | deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] 157 | uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" 158 | version = "1.11.0" 159 | 160 | [[LibGit2_jll]] 161 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] 162 | uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" 163 | version = "1.7.2+0" 164 | 165 | [[LibSSH2_jll]] 166 | deps = ["Artifacts", "Libdl", "MbedTLS_jll"] 167 | uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" 168 | version = "1.11.0+1" 169 | 170 | [[Libdl]] 171 | uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" 172 | version = "1.11.0" 173 | 174 | [[LinearAlgebra]] 175 | deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] 176 | uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 177 | version = "1.11.0" 178 | 179 | [[Logging]] 180 | uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" 181 | version = "1.11.0" 182 | 183 | [[MIMEs]] 184 | git-tree-sha1 = "c64d943587f7187e751162b3b84445bbbd79f691" 185 | uuid = "6c6e2e6c-3030-632d-7369-2d6c69616d65" 186 | version = "1.1.0" 187 | 188 | [[Markdown]] 189 | deps = ["Base64"] 190 | uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" 191 | version = "1.11.0" 192 | 193 | [[MbedTLS_jll]] 194 | deps = ["Artifacts", "Libdl"] 195 | uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" 196 | version = "2.28.6+0" 197 | 198 | [[Mmap]] 199 | uuid = "a63ad114-7e13-5084-954f-fe012c677804" 200 | version = "1.11.0" 201 | 202 | [[MozillaCACerts_jll]] 203 | uuid = "14a3606d-f60d-562e-9121-12d972cd8159" 204 | version = "2023.12.12" 205 | 206 | [[NetworkOptions]] 207 | uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" 208 | version = "1.2.0" 209 | 210 | [[OpenBLAS_jll]] 211 | deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] 212 | uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" 213 | version = "0.3.27+1" 214 | 215 | [[Parsers]] 216 | deps = ["Dates", "PrecompileTools", "UUIDs"] 217 | git-tree-sha1 = "7d2f8f21da5db6a806faf7b9b292296da42b2810" 218 | uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" 219 | version = "2.8.3" 220 | 221 | [[Pkg]] 222 | deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] 223 | uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" 224 | version = "1.11.0" 225 | 226 | [Pkg.extensions] 227 | REPLExt = "REPL" 228 | 229 | [Pkg.weakdeps] 230 | REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" 231 | 232 | [[PlutoUI]] 233 | deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "FixedPointNumbers", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "MIMEs", "Markdown", "Random", "Reexport", "URIs", "UUIDs"] 234 | git-tree-sha1 = "d3de2694b52a01ce61a036f18ea9c0f61c4a9230" 235 | uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8" 236 | version = "0.7.62" 237 | 238 | [[PrecompileTools]] 239 | deps = ["Preferences"] 240 | git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" 241 | uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" 242 | version = "1.2.1" 243 | 244 | [[Preferences]] 245 | deps = ["TOML"] 246 | git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" 247 | uuid = "21216c6a-2e73-6563-6e65-726566657250" 248 | version = "1.4.3" 249 | 250 | [[Printf]] 251 | deps = ["Unicode"] 252 | uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" 253 | version = "1.11.0" 254 | 255 | [[Random]] 256 | deps = ["SHA"] 257 | uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 258 | version = "1.11.0" 259 | 260 | [[Reexport]] 261 | git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" 262 | uuid = "189a3867-3050-52da-a836-e630ba90ab69" 263 | version = "1.2.2" 264 | 265 | [[SHA]] 266 | uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" 267 | version = "0.7.0" 268 | 269 | [[Serialization]] 270 | uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" 271 | version = "1.11.0" 272 | 273 | [[Statistics]] 274 | deps = ["LinearAlgebra"] 275 | git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0" 276 | uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" 277 | version = "1.11.1" 278 | 279 | [Statistics.extensions] 280 | SparseArraysExt = ["SparseArrays"] 281 | 282 | [Statistics.weakdeps] 283 | SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" 284 | 285 | [[TOML]] 286 | deps = ["Dates"] 287 | uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" 288 | version = "1.0.3" 289 | 290 | [[Tar]] 291 | deps = ["ArgTools", "SHA"] 292 | uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" 293 | version = "1.10.0" 294 | 295 | [[Test]] 296 | deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] 297 | uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" 298 | version = "1.11.0" 299 | 300 | [[Tricks]] 301 | git-tree-sha1 = "6cae795a5a9313bbb4f60683f7263318fc7d1505" 302 | uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" 303 | version = "0.1.10" 304 | 305 | [[URIs]] 306 | git-tree-sha1 = "cbbebadbcc76c5ca1cc4b4f3b0614b3e603b5000" 307 | uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" 308 | version = "1.5.2" 309 | 310 | [[UUIDs]] 311 | deps = ["Random", "SHA"] 312 | uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" 313 | version = "1.11.0" 314 | 315 | [[Unicode]] 316 | uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" 317 | version = "1.11.0" 318 | 319 | [[Zlib_jll]] 320 | deps = ["Libdl"] 321 | uuid = "83775a58-1f1d-513f-b197-d71354ab007a" 322 | version = "1.2.13+1" 323 | 324 | [[libblastrampoline_jll]] 325 | deps = ["Artifacts", "Libdl"] 326 | uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" 327 | version = "5.11.0+0" 328 | 329 | [[nghttp2_jll]] 330 | deps = ["Artifacts", "Libdl"] 331 | uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" 332 | version = "1.59.0+0" 333 | 334 | [[p7zip_jll]] 335 | deps = ["Artifacts", "Libdl"] 336 | uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" 337 | version = "17.4.0+2" 338 | """ 339 | 340 | # ╔═╡ Cell order: 341 | # ╠═2e148e61-8090-483c-b52c-0b1a4631e51a 342 | # ╠═74aee166-2ae3-11ee-2eae-03b413b9e6d9 343 | # ╠═37acb7bc-0045-4515-b770-94960ddb7cba 344 | # ╠═5f5b8de0-096f-4546-a7f0-0d468f3a73e4 345 | # ╠═467aad45-8708-41bb-a916-5a795bce960d 346 | # ╠═09070d82-f05f-4829-b403-873a51867582 347 | # ╟─00000000-0000-0000-0000-000000000001 348 | # ╟─00000000-0000-0000-0000-000000000002 349 | -------------------------------------------------------------------------------- /src/basic/Markdown.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://github.com/JuliaPluto/featured/blob/2a6a9664e5428b37abe4957c1dca0994f4a8b7fd/LICENSES/Unlicense" 6 | #> image = "https://upload.wikimedia.org/wikipedia/commons/a/a0/Textformatting.svg" 7 | #> order = "1.5" 8 | #> title = "Markdown" 9 | #> tags = ["markdown", "basic"] 10 | #> license = "Unlicense" 11 | #> description = "Learn to write text cells with Markdown." 12 | #> 13 | #> [[frontmatter.author]] 14 | #> name = "Pluto.jl" 15 | #> url = "https://github.com/JuliaPluto" 16 | 17 | using Markdown 18 | using InteractiveUtils 19 | 20 | # ╔═╡ ce092665-e18d-4314-a43e-51a04e25cd30 21 | md""" 22 | # How to use Markdown in Pluto 23 | 24 | If a Pluto cell starts with `md"` and ends with `"`, it is a markdown cell! 25 | """ 26 | 27 | # ╔═╡ 02b26da6-40d1-4b3c-a594-aff8016b0945 28 | 29 | 30 | # ╔═╡ 1adedccd-db89-40ec-ab77-a92c2976fc2c 31 | md"Hello *Markdown*" 32 | 33 | # ╔═╡ 2f8d4781-a364-4803-ba5f-69f85ef1c055 34 | 35 | 36 | # ╔═╡ 50891330-1c60-4020-b4f6-f1200ca2b71d 37 | md""" 38 | !!! info "Julia cells and Markdown cells" 39 | Some notebook environments have different **cell types**: a *code* cell and a *Markdown* cell. 40 | 41 | In Pluto, there is **only one cell type**: a Julia cell. But you can use the Julia string macro `md"` to write Markdown inside of Julia! 🤯 42 | """ 43 | 44 | # ╔═╡ 57e3bfde-b692-44e6-a764-7459626a8919 45 | 46 | 47 | # ╔═╡ 50fa8a8b-2c55-45b6-b4e0-8f510294586c 48 | 49 | 50 | # ╔═╡ 76b5db23-8174-445d-927e-ef2d92bbf32f 51 | 52 | 53 | # ╔═╡ e548c2ce-0e77-43b2-acaa-97005d67801f 54 | md""" 55 | # Keyboard shortcut 56 | 57 | Instead of typing `md"` by hand, you can press **`Ctrl + M`** (or **`Cmd + M`** on Mac) to do it automatically. 58 | 59 | 👉 Try it yourself! In the cell below, press **`Ctrl/Cmd + M`**, type a message, and run the cell. 60 | """ 61 | 62 | # ╔═╡ f953ef79-b3a5-4adb-8467-b92b5f5bfbce 63 | 64 | 65 | # ╔═╡ c16b0170-5b0b-4618-b028-b6278bd6319d 66 | 67 | 68 | # ╔═╡ 4dbbfcee-37d0-4361-9058-ea3f9354e2de 69 | 70 | 71 | # ╔═╡ 49fd22a1-63d7-48c3-a1de-67087b77e347 72 | 73 | 74 | # ╔═╡ 9a7e812e-f6bd-47b8-ac36-124a2a233354 75 | md""" 76 | > 🐤 This is how all the text cells in this notebook are made! You can show the code on any of them to see how they are written. 77 | """ 78 | 79 | # ╔═╡ 838cb47d-db5e-4182-b7a1-164f0552bd02 80 | 81 | 82 | # ╔═╡ 9cae62be-7591-4ebe-9fbc-c39be4e479c4 83 | md""" 84 | --- 85 | """ 86 | 87 | # ╔═╡ dfb656e4-94bc-4b3b-bd09-979d937246b8 88 | 89 | 90 | # ╔═╡ af97612d-832e-431a-b096-be8d7c94228f 91 | md""" 92 | # Markdown syntax 93 | 94 | We've seen one bit of markdown syntax already: a single `*` for italics. There are more! Here is a quick reference to get you started: 95 | """ 96 | 97 | # ╔═╡ 99f3bca7-5314-4e86-8f28-bb5a6358bdbd 98 | md""" 99 | Text in *italics* or **bold** 100 | """ 101 | 102 | # ╔═╡ cd5b10ac-0618-4220-b7e3-b1beeea43eff 103 | md""" 104 | Headers: 105 | 106 | # Biggest header 107 | ## Big header 108 | ### Medium header 109 | #### Small header 110 | ##### Smaller header 111 | """ 112 | 113 | # ╔═╡ 8b622d0d-def6-4a2c-af3b-fdf91240fb90 114 | md""" 115 | Bullet points: 116 | 117 | - something 118 | - something else 119 | """ 120 | 121 | # ╔═╡ 5a399dae-5756-4614-a64f-214e812ee069 122 | md""" 123 | Numbered lists: 124 | 125 | 1. First item 126 | 2. Second item 127 | """ 128 | 129 | # ╔═╡ cca6c895-7974-4c3e-9170-ed85ae127478 130 | md""" 131 | If you're familiar with writing LaTeX formulas, you can do that too: ``i = \sqrt{-1}``. 132 | """ 133 | 134 | # ╔═╡ 65b31de3-fe0b-4e2a-97ad-39e4cd17962f 135 | md""" 136 | Text blocks are often describing code, so it's important that we can write code neatly! 137 | 138 | You can use `ticks` when you want to talk about variables or expressions. 139 | """ 140 | 141 | # ╔═╡ 3b8ae605-025f-485e-a5a2-1f823319a67a 142 | md""" 143 | For longer pieces of code, you can use three ticks: 144 | 145 | ``` 146 | x = 1 147 | ``` 148 | 149 | If you're writing code in a specific language, you can also specify it to get nice formatting: 150 | 151 | ```julia 152 | function square(x) 153 | x^2 154 | end 155 | ``` 156 | 157 | Neat! 158 | """ 159 | 160 | # ╔═╡ 6e315f3b-1a46-483e-86bc-931023a8ac54 161 | md""" 162 | You can add links like so: [read about Julia](https://julialang.org). 163 | """ 164 | 165 | # ╔═╡ cb3b24f4-10d1-4de9-bd82-813af622f79b 166 | md""" 167 | If you want to include an image from the web, it looks a lot like adding a a link. Adding a `!` at the start means that we want to *show* the image instead of linking to it. 168 | 169 | ![julia logo](https://julialang.org/assets/infra/logo.svg) 170 | 171 | For images, the text between the `[]` is used as *alt text*: a text description that can be used when the image can't be shown. This is useful for people with impaired vision, but it's also useful if the link doesn't work. 172 | 173 | ![julia logo](https://broken.link) 174 | """ 175 | 176 | # ╔═╡ dd004d6c-54f6-4dd7-9aea-910adf0b22a5 177 | md""" 178 | What if you want to add an image that isn't on the internet? You can also link to your own filesystem: 179 | 180 | ![cute picture of my dog](C:/Users/Luka/Pictures/Hannes_playing_in_the_snow.jpg) 181 | 182 | Oops, you probably can't see that one! That's the trouble with linking to files: it doesn't always work. There are ways around that, but if you're new to all this, linking to online images is the way to go. We recommend uploading your image to the web (with `imgur.com` for example) to get a URL. 183 | """ 184 | 185 | # ╔═╡ 5b08043c-302b-4b9b-982d-4ba1da41ff9f 186 | md""" 187 | Those are the basics! There is more you can do in markdown, like adding tables or footnotes: see the links at the bottom if you want to learn more. 188 | """ 189 | 190 | # ╔═╡ e7626671-ff5d-45f1-b8df-853d1d9bc1ac 191 | 192 | 193 | # ╔═╡ 4428fe55-7d65-487b-864b-b566e7ecee9e 194 | md""" 195 | ## Dynamic content 196 | 197 | Writing some text is nice, what's really neat is if the text can **respond to code**. A simple way to do this is with an `if`/`else` block. Here we make a statement based on the value of `x`: 198 | 199 | 👉 Try changing the value of `x` to `-5`, and watch how the text changes. 200 | """ 201 | 202 | # ╔═╡ 7e5644fd-75ff-4f70-9981-ddb7d9ad470c 203 | x = 1 204 | 205 | # ╔═╡ 445eddb1-ccee-45d9-be5b-3f5fec9e2c7a 206 | if x > 0 207 | md"`x` is positive" 208 | elseif x < 0 209 | md"`x` is negative" 210 | else 211 | md"`x` is zero" 212 | end 213 | 214 | # ╔═╡ 51e38551-742c-48dd-aaea-ffe479b9621b 215 | md""" 216 | ### Interpolating values 217 | 218 | You can also use **`$`** (the dollar sign) to include expressions in your text. 219 | 220 | For example, your text can include the value of a variable: 221 | """ 222 | 223 | # ╔═╡ 1a2f37ec-9be2-4fd5-8f0b-b6579a241b55 224 | md""" 225 | The value of `x` is $(x), which is $(x > 100 ? "a lot!" : "not very high.") 226 | """ 227 | 228 | # ╔═╡ d2451923-6487-497c-a169-9815702c42fc 229 | md""" 230 | ## Useful links 231 | 232 | - [Markdown Guide](https://www.markdownguide.org/) 233 | - [Documentation of Julia's Markdown library](https://docs.julialang.org/en/v1/stdlib/Markdown/) 234 | 235 | """ 236 | 237 | # ╔═╡ 64a23ad5-0fa1-48dd-9786-dcfbc73a3b52 238 | 239 | 240 | # ╔═╡ d6def1a3-cc96-4eb9-bfce-949d29ffe31f 241 | function pluto_icon(name, alt=name) 242 | 243 | # It would be better to use HypertextLiteral.jl instead of just the HTML function, but this means that the notebook works without any packages, which can be a problem when reading this notebook without internet. 244 | HTML("""$(alt) 250 | """) 251 | end 252 | 253 | # ╔═╡ 8f45d098-4041-4449-83c3-79280232691e 254 | md""" 255 | 👉 Try it yourself! In the cell below, write some markdown text, and run the cell with the $(pluto_icon("caret-forward-circle", "play")) button on the bottom right of the cell (or **`Shift + Enter`**). 256 | """ 257 | 258 | # ╔═╡ 688a8ea9-1bff-45c5-8942-f8e96ed0ef79 259 | md""" 260 | When you are done, **hide the code** by clicking the $(pluto_icon("eye")) button on the left of the cell. 261 | """ 262 | 263 | # ╔═╡ e392d442-5c83-4711-bc45-c2dbedf62b7f 264 | md""" 265 | ## Helper function 266 | 267 | We wrote a helper function to show Pluto's GUI buttons in the introduction text, like $(pluto_icon("eye")) and $(pluto_icon("caret-forward-circle")). A bit too advanced for this notebook, but hopefully it made the text easier to read! 268 | """ 269 | 270 | # ╔═╡ 58eb1225-6521-45ef-827a-78cdafbaf784 271 | pluto_icon_style = html""" 272 | 279 | """ 280 | 281 | # ╔═╡ 00000000-0000-0000-0000-000000000001 282 | PLUTO_PROJECT_TOML_CONTENTS = """ 283 | [deps] 284 | """ 285 | 286 | # ╔═╡ 00000000-0000-0000-0000-000000000002 287 | PLUTO_MANIFEST_TOML_CONTENTS = """ 288 | # This file is machine-generated - editing it directly is not advised 289 | 290 | julia_version = "1.11.3" 291 | manifest_format = "2.0" 292 | project_hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709" 293 | 294 | [deps] 295 | """ 296 | 297 | # ╔═╡ Cell order: 298 | # ╟─ce092665-e18d-4314-a43e-51a04e25cd30 299 | # ╟─02b26da6-40d1-4b3c-a594-aff8016b0945 300 | # ╠═1adedccd-db89-40ec-ab77-a92c2976fc2c 301 | # ╟─2f8d4781-a364-4803-ba5f-69f85ef1c055 302 | # ╟─50891330-1c60-4020-b4f6-f1200ca2b71d 303 | # ╟─8f45d098-4041-4449-83c3-79280232691e 304 | # ╠═57e3bfde-b692-44e6-a764-7459626a8919 305 | # ╟─688a8ea9-1bff-45c5-8942-f8e96ed0ef79 306 | # ╟─50fa8a8b-2c55-45b6-b4e0-8f510294586c 307 | # ╟─76b5db23-8174-445d-927e-ef2d92bbf32f 308 | # ╟─e548c2ce-0e77-43b2-acaa-97005d67801f 309 | # ╠═f953ef79-b3a5-4adb-8467-b92b5f5bfbce 310 | # ╟─c16b0170-5b0b-4618-b028-b6278bd6319d 311 | # ╟─4dbbfcee-37d0-4361-9058-ea3f9354e2de 312 | # ╟─49fd22a1-63d7-48c3-a1de-67087b77e347 313 | # ╟─9a7e812e-f6bd-47b8-ac36-124a2a233354 314 | # ╟─838cb47d-db5e-4182-b7a1-164f0552bd02 315 | # ╟─9cae62be-7591-4ebe-9fbc-c39be4e479c4 316 | # ╟─dfb656e4-94bc-4b3b-bd09-979d937246b8 317 | # ╟─af97612d-832e-431a-b096-be8d7c94228f 318 | # ╠═99f3bca7-5314-4e86-8f28-bb5a6358bdbd 319 | # ╠═cd5b10ac-0618-4220-b7e3-b1beeea43eff 320 | # ╠═8b622d0d-def6-4a2c-af3b-fdf91240fb90 321 | # ╠═5a399dae-5756-4614-a64f-214e812ee069 322 | # ╠═cca6c895-7974-4c3e-9170-ed85ae127478 323 | # ╠═65b31de3-fe0b-4e2a-97ad-39e4cd17962f 324 | # ╠═3b8ae605-025f-485e-a5a2-1f823319a67a 325 | # ╠═6e315f3b-1a46-483e-86bc-931023a8ac54 326 | # ╠═cb3b24f4-10d1-4de9-bd82-813af622f79b 327 | # ╠═dd004d6c-54f6-4dd7-9aea-910adf0b22a5 328 | # ╟─5b08043c-302b-4b9b-982d-4ba1da41ff9f 329 | # ╟─e7626671-ff5d-45f1-b8df-853d1d9bc1ac 330 | # ╟─4428fe55-7d65-487b-864b-b566e7ecee9e 331 | # ╠═7e5644fd-75ff-4f70-9981-ddb7d9ad470c 332 | # ╠═445eddb1-ccee-45d9-be5b-3f5fec9e2c7a 333 | # ╟─51e38551-742c-48dd-aaea-ffe479b9621b 334 | # ╠═1a2f37ec-9be2-4fd5-8f0b-b6579a241b55 335 | # ╟─d2451923-6487-497c-a169-9815702c42fc 336 | # ╟─64a23ad5-0fa1-48dd-9786-dcfbc73a3b52 337 | # ╟─e392d442-5c83-4711-bc45-c2dbedf62b7f 338 | # ╟─d6def1a3-cc96-4eb9-bfce-949d29ffe31f 339 | # ╟─58eb1225-6521-45ef-827a-78cdafbaf784 340 | # ╟─00000000-0000-0000-0000-000000000001 341 | # ╟─00000000-0000-0000-0000-000000000002 342 | -------------------------------------------------------------------------------- /src/puzzles-games/Tower of Hanoi.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://github.com/JuliaPluto/featured/blob/2a6a9664e5428b37abe4957c1dca0994f4a8b7fd/LICENSES/Unlicense" 6 | #> image = "https://upload.wikimedia.org/wikipedia/commons/0/07/Tower_of_Hanoi.jpeg" 7 | #> tags = ["classic", "puzzle"] 8 | #> license = "Unlicense" 9 | #> description = "An interactive Julia puzzle about stacking disks." 10 | #> 11 | #> [[frontmatter.author]] 12 | #> name = "Luka van der Plas" 13 | #> url = "https://github.com/lukavdplas" 14 | 15 | using Markdown 16 | using InteractiveUtils 17 | 18 | # ╔═╡ 5b2ee40e-a2b8-11ea-0fef-c35fe6918860 19 | md""" 20 | # The tower of Hanoi 21 | 22 | The tower of hanoi is a famous puzzle. 23 | 24 | ![setup of the tower of hanoi](https://upload.wikimedia.org/wikipedia/commons/0/07/Tower_of_Hanoi.jpeg) 25 | 26 | The game consists of three rods with disks stacked on top of them. The puzzle will start with all disks in a stack on one of the rods (like in the picture). The goal is to move all the discs to a single stack on the last rod. 27 | 28 | To move the disks, you have to follow the following rules: 29 | 30 | * You can move only one disk at a time. 31 | * For each move, you have to take the upper disk from one of the stacks, and place it on top of another stack or empty rod. 32 | * You cannot place a larger disk on top of a smaller disk. 33 | 34 | This notebook will define a Julia implementation of the puzzle. It's up to you to write an algorithm that solves it. 35 | """ 36 | 37 | # ╔═╡ 95fbd0d2-a2b9-11ea-0682-fdf783251797 38 | md""" 39 | ## Setting up the game pieces 40 | 41 | What does a Julia implementation look like? We're not really interested in writing code that will manipulate physical disks. Our final goal is a function that will give us a _recipe_ to solve the tower of hanoi, which is just a list of moves to make. Because of that, we can use a lot of abstraction in our implementation, and keep the data structures as simple as possible. 42 | 43 | To start, we have to define some representation of the disks and the stacks. The disks have one important property, which is that they are ordered. We can use integers to represent them. 44 | """ 45 | 46 | # ╔═╡ 620d6834-a2ba-11ea-150a-2132bb54e4b3 47 | num_disks = 8 48 | 49 | # ╔═╡ 35ada214-a32c-11ea-0da3-d5d494b28467 50 | md"""(Side note: the number of disks is arbitrary. When testing your function, you may want to set it to 1 or 2 to start.)""" 51 | 52 | # ╔═╡ 7243cc8e-a2ba-11ea-3f29-99356f0cdcf4 53 | all_disks = 1:num_disks 54 | 55 | # ╔═╡ 7e1ba2ac-a2ba-11ea-0134-2f61ed75be18 56 | md""" 57 | A single stack can be represented as an array with all the disks in it. We will list them from top to bottom. 58 | """ 59 | 60 | # ╔═╡ 43781a52-a339-11ea-3803-e56e2d08aa83 61 | first_stack = collect(all_disks) 62 | 63 | # ╔═╡ b648ab70-a2ba-11ea-2dcc-55b630e44325 64 | md""" 65 | Now we have to make three of those. 66 | """ 67 | 68 | # ╔═╡ 32f26f80-a2bb-11ea-0f2a-3fc631ada63d 69 | starting_stacks = [first_stack, [], []] 70 | 71 | # ╔═╡ e347f1de-a2bb-11ea-06e7-87cca6f2a240 72 | md""" 73 | ## Defining the rules 74 | 75 | Now that we have our "game board", we can implement the rules. 76 | 77 | To start, we make two functions for states. A state of the game is just an array of stacks. 78 | 79 | We will define a function that checks if a state is okay according to the rules. To be legal, all the stacks should be in the correct order, so no larger disks on top of smaller disks. 80 | 81 | Another good thing to check: no disks should have appeared or disappeared since we started! 82 | """ 83 | 84 | # ╔═╡ 512fa6d2-a2bd-11ea-3dbe-b935b536967b 85 | function islegal(stacks) 86 | order_correct = all(issorted, stacks) 87 | 88 | #check if we use the same disk set that we started with 89 | 90 | disks_in_state = sort([disk for stack in stacks for disk in stack]) 91 | disks_complete = disks_in_state == all_disks 92 | 93 | order_correct && disks_complete 94 | end 95 | 96 | # ╔═╡ c56a5858-a2bd-11ea-1d96-77eaf5e74925 97 | md""" 98 | Another function for states: check if we are done! We can assume that we already checked if the state was legal. So we know that all the disks are there and they are ordered correctly. To check if we are finished, we just need to check if the last stack contains all the disks. 99 | """ 100 | 101 | # ╔═╡ d5cc41e8-a2bd-11ea-39c7-b7df8de6ae3e 102 | function iscomplete(stacks) 103 | last(stacks) == all_disks 104 | end 105 | 106 | # ╔═╡ 53374f0e-a2c0-11ea-0c91-97474780721e 107 | md""" 108 | Now the only rules left to implement are the rules for moving disks. 109 | 110 | We could implement this as another check on states, but it's easier to just write a legal `move` function. Your solution will specify moves for the `move` function, so this will be the only way that the stacks are actually manipulated. That way, we are sure that nothing fishy is happening. 111 | 112 | We will make our `move` function so that its input consists of a state of the game, and instructions for what to do. Its output will be the new state of the game. 113 | 114 | So what should those instructions look like? It may seem intuitive to give a _disk_ that should be moved, but that's more than we need. After all, we are only allowed to take the top disk from one stack, and move it to the top of another. So we only have to say which _stacks_ we are moving between. 115 | 116 | (Note that the `move` function is okay with moving a larger disk on top of a smaller disk. We already implemented that restriction in `islegal`.) 117 | """ 118 | 119 | # ╔═╡ e915394e-a2c0-11ea-0cd9-1df6fd3c7adf 120 | function move(stacks, source::Int, target::Int) 121 | #check if the from stack if not empty 122 | if isempty(stacks[source]) 123 | error("Error: attempted to move disk from empty stack") 124 | end 125 | 126 | new_stacks = deepcopy(stacks) 127 | 128 | disk = popfirst!(new_stacks[source]) #take disk 129 | pushfirst!(new_stacks[target], disk) #put on new stack 130 | 131 | return new_stacks 132 | end 133 | 134 | # ╔═╡ 87b2d164-a2c4-11ea-3095-916628943879 135 | md""" 136 | ## Solving the problem 137 | 138 | We have implemented the game pieces and the rules, so you can start working on your solution. 139 | 140 | To do this, you can fill in the `solve(stacks)` function. This function should give a solution for the given `stacks`, by moving all the disks from stack 1 to stack 3. 141 | 142 | As output, `solve` should give a recipe, that tells us what to do. This recipe should be an array of moves. Each moves is a `(source, target)` tuple, specifying from which stack to which stack you should move. 143 | 144 | For example, it might look like this: 145 | """ 146 | 147 | # ╔═╡ 29b410cc-a329-11ea-202a-795b31ce5ad5 148 | function wrong_solution(stacks)::Array{Tuple{Int, Int}} 149 | return [(1,2), (2,3), (2,1), (1,3)] 150 | end 151 | 152 | # ╔═╡ ea24e778-a32e-11ea-3f11-dbe9d36b1011 153 | md""" 154 | Now you can work on building an actual solution. Some tips: 155 | * `solve(stacks)` can keep track of the board if you want, but it doesn't have to. 156 | * The section below will actually run your moves, which is very useful for checking them. 157 | * If you want, you can change `num_disks` to 1 or 2. That can be a good starting point. 158 | """ 159 | 160 | # ╔═╡ 010dbdbc-a2c5-11ea-34c3-837eae17416f 161 | function solve(start = starting_stacks)::Array{Tuple{Int, Int}} 162 | 163 | #what to do? 164 | 165 | return [] 166 | end 167 | 168 | # ╔═╡ 3eb3c4c0-a2c5-11ea-0bcc-c9b52094f660 169 | md""" 170 | ## Checking solutions 171 | 172 | This is where we can check a solution. We start with a function that takes our recipe and runs it. 173 | """ 174 | 175 | # ╔═╡ 4709db36-a327-11ea-13a3-bbfb18da84ce 176 | function run_solution(solver::Function, start = starting_stacks) 177 | moves = solver(deepcopy(start)) #apply the solver 178 | 179 | all_states = Vector{Any}(undef, length(moves) + 1) 180 | all_states[1] = start 181 | 182 | for (i, m) in enumerate(moves) 183 | try 184 | all_states[i + 1] = move(all_states[i], m[1], m[2]) 185 | catch 186 | all_states[i + 1] = missing 187 | end 188 | end 189 | 190 | return all_states 191 | end 192 | 193 | # ╔═╡ 372824b4-a330-11ea-2f26-7b9a1ad018f1 194 | md""" 195 | You can use this function to see what your solution does. 196 | 197 | If `run_solution` tries to make an impossible move, it will give `missing` from that point onwards. Look at what happens in the `wrong_solution` version and compare it to the moves in `wrong_solution`. 198 | """ 199 | 200 | # ╔═╡ d2227b40-a329-11ea-105c-b585d5fcf970 201 | run_solution(wrong_solution) 202 | 203 | # ╔═╡ 9173b174-a327-11ea-3a69-9f7525f2e7b4 204 | run_solution(solve) 205 | 206 | # ╔═╡ bb5088ec-a330-11ea-2c41-6b8b92724b3b 207 | md""" 208 | Now that we have way to run a recipe, we can check if its output is correct. We will check if all the intermediate states are legal and the final state is the finished puzzle. 209 | """ 210 | 211 | # ╔═╡ 10fb1c56-a2c5-11ea-2a06-0d8c36bfa138 212 | function check_solution(solver::Function, start = starting_stacks) 213 | try 214 | #run the solution 215 | all_states = run_solution(solver, start) 216 | 217 | #check if each state is legal 218 | all_legal = all(islegal, all_states) 219 | 220 | #check if the final state is is the completed puzzle 221 | complete = (iscomplete ∘ last)(all_states) 222 | 223 | all_legal && complete 224 | catch 225 | #return false if we encountered an error 226 | return false 227 | end 228 | end 229 | 230 | # ╔═╡ 8ea7f944-a329-11ea-22cc-4dbd11ec0610 231 | check_solution(solve) 232 | 233 | # ╔═╡ e54add0a-a330-11ea-2eeb-1d42f552ba38 234 | if check_solution(solve) 235 | if num_disks >= 8 236 | md""" 237 | #### Congratulations, your solution works! 😎 238 | """ 239 | else 240 | md""" 241 | Your solution works for $(num_disks) disks. Change `num_disks` to see if it works for 8 or more. 242 | """ 243 | end 244 | else 245 | md""" 246 | The `solve` function doesn't work yet. Keep working on it! 247 | """ 248 | end 249 | 250 | # ╔═╡ 00000000-0000-0000-0000-000000000001 251 | PLUTO_PROJECT_TOML_CONTENTS = """ 252 | [deps] 253 | """ 254 | 255 | # ╔═╡ 00000000-0000-0000-0000-000000000002 256 | PLUTO_MANIFEST_TOML_CONTENTS = """ 257 | # This file is machine-generated - editing it directly is not advised 258 | 259 | julia_version = "1.11.3" 260 | manifest_format = "2.0" 261 | project_hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709" 262 | 263 | [deps] 264 | """ 265 | 266 | # ╔═╡ Cell order: 267 | # ╟─5b2ee40e-a2b8-11ea-0fef-c35fe6918860 268 | # ╟─95fbd0d2-a2b9-11ea-0682-fdf783251797 269 | # ╠═620d6834-a2ba-11ea-150a-2132bb54e4b3 270 | # ╟─35ada214-a32c-11ea-0da3-d5d494b28467 271 | # ╠═7243cc8e-a2ba-11ea-3f29-99356f0cdcf4 272 | # ╟─7e1ba2ac-a2ba-11ea-0134-2f61ed75be18 273 | # ╠═43781a52-a339-11ea-3803-e56e2d08aa83 274 | # ╟─b648ab70-a2ba-11ea-2dcc-55b630e44325 275 | # ╠═32f26f80-a2bb-11ea-0f2a-3fc631ada63d 276 | # ╟─e347f1de-a2bb-11ea-06e7-87cca6f2a240 277 | # ╠═512fa6d2-a2bd-11ea-3dbe-b935b536967b 278 | # ╟─c56a5858-a2bd-11ea-1d96-77eaf5e74925 279 | # ╠═d5cc41e8-a2bd-11ea-39c7-b7df8de6ae3e 280 | # ╟─53374f0e-a2c0-11ea-0c91-97474780721e 281 | # ╠═e915394e-a2c0-11ea-0cd9-1df6fd3c7adf 282 | # ╟─87b2d164-a2c4-11ea-3095-916628943879 283 | # ╠═29b410cc-a329-11ea-202a-795b31ce5ad5 284 | # ╟─ea24e778-a32e-11ea-3f11-dbe9d36b1011 285 | # ╠═010dbdbc-a2c5-11ea-34c3-837eae17416f 286 | # ╟─3eb3c4c0-a2c5-11ea-0bcc-c9b52094f660 287 | # ╠═4709db36-a327-11ea-13a3-bbfb18da84ce 288 | # ╟─372824b4-a330-11ea-2f26-7b9a1ad018f1 289 | # ╠═d2227b40-a329-11ea-105c-b585d5fcf970 290 | # ╠═9173b174-a327-11ea-3a69-9f7525f2e7b4 291 | # ╟─bb5088ec-a330-11ea-2c41-6b8b92724b3b 292 | # ╠═10fb1c56-a2c5-11ea-2a06-0d8c36bfa138 293 | # ╠═8ea7f944-a329-11ea-22cc-4dbd11ec0610 294 | # ╟─e54add0a-a330-11ea-2eeb-1d42f552ba38 295 | # ╟─00000000-0000-0000-0000-000000000001 296 | # ╟─00000000-0000-0000-0000-000000000002 297 | -------------------------------------------------------------------------------- /src/basic/Getting started.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://github.com/JuliaPluto/featured/blob/2a6a9664e5428b37abe4957c1dca0994f4a8b7fd/LICENSES/Unlicense" 6 | #> image = "https://user-images.githubusercontent.com/6933510/174066314-d338f28b-36cf-48e0-981f-dd0f140ad66c.png" 7 | #> order = "1" 8 | #> tags = ["classic"] 9 | #> license = "Unlicense" 10 | #> description = "Welcome to Pluto!" 11 | #> 12 | #> [[frontmatter.author]] 13 | #> name = "Pluto.jl" 14 | #> url = "https://github.com/JuliaPluto" 15 | 16 | using Markdown 17 | using InteractiveUtils 18 | 19 | # This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). 20 | macro bind(def, element) 21 | #! format: off 22 | return quote 23 | local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end 24 | local el = $(esc(element)) 25 | global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) 26 | el 27 | end 28 | #! format: on 29 | end 30 | 31 | # ╔═╡ b129ba7c-953a-11ea-3379-17adae34924c 32 | md"# _Welcome to Pluto!_ 33 | 34 | Pluto is a programming environment for _Julia_, designed to be **interactive** and **helpful**. 35 | 36 | In this introduction, we will go through the basics of using Pluto. To make it interesting, this notebook does something special: it **changes while you work on it**. Computer magic ✨" 37 | 38 | # ╔═╡ 4d88b926-9543-11ea-293a-1379b1b5ae64 39 | md"## Cats 40 | Let's say you're like my grandma, and you have a lot of cats. Our story will be about them." 41 | 42 | # ╔═╡ 3e8e381e-953f-11ea-3d3e-71d0fea52560 43 | cat = "Ks*;lj" 44 | 45 | # ╔═╡ aeb3a6bc-9540-11ea-0b8f-6d37412bfe68 46 | if cat == "Ks*;lj" 47 | md"Oh no! Someone messed with my pretty introduction. Change the code above to give our cat a proper name!" 48 | else 49 | HTML("""

Well done, your cat is called $cat now. This text gets updated every time you change the name. To see how the magic works, click on the to the left of this text.

""") 50 | end 51 | 52 | # ╔═╡ 611c28fa-9542-11ea-1751-fbdedcfb7690 53 | html"""

To edit any code, just click on it. When you're done programming, press the in the lower-right corner of a cell to run the code. You can also use Shift+Enter if you are in a hurry.

""" 54 | 55 | # ╔═╡ 6f7eecec-9543-11ea-1284-dd52fce3ecca 56 | md"I feel like our cat needs a friend. Let's call them $(friend)." 57 | 58 | # ╔═╡ a1a20314-9543-11ea-17de-0b658da18992 59 | if !@isdefined friend 60 | md"Uh oh, what is this? I forgot to add a cell defining our friend. Can you do it for me?" 61 | else 62 | md"**Well done!** $cat and $friend are both happy with your performance." 63 | end 64 | 65 | # ╔═╡ f112b662-9543-11ea-3dcb-2906a99b2188 66 | html"""

A cell is a container for code & output. To add one, click on the above or below another cell. You can do it wherever you like. After you're done writing code in your cell, remember to run it!

""" 67 | 68 | # ╔═╡ e0642f42-9545-11ea-14ee-fde52cb54ccc 69 | md"## Feeding neighbors 70 | Our cats have some neighbors. Let's involve them in the story too!" 71 | 72 | # ╔═╡ 3653b1ac-9546-11ea-2a44-ddd3054636fe 73 | neighbors = [cat, friend, "Smerfetka", "Latte"] 74 | 75 | # ╔═╡ 19ff8d36-9547-11ea-0e08-e5cdd8338673 76 | md"Now, if you're like my grandma, you're feeding the entire neighborhood by yourself. Let's see how many cans of cat food you need to prepare." 77 | 78 | # ╔═╡ 270ac49e-9549-11ea-3ffd-71ddaee9f134 79 | md"But what does `confusing_function` do? If you ever need help, click on 📚 **Live docs** in the lower right, and then place your cursor on the code you need help with. 80 | 81 | If you don't see it, then your screen is too small! Maybe you need to zoom out?" 82 | 83 | # ╔═╡ 745a4584-954a-11ea-028e-59011f268ec6 84 | cans_in_stock = "🥫🥫🥫🥫" 85 | 86 | # ╔═╡ 55ad7422-954e-11ea-0a33-a3b03febb56e 87 | if @isdefined cans_in_stock 88 | md"Actually, I have a hunch there will be another cat coming. Uncomment the code below (remove the #) to add one more can. Remember to run it after making the change!" 89 | else 90 | md"**Whoopsie!** Because Pluto figures out execution order for you, it doesn't really make sense to assign to the same variable twice. A smarter way to plan ahead is to write `cans_in_stock = consumption` — Pluto will take care of updating everything." 91 | end 92 | 93 | # ╔═╡ eac62fea-954e-11ea-2768-39ce6f4059ab 94 | # cans_in_stock = "🥫🥫🥫🥫🥫" 95 | 96 | # ╔═╡ 6c8e2108-9550-11ea-014d-235770ed4771 97 | md"## Saving cats and notebooks 98 | Alright, we have a neighborhood full of well-fed cats. But oh no, here comes..." 99 | 100 | # ╔═╡ 9e89fc9a-9550-11ea-14b4-7f0e96225ec0 101 | scary_dog = "Piesio" 102 | 103 | # ╔═╡ bdd5d268-9550-11ea-1046-31efedc36872 104 | if @isdefined scary_dog 105 | md" $scary_dog is terrorizing the neighborhood! We must do something about it!" 106 | else 107 | md"You saved the neighborhood! Referencing `scary_dog` leads to an `UndefVarError`, as if it never even existed." 108 | end 109 | 110 | # ╔═╡ 36cd006a-9551-11ea-3c0c-df8b7f2843c1 111 | HTML("""

To delete a cell like the one defining $scary_dog, click on the on the right of its code.

""") 112 | 113 | # ╔═╡ fb4e471c-9551-11ea-1ab5-41bbd5de76b8 114 | md""" 115 | Speaking of saving, this notebook is autosaved whenever you change something. The default location for new notebooks is $(joinpath(first(DEPOT_PATH), "pluto_notebooks")), you can find it using your file explorer. To change the name or the directory of a notebook, scroll to the top - you enter the notebook's path next to the Pluto logo. 116 | """ 117 | 118 | # ╔═╡ 9d3af596-9554-11ea-21bd-bf427c91c424 119 | md"## ⚡ Pluto power ⚡ 120 | Oof, that dog situation was intense. Let's give our cats superpowers to make sure it never happens again!" 121 | 122 | # ╔═╡ 3150bf1a-9555-11ea-306f-0fd4d9229a51 123 | md"Remember learning HTML in junior high? Now you can use it for something! Pluto lets you `@bind` variables to HTML elements. As always, every time you change something, Pluto knows what to update!" 124 | 125 | # ╔═╡ f2c79746-9554-11ea-39ca-298fd09248ad 126 | @bind power_level html"" 127 | 128 | # ╔═╡ 0b094cea-9556-11ea-268e-0d270fd04d56 129 | md"The power level is $power_level, but we should do more than just say it - let's equip our cats with $power_level emoji!" 130 | 131 | # ╔═╡ 1908f9f2-9557-11ea-2abd-dd52f8d776f4 132 | power_emoji = "⚡" 133 | power = repeat(power_emoji, power_level) 134 | 135 | # ╔═╡ 784b1774-9557-11ea-315e-d1ea277ce0fd 136 | if !@isdefined power 137 | md"Uh oh! Pluto doesn't support multiple expressions per cell. This is a conscious choice - this restriction helps you write less buggy code once you get used to it. To fix the code, you can either split the above cell, or wrap it in a `begin ... end` block. Both work." 138 | else 139 | md"**Well done!** Your cats have powers now." 140 | end 141 | 142 | # ╔═╡ 5edadcd2-9554-11ea-1714-b5b7692c4797 143 | html"""

We're almost done! It's time to share your amazing story. Scroll to the top of the notebook, and click on to see the export options - or you can always share this notebook's save file. (The file is pure Julia, by the way, and it's runnable! You'll learn more about this in the advanced introduction.)

""" 144 | 145 | # ╔═╡ 4634c856-9553-11ea-008d-3539195970ea 146 | md"## Final notes" 147 | 148 | # ╔═╡ 4d0ebb46-9553-11ea-3431-2d203f594815 149 | md"If anything about this introduction left you confused, something doesn't work, or you have a cool new idea - don't hesitate to contact us! You can do it right from this screen, using the `Instant feedback` form in the bottom right." 150 | 151 | # ╔═╡ d736e096-9553-11ea-3ba5-277afde1afe7 152 | md"Also, if you were wondering where `confusing_function` came from, here you go! Remember that you, too, can place code wherever you like." 153 | 154 | # ╔═╡ 7366f1b6-954c-11ea-3f68-b12444c902c3 155 | """ 156 | confusing_function(text::String, array::Array) 157 | 158 | Repeats the `text` as many times as there are elements in `array`. 159 | """ 160 | confusing_function(text::String, array::Array) = repeat(text, length(array)) 161 | 162 | # ╔═╡ a4a60262-9547-11ea-3a81-5bf7f9ee5d16 163 | consumption = confusing_function("🥫", neighbors) 164 | 165 | # ╔═╡ e11e1660-9549-11ea-22f6-8bb53dc045fe 166 | md"Now we know to prepare $(length(consumption)) cans. Let's stock up!" 167 | 168 | # ╔═╡ f27f90c2-954f-11ea-3f93-17acb2ce4280 169 | md"We have $(length(cans_in_stock)) cans of cat food, and our cats need $(length(consumption)). Try adding another cat to the neighborhood to see what changes!" 170 | 171 | # ╔═╡ 1deaaf36-9554-11ea-3dae-85851f73dbc6 172 | md"**Have fun using Pluto!** 173 | 174 | _~ Fons van der Plas & Nicholas Bochenski_" 175 | 176 | # ╔═╡ f7588ff8-4eac-4c5a-bc06-0983bc4d5ee1 177 | html""" 178 | 185 | """ 186 | 187 | # ╔═╡ 00000000-0000-0000-0000-000000000001 188 | PLUTO_PROJECT_TOML_CONTENTS = """ 189 | [deps] 190 | """ 191 | 192 | # ╔═╡ 00000000-0000-0000-0000-000000000002 193 | PLUTO_MANIFEST_TOML_CONTENTS = """ 194 | # This file is machine-generated - editing it directly is not advised 195 | 196 | julia_version = "1.11.3" 197 | manifest_format = "2.0" 198 | project_hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709" 199 | 200 | [deps] 201 | """ 202 | 203 | # ╔═╡ Cell order: 204 | # ╟─b129ba7c-953a-11ea-3379-17adae34924c 205 | # ╟─4d88b926-9543-11ea-293a-1379b1b5ae64 206 | # ╠═3e8e381e-953f-11ea-3d3e-71d0fea52560 207 | # ╟─aeb3a6bc-9540-11ea-0b8f-6d37412bfe68 208 | # ╟─611c28fa-9542-11ea-1751-fbdedcfb7690 209 | # ╠═6f7eecec-9543-11ea-1284-dd52fce3ecca 210 | # ╟─a1a20314-9543-11ea-17de-0b658da18992 211 | # ╟─f112b662-9543-11ea-3dcb-2906a99b2188 212 | # ╟─e0642f42-9545-11ea-14ee-fde52cb54ccc 213 | # ╠═3653b1ac-9546-11ea-2a44-ddd3054636fe 214 | # ╟─19ff8d36-9547-11ea-0e08-e5cdd8338673 215 | # ╠═a4a60262-9547-11ea-3a81-5bf7f9ee5d16 216 | # ╟─270ac49e-9549-11ea-3ffd-71ddaee9f134 217 | # ╟─e11e1660-9549-11ea-22f6-8bb53dc045fe 218 | # ╠═745a4584-954a-11ea-028e-59011f268ec6 219 | # ╟─55ad7422-954e-11ea-0a33-a3b03febb56e 220 | # ╠═eac62fea-954e-11ea-2768-39ce6f4059ab 221 | # ╟─f27f90c2-954f-11ea-3f93-17acb2ce4280 222 | # ╟─6c8e2108-9550-11ea-014d-235770ed4771 223 | # ╠═9e89fc9a-9550-11ea-14b4-7f0e96225ec0 224 | # ╟─bdd5d268-9550-11ea-1046-31efedc36872 225 | # ╟─36cd006a-9551-11ea-3c0c-df8b7f2843c1 226 | # ╟─fb4e471c-9551-11ea-1ab5-41bbd5de76b8 227 | # ╟─9d3af596-9554-11ea-21bd-bf427c91c424 228 | # ╟─3150bf1a-9555-11ea-306f-0fd4d9229a51 229 | # ╠═f2c79746-9554-11ea-39ca-298fd09248ad 230 | # ╟─0b094cea-9556-11ea-268e-0d270fd04d56 231 | # ╠═1908f9f2-9557-11ea-2abd-dd52f8d776f4 232 | # ╟─784b1774-9557-11ea-315e-d1ea277ce0fd 233 | # ╟─5edadcd2-9554-11ea-1714-b5b7692c4797 234 | # ╟─4634c856-9553-11ea-008d-3539195970ea 235 | # ╟─4d0ebb46-9553-11ea-3431-2d203f594815 236 | # ╟─d736e096-9553-11ea-3ba5-277afde1afe7 237 | # ╟─7366f1b6-954c-11ea-3f68-b12444c902c3 238 | # ╟─1deaaf36-9554-11ea-3dae-85851f73dbc6 239 | # ╟─f7588ff8-4eac-4c5a-bc06-0983bc4d5ee1 240 | # ╟─00000000-0000-0000-0000-000000000001 241 | # ╟─00000000-0000-0000-0000-000000000002 242 | -------------------------------------------------------------------------------- /src/web/CSS.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://github.com/JuliaPluto/featured/blob/main/LICENSES/Unlicense" 6 | #> image = "https://github.com/JuliaPluto/featured/assets/43678097/ebcd0d6c-fa37-4d2b-8d82-6814854f726b" 7 | #> order = "2" 8 | #> title = "Styling with CSS" 9 | #> tags = ["web", "css"] 10 | #> license = "Unlicense" 11 | #> description = "Learn how to use CSS to give a unique style to your notebooks!" 12 | #> 13 | #> [[frontmatter.author]] 14 | #> name = "Pluto.jl" 15 | #> url = "https://github.com/JuliaPluto" 16 | 17 | using Markdown 18 | using InteractiveUtils 19 | 20 | # ╔═╡ 9e7188e0-9e7f-11ee-1fef-b56479103e4a 21 | md""" 22 | # Styling notebooks with CSS 23 | 24 | Are you looking bring your notebook presentation to the next level? Do you want to change the way Pluto looks for you? Do you want special formatting for your cell output? 25 | 26 | This is the notebook for you! We'll talk about how to style the notebook page using CSS. Let's get started! 27 | """ 28 | 29 | # ╔═╡ 01455807-c26e-478b-a871-f2b28526b5d9 30 | md""" 31 | ## What is CSS? 32 | 33 | CSS stands for _cascading style sheets_ and it's the language we use to describe what web content should look like. 34 | 35 | A typical web page is written in HTML. HTML is essentially text with tags, which your browser is able to make sense of. For example: 36 | """ 37 | 38 | # ╔═╡ 0bbfdbd5-91cd-4faf-98ef-ed2401c7de15 39 | html""" 40 |

I like apples...

41 |

but I don't like oranges.

42 | """ 43 | 44 | # ╔═╡ df764c10-adc0-4552-b1cf-a77afb9fbe27 45 | md""" 46 | In this case, `

`, ``, and `` are tags. When your browser displays this text, it understands that when you use the `` tag, it should be displayed in a particular way - in this case, by writing the text in italics. 47 | """ 48 | 49 | # ╔═╡ 4812a04f-0e9f-484f-9253-cef3b3667a23 50 | md""" 51 | A CSS stylesheet is what we use to control exactly what each element should look like. 52 | 53 | It lists _selectors_ for elements in the HTML content and then describes the desired look of those elements. 54 | 55 | Here is an example. We have some text: 56 | """ 57 | 58 | # ╔═╡ d6c7985c-ff4b-4799-951f-093bfe920f98 59 | html""" 60 | I don't like oranges! 61 | """ 62 | 63 | # ╔═╡ 30e31be7-8aa1-4a00-913d-7af3388d71b2 64 | md""" 65 | And here is a stylesheet: 66 | """ 67 | 68 | # ╔═╡ e70d7a55-7eff-4c29-9af2-3288d99fb37c 69 | html""" 70 | 75 | """ 76 | 77 | # ╔═╡ cdf0c733-bbf0-4e2f-832b-19e13e7fe561 78 | md""" 79 | What's happening here? 80 | 81 | - Our first cell contains the tag ``. A span is a _generic_ element that just tags a selection of text. It doesn't really do anything. 82 | - The span tag includes another attribute: `id="orange"`. That's a way of giving a unique name to this element. 83 | - We then write some style rules in a ` 123 | """ 124 | 125 | # ╔═╡ 6d224e02-a713-41df-a11c-80f39b7a90f8 126 | md""" 127 | ## CSS selectors 128 | 129 | So far we've used the `id` of elements to describe what they should look like. That's a fine way to do things if we want to style a specific element, like the output of a single cell. 130 | 131 | But a lot of the time, we want to write more _general_ rules that describe the overall layout of the page, like "every code cell should have a blue background" or "images should have a margin of 100 pixels". 132 | 133 | Luckily, CSS selectors can do a lot more than selecting elements by their ID. Let's go over the fundamentals. 134 | """ 135 | 136 | # ╔═╡ 4a0aaf47-3685-4b01-bd57-f1ea0a09d01a 137 | html""" 138 | We've already seen one type of selector: selecting the id of the element. 139 | 140 | 146 | """ 147 | 148 | # ╔═╡ 8c0bd2dd-f819-4f77-ba27-23119a216636 149 | html""" 150 | You can also select the name of the tag. This is useful for very generic selectors, like "any paragraph". 151 | 152 | 158 | """ 159 | 160 | # ╔═╡ b6279fae-90fc-430f-bcb6-1d79f0e98fba 161 | html""" 162 |

163 | Sometimes we want something a bit more fine-tuned than the element type: not all paragraphs, but some of them. We can't use IDs here: those are meant to be unique. 164 |

165 | 166 |

167 | In this case, we usually use the class attribute. That's a way of saying a bunch of elements belong to a particular category. Then you can select elements of a class. 168 |

169 | 170 | 176 | """ 177 | 178 | # ╔═╡ 18613f4c-7beb-4051-ab75-1c3db8c4c97a 179 | md""" 180 | Alright, so we can select by the element type, the unique ID of the element, or the class name we assign to the element. We can also combine selectors! 181 | """ 182 | 183 | # ╔═╡ 8f553705-9f6f-4b0e-babc-1170cede56e6 184 | html""" 185 |

186 | This is the first example. 187 |

188 |

189 | This is the second 191 |

192 | This is the third 194 | 195 | 222 | """ 223 | 224 | # ╔═╡ 89f79aa7-bcea-43a7-9596-ec347d67e03b 225 | md""" 226 | There is a lot more that you can do with CSS selectors, but this is already very powerful, and it should be enough to get you underway! 227 | """ 228 | 229 | # ╔═╡ 2c867409-ed53-42db-960d-27d3a25ab1b7 230 | md""" 231 | ### Exercise: CSS selectors 232 | 233 | 👉 **Your turn!** Match up the colours with the story! 234 | """ 235 | 236 | # ╔═╡ 7af3994f-b0a1-40c1-9c64-f401a58bbfc7 237 | html""" 238 |

239 |

240 | I have a red bike but my shoes are green. 241 |

242 |

243 | Yesterday a blue car drove by and splashed brown mud all over my shoes. 244 |

245 |

246 | Luckily, my new purple coat was still clean! I hopped on my bike and went to the shoe cleaner. 247 |

248 |
249 | 250 | 262 | """ 263 | 264 | # ╔═╡ fbf50d51-ba14-4f51-8820-aa1df38fb606 265 | md""" 266 | ### Learn more about CSS 267 | 268 | If this was all new to you so far, there is a lot more you can do with CSS - much more than we can cover in this notebook. 269 | 270 | Luckily, CSS is widely used to there are plenty of tutorials available. I frequently use [MDN's CSS guide and reference](https://developer.mozilla.org/en-US/docs/Web/CSS)! 271 | """ 272 | 273 | # ╔═╡ c211b0c4-3801-4a49-ab78-692420240129 274 | md""" 275 | ## Styling Pluto 276 | 277 | Okay, we've gone over the basics of CSS and we've done some styling. How do we go about styling notebooks? 278 | 279 | There are two things you may want to use CSS for: styling the output of specific cells, or styling the whole notebook page. 280 | """ 281 | 282 | # ╔═╡ dd8f6a67-3a00-4ca8-aaf4-c8d2a320dda0 283 | md""" 284 | ### Selection scope 285 | 286 | When you create a ` 296 | """ 297 | 298 | # ╔═╡ db10ee0f-065e-4207-a20b-37ae17d8bbfe 299 | md""" 300 | With that in mind, let's look at our two uses for styling. 301 | """ 302 | 303 | # ╔═╡ 9483d382-1586-4668-8c1d-89d4afc46fa2 304 | md""" 305 | ### Styling specific cells 306 | 307 | If you want to add some styling to the output of specific styles, it's good to avoid statements that can accidentally affect the whole page. 308 | 309 | A good way to do this is to wrap your cell in a tag with a `class` or `id`. Then when you write rules for that cell, write all your rules within that class or ID. 310 | """ 311 | 312 | # ╔═╡ 063a220c-58fb-4113-8f14-a2b4fe0c5791 313 | html""" 314 |
315 | This cell has special formatting. 316 |
317 | """ 318 | 319 | # ╔═╡ 0d4dac94-3b71-4cb0-be7d-52fe63878a2f 320 | html""" 321 |
322 | So does this one! 323 |
324 | """ 325 | 326 | # ╔═╡ 3f457aad-ffe9-4453-b11b-2e74e7bb45a1 327 | html""" 328 | But this is just a plain-looking cell! 329 | """ 330 | 331 | # ╔═╡ 7d989347-3aa1-4bc7-8202-d2590bfd2a4e 332 | html""" 333 | 345 | """ 346 | 347 | # ╔═╡ 0edc1d57-baff-4372-94bb-55cea542ebbc 348 | md""" 349 | !!! info "What's a div?" 350 | 351 | We used `
` as the top-level tag in these examples. `
` stands for division: it's a generic element meant to divide the content of a page into parts without really saying anything else about what those parts are for - it's a suitable generic wrapper for cell output. 352 | """ 353 | 354 | # ╔═╡ 00398409-91c3-4bec-8f80-d53d71c33bdd 355 | md""" 356 | If the style is supposed to apply to a single cell, it often makes sense to write it in there, like we've seen in this notebook a few times. But doing so won't restrict the styling to that cell: you should still use a selector. 357 | """ 358 | 359 | # ╔═╡ d1e9080c-e998-43a0-8f57-759c24b3207a 360 | html""" 361 |
362 |

This cell has its own styling!

363 |
364 | 365 | 372 | """ 373 | 374 | # ╔═╡ a08b40ea-9d80-4552-83bc-50d0c1bdaa13 375 | md""" 376 | ## Styling Pluto 377 | 378 | What if we _don't_ want to style specific cells? 379 | 380 | Sometimes it's useful to style the entire page. For instance, you could change the layout of a notebook for a presentation to show bigger text or hide the live docs. Or maybe you just have a personal preference to show all text in purple! 381 | 382 | We've already seen that ` 397 | """ 398 | 399 | # ╔═╡ d9ac05cc-3c54-46fc-bf28-ad38418fe413 400 | md""" 401 | Keep in mind that Pluto doesn't guarantee a stable API for styling. That is to say, new versions of Pluto might change class names or element names, or just slightly restyle the page in a way that messes up your own styling rules. 402 | 403 | That said, Pluto has been around for a while, so you can expect it to be reasonably stable. 404 | """ 405 | 406 | # ╔═╡ 00000000-0000-0000-0000-000000000001 407 | PLUTO_PROJECT_TOML_CONTENTS = """ 408 | [deps] 409 | """ 410 | 411 | # ╔═╡ 00000000-0000-0000-0000-000000000002 412 | PLUTO_MANIFEST_TOML_CONTENTS = """ 413 | # This file is machine-generated - editing it directly is not advised 414 | 415 | julia_version = "1.11.3" 416 | manifest_format = "2.0" 417 | project_hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709" 418 | 419 | [deps] 420 | """ 421 | 422 | # ╔═╡ Cell order: 423 | # ╟─9e7188e0-9e7f-11ee-1fef-b56479103e4a 424 | # ╟─01455807-c26e-478b-a871-f2b28526b5d9 425 | # ╠═0bbfdbd5-91cd-4faf-98ef-ed2401c7de15 426 | # ╟─df764c10-adc0-4552-b1cf-a77afb9fbe27 427 | # ╟─4812a04f-0e9f-484f-9253-cef3b3667a23 428 | # ╠═d6c7985c-ff4b-4799-951f-093bfe920f98 429 | # ╟─30e31be7-8aa1-4a00-913d-7af3388d71b2 430 | # ╠═e70d7a55-7eff-4c29-9af2-3288d99fb37c 431 | # ╟─cdf0c733-bbf0-4e2f-832b-19e13e7fe561 432 | # ╟─0742d69f-246c-4c69-ae48-e80fc4ed3cf5 433 | # ╠═e6f1b9dc-8243-4d11-bd21-aa37396cb1e7 434 | # ╟─6d224e02-a713-41df-a11c-80f39b7a90f8 435 | # ╠═4a0aaf47-3685-4b01-bd57-f1ea0a09d01a 436 | # ╠═8c0bd2dd-f819-4f77-ba27-23119a216636 437 | # ╠═b6279fae-90fc-430f-bcb6-1d79f0e98fba 438 | # ╟─18613f4c-7beb-4051-ab75-1c3db8c4c97a 439 | # ╠═8f553705-9f6f-4b0e-babc-1170cede56e6 440 | # ╟─89f79aa7-bcea-43a7-9596-ec347d67e03b 441 | # ╟─2c867409-ed53-42db-960d-27d3a25ab1b7 442 | # ╠═7af3994f-b0a1-40c1-9c64-f401a58bbfc7 443 | # ╟─fbf50d51-ba14-4f51-8820-aa1df38fb606 444 | # ╟─c211b0c4-3801-4a49-ab78-692420240129 445 | # ╟─dd8f6a67-3a00-4ca8-aaf4-c8d2a320dda0 446 | # ╠═ad900671-1662-415e-a1a2-48fcef3df6e2 447 | # ╟─db10ee0f-065e-4207-a20b-37ae17d8bbfe 448 | # ╟─9483d382-1586-4668-8c1d-89d4afc46fa2 449 | # ╠═063a220c-58fb-4113-8f14-a2b4fe0c5791 450 | # ╠═0d4dac94-3b71-4cb0-be7d-52fe63878a2f 451 | # ╠═3f457aad-ffe9-4453-b11b-2e74e7bb45a1 452 | # ╠═7d989347-3aa1-4bc7-8202-d2590bfd2a4e 453 | # ╟─0edc1d57-baff-4372-94bb-55cea542ebbc 454 | # ╟─00398409-91c3-4bec-8f80-d53d71c33bdd 455 | # ╠═d1e9080c-e998-43a0-8f57-759c24b3207a 456 | # ╟─a08b40ea-9d80-4552-83bc-50d0c1bdaa13 457 | # ╠═838600d7-1965-445d-ab79-cc81866eca24 458 | # ╟─d9ac05cc-3c54-46fc-bf28-ad38418fe413 459 | # ╟─00000000-0000-0000-0000-000000000001 460 | # ╟─00000000-0000-0000-0000-000000000002 461 | -------------------------------------------------------------------------------- /src/basic/Basic mathematics.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://github.com/JuliaPluto/featured/blob/2a6a9664e5428b37abe4957c1dca0994f4a8b7fd/LICENSES/Unlicense" 6 | #> image = "https://user-images.githubusercontent.com/6933510/174066114-bc76964d-6ed1-491a-baa0-5063e3b08a17.png" 7 | #> order = "2" 8 | #> tags = ["basic", "classic"] 9 | #> license = "Unlicense" 10 | #> description = "Learn mathematics in Julia using pizzas! 🍕" 11 | #> 12 | #> [[frontmatter.author]] 13 | #> name = "Pluto.jl" 14 | #> url = "https://github.com/JuliaPluto" 15 | 16 | using Markdown 17 | using InteractiveUtils 18 | 19 | # This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). 20 | macro bind(def, element) 21 | #! format: off 22 | return quote 23 | local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end 24 | local el = $(esc(element)) 25 | global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) 26 | el 27 | end 28 | #! format: on 29 | end 30 | 31 | # ╔═╡ 14158eb0-d45c-11ea-088f-330e45412320 32 | a = 2 33 | 34 | # ╔═╡ 2ed4bb92-d45c-11ea-0b31-2d8e32ce7b44 35 | b = 6 36 | 37 | # ╔═╡ 03664f5c-d45c-11ea-21b6-91cd647a07aa 38 | md"# Mathematics in Julia 🍕 39 | This is an introduction to programming. Let's get started! 40 | 41 | ## Let's make a calculator! 42 | 43 | First let's do some simple math with setting **a = $a**, **b = $b** and **c = a * b**. What will **c** equal? 44 | 45 | Type in the cells (with the coloured background) below and press **`Shift-Enter`** or the click the right-arrow button (▶️) to the right to execute the cell after changing the values." 46 | 47 | # ╔═╡ e5e0a0da-d45c-11ea-1042-e9b5d0654d4f 48 | md"Fix the value of `c` below to make it `c = a * b`" 49 | 50 | # ╔═╡ 30f0f882-d45c-11ea-2adc-7d84ecf8a7a6 51 | c = 10 52 | 53 | # ╔═╡ 262b312a-d460-11ea-26c5-df30459effc5 54 | people = 10 55 | 56 | # ╔═╡ 2ea7f162-d460-11ea-0e8e-25340e2e64da 57 | avg = 2.5 58 | 59 | # ╔═╡ 3da812c6-d460-11ea-0170-79fbb6a4347c 60 | slices = 8 61 | 62 | # ╔═╡ a38cb92e-d45e-11ea-2959-05be909befb2 63 | md"""### Now you have a calculator! 64 | 65 | You did multiplication above. Here's how you do other mathematical operations: 66 | 67 | Operation | Type This 68 | :------------ | :-------------: 69 | add | + 70 | subtract | - 71 | multiply | * 72 | divide | / 73 | power | ^ 74 | 75 | ### Pizza Slices 76 | 77 | Let's try this out on a problem. Let's say you want to order pizzas for $people people (**people = $people**) and each person wants $avg slices on average (**avg = $avg**). A pizza has $slices slices per pizza (**slices = $slices**). How many pizzas should you order (**pizzas = ?**)? So we have the following 78 | 79 | Meaning | Variable 80 | :------ | :--------: 81 | Number of people | people 82 | Average number of slices each person eats | avg 83 | Number of slices on a piece of pizza | slices 84 | 85 | """ 86 | 87 | # ╔═╡ 4dff4b5e-d461-11ea-29c8-d548fdb5f08b 88 | md"Edit the equation below to calculate the number of pizzas to order using the variables above for **people**, **avg**, and **slices**:" 89 | 90 | # ╔═╡ 444e2fa4-d460-11ea-12aa-57e0576c2d66 91 | pizzas = 1 92 | 93 | # ╔═╡ 3c12f2b4-d471-11ea-2d37-539f061f7cf2 94 | r = 6 95 | 96 | # ╔═╡ d9c31dfa-d470-11ea-23b2-838975b71f7c 97 | md"""## Writing your own math functions 98 | 99 | The area of a pizza is ``A = \pi r^2``. Lets try calculating the area of a pizza that has a radius of $r inches (**r = $r**). Type **pi** to get the value of ``\pi`` and **r^2** to get the radius squared. 100 | """ 101 | 102 | # ╔═╡ 50f0f6d6-d471-11ea-304e-8f72e7ef9d7e 103 | A = r^2 104 | 105 | # ╔═╡ f907e46a-d471-11ea-07e5-f30e2aab3d08 106 | md"""The diameter of a pizza is often stated on a menu so let's define a **formula** to calculate the area of a pizza given the diameter **d**. 107 | 108 | We do this by writing a formula like this: `area(d) = pi * (d/2)^2` 109 | 110 | Let's write that below: 111 | """ 112 | 113 | # ╔═╡ cb36a9ee-d472-11ea-1835-bf7963137e18 114 | area(d) = pi * (d / 2)^2 115 | 116 | # ╔═╡ d9575e9c-d472-11ea-1eda-2d335d039f28 117 | md"""Now we have a function called **area** that we can pass any diameter and it will return the area of a pizza (or circle), let's try that with the pizza from before with `area(2*r)` to get the area of the pizza: 118 | """ 119 | 120 | # ╔═╡ 04b010c0-d473-11ea-1767-136c7e26e122 121 | A2 = area(r) 122 | 123 | # ╔═╡ edb95b14-d473-11ea-3a5a-77382d31f941 124 | md"""## Finding the best pizza deal 125 | 126 | Let's see if a larger pizza is a better value by calculating the price per area. There are 4 sizes: small, medium, large, extra large with the following prices: 127 | 128 | Size | Diameter (inches) | Price ($) 129 | :------- | :---------------: | --------: 130 | small | 9 | 13.10 131 | medium | 13 | 20.95 132 | large | 15 | 24.90 133 | XL | 17 | 30.95 134 | 135 | ### 1. How many small pizzas is the same as one XL pizza? 136 | 137 | Edit the expression below: 138 | """ 139 | 140 | # ╔═╡ 637c26fa-d475-11ea-2c5b-2b0f4775b119 141 | smalls_in_xl = 1 142 | 143 | # ╔═╡ 5b07b8fe-d475-11ea-01aa-6b88d6ed8a05 144 | md"""### 2. Calculate the cost per area of each pizza: 145 | """ 146 | 147 | # ╔═╡ 3823d09e-d474-11ea-194e-59b5805f303b 148 | small = 13.10 / area(9) 149 | 150 | # ╔═╡ 76c11174-d474-11ea-29c5-81856d47cf74 151 | medium = 20.95 / area(13) 152 | 153 | # ╔═╡ 8b12d200-d474-11ea-3035-01eccf39f917 154 | large = 24.90 / area(15) 155 | 156 | # ╔═╡ 962e6b86-d474-11ea-11a6-a1d11e33ae42 157 | xl = 30.95 / area(17) 158 | 159 | # ╔═╡ a42e4eb0-d474-11ea-316a-3d864451bc01 160 | md"Which size of pizza is the best deal? Write your answer below and assign it to the variable **best_value**." 161 | 162 | # ╔═╡ 16ec3f32-d4ff-11ea-20e2-5bc6dd5db083 163 | best_value = small 164 | 165 | # ╔═╡ cb419286-d4ff-11ea-1d7f-af5c8574b775 166 | md"""### 3. Is this a good deal? 167 | 168 | San Marinos has a special **\"Buy two medium pizzas and save \$5\"**. Is this a better deal than buying a extra-large pizza? 169 | 170 | Calculate the total cost of two medium pizzas deal (saving \$5):""" 171 | 172 | # ╔═╡ f147b6cc-d4ff-11ea-05ad-6f5b441e5d1b 173 | two_medium_cost = 20.95 * 1 - 0 174 | 175 | # ╔═╡ 0d76d97c-d500-11ea-2433-e96c6fc43b05 176 | md"Calculate the total area of two medium pizzas:" 177 | 178 | # ╔═╡ 19eb2a82-d500-11ea-3782-596adc689382 179 | two_medium_area = 1 * area(13) 180 | 181 | # ╔═╡ 20a1e9cc-d500-11ea-3d9b-279c71bc20f1 182 | md"Now calculate cost per area by taking the total cost of two medium pizzas and divide by the total area:" 183 | 184 | # ╔═╡ 70e85498-d500-11ea-35af-474574f5c011 185 | two_medium_deal = 1 186 | 187 | # ╔═╡ 57f024ae-d500-11ea-1cc4-ed28348fdf93 188 | md"""Is it a better deal to get two medium pizzas for \$5 off or to just buy an extra-large?""" 189 | 190 | # ╔═╡ 180c8fdc-d503-11ea-04ca-bf2c07fd1c17 191 | md"""### 4. Advanced Problem 192 | 193 | A new worker at a pizza shop was getting paid for cutting pizza into pieces. The pieces of pizza could be any size. Calculate the maximum number of pieces the worker could make with two cuts of the pizza.""" 194 | 195 | # ╔═╡ 6494e270-d503-11ea-38a7-df96e7f0a241 196 | cuts2 = 1 197 | 198 | # ╔═╡ 92b4a012-d503-11ea-15a2-1f3a446d3284 199 | md"Now what about 3 cuts across the pizza? What is the maximum number of pieces that can be made with **3 cuts**?" 200 | 201 | # ╔═╡ a05aae8e-d506-11ea-190f-57e9ce53b8b9 202 | cuts3 = 1 203 | 204 | # ╔═╡ 2eb9a560-d507-11ea-3b8b-9d06678fe131 205 | md"Now, how many pieces can be made with **4 cuts**?" 206 | 207 | # ╔═╡ 5a8ede88-d507-11ea-30d9-c99a67243781 208 | cuts4 = 1 209 | 210 | # ╔═╡ d1e3dec0-d507-11ea-1213-d37a9325ee2f 211 | md"Are you starting to see a pattern? Can you figure out a formula for how many pieces of pizza can be made with \"n\" cuts? Make a table and fill in the number of pieces for a number of cuts and see if you can find the pattern: 212 | 213 | Cuts | Pieces 214 | :--- | ------: 215 | 0 | 1 216 | 1 | 2 217 | 2 | 4 218 | 3 | 219 | 4 | 220 | " 221 | 222 | # ╔═╡ 97bfd13c-dcc2-11ea-0067-ad8c2c6517fc 223 | md"To get an extra hint, figure out how many slices we can get from **5 cuts**:" 224 | 225 | # ╔═╡ bae0cb62-dcc2-11ea-0667-512e1c407d40 226 | cuts5 = 1 227 | 228 | # ╔═╡ e0cb2822-dcc2-11ea-2c85-5748bfe526dc 229 | md"Have you found the pattern? Write down the formula below:" 230 | 231 | # ╔═╡ f5f89724-d507-11ea-0a93-6d904f36bbe4 232 | function pieces(n) 233 | return n 234 | end 235 | 236 | # ╔═╡ 03249876-d508-11ea-16bb-fd5afed37a1f 237 | md"""##### Let's test your formula!""" 238 | 239 | # ╔═╡ bd9f3d24-d509-11ea-165d-3d465a0b4542 240 | md"""Move the slider to change the number of cuts: 241 | 242 | $(@bind n html"")""" 243 | 244 | # ╔═╡ b8644fb0-daa6-11ea-1e94-9bf46e7b0fad 245 | hint(text) = Markdown.MD(Markdown.Admonition("hint", "Hint", [text])); 246 | 247 | # ╔═╡ 8700d986-d475-11ea-0d0e-790448cf92ba 248 | let 249 | ans = (pi * (17 / 2)^2) / (pi * (9 / 2)^2) 250 | if smalls_in_xl == 1 251 | hint(md"""The diameter of the XL pizza is 17 inches while the diameter of the small pizza is 9 inches. Use the **area()** function from before to find the area of each and divide them.""") 252 | elseif smalls_in_xl < ans - 4 * eps(ans) 253 | md"""Keep trying, your answer is too low.""" 254 | elseif smalls_in_xl > ans + 4 * eps(ans) 255 | md"""Keep trying, your answer is too high.""" 256 | else 257 | md"""**Great!** You got it right. Let's move on.""" 258 | end 259 | end 260 | 261 | # ╔═╡ 2814a1d4-dcc0-11ea-3d42-f52765e478fe 262 | hint(md"For each extra cut, start out with the solution for the previous number. When you add one extra cut, how many new slices do you get?") 263 | 264 | # ╔═╡ 48647ab2-daa5-11ea-0494-ef87be7cbf7c 265 | hint(md"A new cut will create the maximum number of _new slices_ if it intersects all previous cuts.") 266 | 267 | # ╔═╡ 8cada086-daa5-11ea-220c-0f660938b604 268 | if cuts5 == 5 + 4 + 3 + 2 + 1 + 1 269 | hint(md"To get the maximum number of pieces with 5 cuts it will be ``5 + 4 + 3 + 2 + 1``, plus 1 extra for the original pizza with 0 cuts. To find the formula of a sequence of numbers group them like so: ``5 + (4 + 1) + (3 + 2) = 3 * 5``.") 270 | else 271 | md"" 272 | end 273 | 274 | # ╔═╡ 4119d19e-dcbc-11ea-3ec8-271e88e1afca 275 | almost(text) = Markdown.MD(Markdown.Admonition("warning", "Almost there!", [text])); 276 | 277 | # ╔═╡ 921bba30-dcbc-11ea-13c3-87554722da8a 278 | keep_working(text=md"The answer is not quite right.") = Markdown.MD(Markdown.Admonition("danger", "Keep working on it!", [text])); 279 | 280 | # ╔═╡ 5a6d1a8e-dcbc-11ea-272a-6f769c8d309c 281 | correct(text=md"Great! You got the right answer! Let's move on to the next section.") = Markdown.MD(Markdown.Admonition("correct", "Got it!", [text])); 282 | 283 | # ╔═╡ 33b1975c-d45c-11ea-035f-ab76e46a31ed 284 | if c == a * b 285 | correct(md"""**Great!** The value of c = $c. So you now have a simple computer! 286 | 287 | Now go back above and change the value of **a = $a** to **a = $(a + 3)** and press **`Shift-Enter`**. 288 | What is the new value of **c**? Notice how all the values get updated in this notebook! 289 | """) 290 | else 291 | keep_working() 292 | end 293 | 294 | # ╔═╡ f26d50da-d46b-11ea-0c2d-77ca13532b3d 295 | if pizzas == people * avg / slices 296 | almost(md"Yes that is right! But we should round $pizzas up to an integer, otherwise the restaurant will be confused. 297 | 298 | Try `ceil(...)`!") 299 | elseif pizzas == ceil(people * avg / slices) 300 | correct(md"Yes that is right, that's a lot of pizza! Excellent, you figured out we need to round up the number of pizzas!") 301 | else 302 | keep_working() 303 | end 304 | 305 | # ╔═╡ 5c4a5f22-d471-11ea-260f-9338d8bfa2d6 306 | if A != pi * r^2 307 | keep_working(md"Let's fix the above cell before we move on! Find the formula to calculate the area using **pi** and **r**.") 308 | else 309 | correct(md"""**Great!** You figured it out. Keep going.""") 310 | end 311 | 312 | # ╔═╡ a07e5c3e-d476-11ea-308c-718f8f128334 313 | if A2 != pi * r^2 314 | hint(md"Keep trying to get the right answer. 315 | **Hint**: you need to multiply the radius by 2 to convert it into the diameter.") 316 | else 317 | correct() 318 | end 319 | 320 | # ╔═╡ 1ba2c208-d4ff-11ea-0a8e-e75bf7e1c3e6 321 | if !isapprox(best_value, xl) 322 | hint(md"No need to copy these digits yourself - what should we assign to **best_value**?") 323 | else 324 | correct() 325 | end 326 | 327 | # ╔═╡ 6ae748b2-d503-11ea-1c51-6b2df24fd212 328 | if cuts2 != 4 329 | hint(md"The cuts must go all the way across the pizza!") 330 | else 331 | correct(md"Awesome!") 332 | end 333 | 334 | # ╔═╡ a679bddc-d506-11ea-143a-6d4dcd70e918 335 | if cuts3 == 6 336 | almost(md"""Close but not quite. Who said that pizza slices need to look like pizza slices?""") 337 | elseif cuts3 == 7 338 | correct(md"You got it right. Now for something harder...") 339 | else 340 | hint(md"Try drawing it out on a piece of paper.") 341 | end 342 | 343 | # ╔═╡ 5df7eefc-d507-11ea-0d1f-45b224a04774 344 | if cuts4 == 11 345 | correct(md"That was a tough question. How did you figure it out? You tried hard.") 346 | elseif cuts4 < 10 347 | hint(md"Draw it out on a piece of paper. You can make more pieces with 4 cuts.") 348 | elseif cuts4 < 11 349 | hint(md"Getting close but you can make more pieces with 4 cuts.") 350 | else 351 | hint(md"That is too high. Only straight lines!") 352 | end 353 | 354 | # ╔═╡ e80986c6-d509-11ea-12e3-f79a54b5ab31 355 | if pieces(n) == n * (n + 1) / 2 + 1 356 | md"""_Testing..._ 357 | 358 | **For $n cuts, you predict $(pieces(n)) pieces.** 359 | 360 | $(correct(md"Well done!"))""" 361 | else 362 | md"""_Testing..._ 363 | 364 | **For $n cuts, you predict $(pieces(n)) pieces.** 365 | 366 | $(keep_working(md"The answer should be $(Int(n*(n+1)/2+1))."))""" 367 | end 368 | 369 | # ╔═╡ 00000000-0000-0000-0000-000000000001 370 | PLUTO_PROJECT_TOML_CONTENTS = """ 371 | [deps] 372 | """ 373 | 374 | # ╔═╡ 00000000-0000-0000-0000-000000000002 375 | PLUTO_MANIFEST_TOML_CONTENTS = """ 376 | # This file is machine-generated - editing it directly is not advised 377 | 378 | julia_version = "1.11.3" 379 | manifest_format = "2.0" 380 | project_hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709" 381 | 382 | [deps] 383 | """ 384 | 385 | # ╔═╡ Cell order: 386 | # ╟─03664f5c-d45c-11ea-21b6-91cd647a07aa 387 | # ╠═14158eb0-d45c-11ea-088f-330e45412320 388 | # ╠═2ed4bb92-d45c-11ea-0b31-2d8e32ce7b44 389 | # ╟─e5e0a0da-d45c-11ea-1042-e9b5d0654d4f 390 | # ╠═30f0f882-d45c-11ea-2adc-7d84ecf8a7a6 391 | # ╟─33b1975c-d45c-11ea-035f-ab76e46a31ed 392 | # ╟─a38cb92e-d45e-11ea-2959-05be909befb2 393 | # ╠═262b312a-d460-11ea-26c5-df30459effc5 394 | # ╠═2ea7f162-d460-11ea-0e8e-25340e2e64da 395 | # ╠═3da812c6-d460-11ea-0170-79fbb6a4347c 396 | # ╟─4dff4b5e-d461-11ea-29c8-d548fdb5f08b 397 | # ╠═444e2fa4-d460-11ea-12aa-57e0576c2d66 398 | # ╟─f26d50da-d46b-11ea-0c2d-77ca13532b3d 399 | # ╟─d9c31dfa-d470-11ea-23b2-838975b71f7c 400 | # ╠═3c12f2b4-d471-11ea-2d37-539f061f7cf2 401 | # ╠═50f0f6d6-d471-11ea-304e-8f72e7ef9d7e 402 | # ╟─5c4a5f22-d471-11ea-260f-9338d8bfa2d6 403 | # ╟─f907e46a-d471-11ea-07e5-f30e2aab3d08 404 | # ╠═cb36a9ee-d472-11ea-1835-bf7963137e18 405 | # ╟─d9575e9c-d472-11ea-1eda-2d335d039f28 406 | # ╠═04b010c0-d473-11ea-1767-136c7e26e122 407 | # ╟─a07e5c3e-d476-11ea-308c-718f8f128334 408 | # ╟─edb95b14-d473-11ea-3a5a-77382d31f941 409 | # ╠═637c26fa-d475-11ea-2c5b-2b0f4775b119 410 | # ╟─8700d986-d475-11ea-0d0e-790448cf92ba 411 | # ╟─5b07b8fe-d475-11ea-01aa-6b88d6ed8a05 412 | # ╠═3823d09e-d474-11ea-194e-59b5805f303b 413 | # ╠═76c11174-d474-11ea-29c5-81856d47cf74 414 | # ╠═8b12d200-d474-11ea-3035-01eccf39f917 415 | # ╠═962e6b86-d474-11ea-11a6-a1d11e33ae42 416 | # ╟─a42e4eb0-d474-11ea-316a-3d864451bc01 417 | # ╠═16ec3f32-d4ff-11ea-20e2-5bc6dd5db083 418 | # ╟─1ba2c208-d4ff-11ea-0a8e-e75bf7e1c3e6 419 | # ╟─cb419286-d4ff-11ea-1d7f-af5c8574b775 420 | # ╠═f147b6cc-d4ff-11ea-05ad-6f5b441e5d1b 421 | # ╟─0d76d97c-d500-11ea-2433-e96c6fc43b05 422 | # ╠═19eb2a82-d500-11ea-3782-596adc689382 423 | # ╟─20a1e9cc-d500-11ea-3d9b-279c71bc20f1 424 | # ╠═70e85498-d500-11ea-35af-474574f5c011 425 | # ╟─57f024ae-d500-11ea-1cc4-ed28348fdf93 426 | # ╟─180c8fdc-d503-11ea-04ca-bf2c07fd1c17 427 | # ╠═6494e270-d503-11ea-38a7-df96e7f0a241 428 | # ╟─6ae748b2-d503-11ea-1c51-6b2df24fd212 429 | # ╟─92b4a012-d503-11ea-15a2-1f3a446d3284 430 | # ╠═a05aae8e-d506-11ea-190f-57e9ce53b8b9 431 | # ╟─a679bddc-d506-11ea-143a-6d4dcd70e918 432 | # ╟─2eb9a560-d507-11ea-3b8b-9d06678fe131 433 | # ╠═5a8ede88-d507-11ea-30d9-c99a67243781 434 | # ╟─5df7eefc-d507-11ea-0d1f-45b224a04774 435 | # ╟─d1e3dec0-d507-11ea-1213-d37a9325ee2f 436 | # ╟─2814a1d4-dcc0-11ea-3d42-f52765e478fe 437 | # ╟─48647ab2-daa5-11ea-0494-ef87be7cbf7c 438 | # ╟─97bfd13c-dcc2-11ea-0067-ad8c2c6517fc 439 | # ╠═bae0cb62-dcc2-11ea-0667-512e1c407d40 440 | # ╟─8cada086-daa5-11ea-220c-0f660938b604 441 | # ╟─e0cb2822-dcc2-11ea-2c85-5748bfe526dc 442 | # ╠═f5f89724-d507-11ea-0a93-6d904f36bbe4 443 | # ╟─03249876-d508-11ea-16bb-fd5afed37a1f 444 | # ╟─bd9f3d24-d509-11ea-165d-3d465a0b4542 445 | # ╟─e80986c6-d509-11ea-12e3-f79a54b5ab31 446 | # ╟─b8644fb0-daa6-11ea-1e94-9bf46e7b0fad 447 | # ╟─4119d19e-dcbc-11ea-3ec8-271e88e1afca 448 | # ╟─921bba30-dcbc-11ea-13c3-87554722da8a 449 | # ╟─5a6d1a8e-dcbc-11ea-272a-6f769c8d309c 450 | # ╟─00000000-0000-0000-0000-000000000001 451 | # ╟─00000000-0000-0000-0000-000000000002 452 | -------------------------------------------------------------------------------- /src/basic/turtles-art.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://github.com/JuliaPluto/featured/blob/2a6a9664e5428b37abe4957c1dca0994f4a8b7fd/LICENSES/Unlicense" 6 | #> image = "https://github.com/JuliaRegistries/General/assets/6933510/9a925232-6a75-47e7-9ab9-f384bc389602" 7 | #> order = "5.1" 8 | #> title = "Turtles – showcase" 9 | #> date = "2024-08-10" 10 | #> tags = ["turtle", "basic"] 11 | #> description = "🐢 A couple of cool artworks made with simple Julia code" 12 | #> license = "Unlicense" 13 | #> 14 | #> [[frontmatter.author]] 15 | #> name = "Pluto.jl" 16 | #> url = "https://github.com/JuliaPluto" 17 | 18 | using Markdown 19 | using InteractiveUtils 20 | 21 | # This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). 22 | macro bind(def, element) 23 | #! format: off 24 | return quote 25 | local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end 26 | local el = $(esc(element)) 27 | global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) 28 | el 29 | end 30 | #! format: on 31 | end 32 | 33 | # ╔═╡ 1ff23021-4eb3-458d-a07e-0c5083eb4c4f 34 | using PlutoTurtles, PlutoUI 35 | 36 | # ╔═╡ 86e25a9c-b877-45cb-8a57-4643dd1fc266 37 | md""" 38 | # Turtle art! 39 | 40 | This notebook uses [PlutoTurtles.jl](https://github.com/JuliaPluto/PlutoTurtles.jl) to recreate some famous works of art! 41 | """ 42 | 43 | # ╔═╡ 0d7fb9e7-3437-4ff9-9de6-1f3f8a93dfff 44 | md"""## "_The Starry Night_" 45 | Vincent van Gogh (1889)""" 46 | 47 | # ╔═╡ abe23881-0354-4068-8115-451f7b3307c7 48 | @bind GO_gogh CounterButton("Another one!") 49 | 50 | # ╔═╡ 75b23160-aada-4e48-8b16-ddd2c6c8df1f 51 | function draw_star(turtle, points, size) 52 | for i in 1:points 53 | right!(turtle, 360 / points) 54 | forward!(turtle, size) 55 | backward!(turtle, size) 56 | end 57 | end 58 | 59 | # ╔═╡ 426a1f52-32dd-4b63-a274-27e1cf139742 60 | md"""## "_Tableau I_" 61 | Piet Mondriaan (1913)""" 62 | 63 | # ╔═╡ f30d72d7-7894-4229-8f25-509195563097 64 | @bind GO_mondriaan CounterButton("Another one!") 65 | 66 | # ╔═╡ ab4d46eb-d441-47c3-b061-2611b2e44009 67 | function draw_mondriaan(rng, turtle, width, height) 68 | #propbability that we make a mondriaan split 69 | p = if width * height < 8 70 | 0 71 | else 72 | ((width * height) / 900) ^ 0.5 73 | end 74 | 75 | if rand(rng) < p 76 | #split into halves 77 | 78 | split = rand(rng, width * 0.1 : width * 0.9) 79 | 80 | #draw split 81 | forward!(turtle, split) 82 | right!(turtle, 90) 83 | color!(turtle, "black") 84 | pendown!(turtle) 85 | forward!(turtle, height) 86 | penup!(turtle) 87 | 88 | #fill in left of split 89 | right!(turtle, 90) 90 | forward!(turtle, split) 91 | right!(turtle, 90) 92 | draw_mondriaan(rng, turtle, height, split) 93 | 94 | #fill in right of split 95 | forward!(turtle, height) 96 | right!(turtle, 90) 97 | forward!(turtle, width) 98 | right!(turtle, 90) 99 | draw_mondriaan(rng, turtle, height, width - split) 100 | 101 | #walk back 102 | right!(turtle, 90) 103 | forward!(turtle, width) 104 | right!(turtle, 180) 105 | 106 | else 107 | #draw a colored square 108 | square_color = rand(rng, ("white", "white", "white", "red", "yellow", "blue")) 109 | color!(turtle, square_color) 110 | for x in (.4:.4:width - .4) ∪ [width - .4] 111 | forward!(turtle, x) 112 | right!(turtle, 90) 113 | forward!(turtle, .2) 114 | pendown!(turtle) 115 | forward!(turtle, height - .4) 116 | penup!(turtle) 117 | right!(turtle, 180) 118 | forward!(turtle, height - .2) 119 | right!(turtle, 90) 120 | backward!(turtle, x) 121 | end 122 | end 123 | end 124 | 125 | # ╔═╡ ff2294a6-2bd0-461c-bc38-02f157d86660 126 | md"""## "_Een Boom_" 127 | Luka van der Plas (2020)""" 128 | 129 | # ╔═╡ b6b1690b-6427-4ff3-9abf-b499f4661c39 130 | @bind fractal_angle Slider(0:90; default=49) 131 | 132 | # ╔═╡ 59963c46-ee42-4989-bff4-90f12606193e 133 | @bind fractal_tilt Slider(0:90; default=36) 134 | 135 | # ╔═╡ 5f6beed8-33ae-463c-9d28-09e3a4235936 136 | @bind fractal_base Slider(0:0.01:2; default=1) 137 | 138 | # ╔═╡ 18a97ce6-ae85-46a2-b294-830473fe80cd 139 | function lindenmayer(turtle, depth, angle, tilt, base) 140 | if depth < 10 141 | old_pos = turtle.pos 142 | old_heading = turtle.heading 143 | 144 | size = base * .5 ^ (depth * 0.5) 145 | 146 | pendown!(turtle) 147 | color!(turtle, "hsl($(depth * 30), 80%, 50%)") 148 | forward!(turtle, size * 8) 149 | right!(turtle, tilt / 2) 150 | lindenmayer(turtle, depth + 1, angle, tilt, base) 151 | left!(turtle, angle) 152 | lindenmayer(turtle, depth + 1, angle, tilt, base) 153 | 154 | 155 | turtle.pos = old_pos 156 | turtle.heading = old_heading 157 | end 158 | end 159 | 160 | # ╔═╡ 83cd894b-2be0-48c7-b5e7-8db7ed96c13f 161 | fractal = turtle_drawing_fast() do t 162 | penup!(t) 163 | backward!(t, 15) 164 | pendown!(t) 165 | lindenmayer(t, 0, fractal_angle, fractal_tilt, fractal_base) 166 | end 167 | 168 | # ╔═╡ e51d4b19-fa30-4643-8d12-407941a4757d 169 | md""" 170 | ## "_Een coole spiraal_" 171 | fonsi (2020) 172 | """ 173 | 174 | # ╔═╡ 6deab6a2-f298-42a8-9c86-db8a2a26ac17 175 | @bind angle Slider(0:90; default=20) 176 | 177 | # ╔═╡ c668c791-9c3b-4eed-babe-9a484a88b68e 178 | turtle_drawing() do t 179 | 180 | for i in 0:.1:10 181 | right!(t, angle) 182 | forward!(t, i) 183 | end 184 | 185 | end 186 | 187 | # ╔═╡ 897cc639-5ab6-48fe-bdba-19aa4e8bad15 188 | import Random 189 | 190 | # ╔═╡ 70402e12-22c2-47fd-99be-aa6cd15ce2c3 191 | starry_night = turtle_drawing_fast(background = "#000088") do t 192 | rng = Random.MersenneTwister(GO_gogh + 7) 193 | 194 | star_count = 100 195 | 196 | color!(t, "yellow") 197 | 198 | for i in 1:star_count 199 | #move 200 | penup!(t) 201 | random_angle = rand(rng) * 360 202 | right!(t, random_angle) 203 | random_distance = rand(rng, 1:8) 204 | forward!(t, random_distance) 205 | 206 | #draw star 207 | pendown!(t) 208 | 209 | draw_star(t, 5, 1) 210 | end 211 | end 212 | 213 | # ╔═╡ d400d8d6-de2c-4886-86b9-ffd9e5f4e073 214 | # turtle_drawing_fast() is the same as turtle_drawing(), but it does not show a little turtle taking the individual steps 215 | 216 | mondriaan = turtle_drawing_fast() do t 217 | rng = Random.MersenneTwister(GO_mondriaan + 7) 218 | size = 30 219 | 220 | #go to top left corner 221 | penup!(t) 222 | forward!(t, size / 2) 223 | left!(t, 90) 224 | forward!(t, size / 2) 225 | right!(t, 180) 226 | 227 | #draw painting 228 | draw_mondriaan(rng, t, size, size) 229 | 230 | #white border around painting 231 | color!(t, "white") 232 | pendown!(t) 233 | for i in 1:4 234 | forward!(t, size) 235 | right!(t, 90) 236 | end 237 | end 238 | 239 | # ╔═╡ 00000000-0000-0000-0000-000000000001 240 | PLUTO_PROJECT_TOML_CONTENTS = """ 241 | [deps] 242 | PlutoTurtles = "67697473-756c-6b61-6172-6b407461726b" 243 | PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" 244 | Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 245 | 246 | [compat] 247 | PlutoTurtles = "~1.0.1" 248 | PlutoUI = "~0.7.62" 249 | """ 250 | 251 | # ╔═╡ 00000000-0000-0000-0000-000000000002 252 | PLUTO_MANIFEST_TOML_CONTENTS = """ 253 | # This file is machine-generated - editing it directly is not advised 254 | 255 | [[AbstractPlutoDingetjes]] 256 | deps = ["Pkg"] 257 | git-tree-sha1 = "6e1d2a35f2f90a4bc7c2ed98079b2ba09c35b83a" 258 | uuid = "6e696c72-6542-2067-7265-42206c756150" 259 | version = "1.3.2" 260 | 261 | [[ArgTools]] 262 | uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" 263 | version = "1.1.2" 264 | 265 | [[Artifacts]] 266 | uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" 267 | version = "1.11.0" 268 | 269 | [[Base64]] 270 | uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" 271 | version = "1.11.0" 272 | 273 | [[ColorTypes]] 274 | deps = ["FixedPointNumbers", "Random"] 275 | git-tree-sha1 = "b10d0b65641d57b8b4d5e234446582de5047050d" 276 | uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" 277 | version = "0.11.5" 278 | 279 | [[Compat]] 280 | deps = ["TOML", "UUIDs"] 281 | git-tree-sha1 = "8ae8d32e09f0dcf42a36b90d4e17f5dd2e4c4215" 282 | uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" 283 | version = "4.16.0" 284 | weakdeps = ["Dates", "LinearAlgebra"] 285 | 286 | [Compat.extensions] 287 | CompatLinearAlgebraExt = "LinearAlgebra" 288 | 289 | [[CompilerSupportLibraries_jll]] 290 | deps = ["Artifacts", "Libdl"] 291 | uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" 292 | version = "1.1.1+0" 293 | 294 | [[Dates]] 295 | deps = ["Printf"] 296 | uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" 297 | version = "1.11.0" 298 | 299 | [[Downloads]] 300 | deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] 301 | uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" 302 | version = "1.6.0" 303 | 304 | [[FileWatching]] 305 | uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" 306 | version = "1.11.0" 307 | 308 | [[FixedPointNumbers]] 309 | deps = ["Statistics"] 310 | git-tree-sha1 = "05882d6995ae5c12bb5f36dd2ed3f61c98cbb172" 311 | uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" 312 | version = "0.8.5" 313 | 314 | [[Hyperscript]] 315 | deps = ["Test"] 316 | git-tree-sha1 = "179267cfa5e712760cd43dcae385d7ea90cc25a4" 317 | uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91" 318 | version = "0.0.5" 319 | 320 | [[HypertextLiteral]] 321 | deps = ["Tricks"] 322 | git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653" 323 | uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" 324 | version = "0.9.5" 325 | 326 | [[IOCapture]] 327 | deps = ["Logging", "Random"] 328 | git-tree-sha1 = "b6d6bfdd7ce25b0f9b2f6b3dd56b2673a66c8770" 329 | uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" 330 | version = "0.2.5" 331 | 332 | [[InteractiveUtils]] 333 | deps = ["Markdown"] 334 | uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" 335 | version = "1.11.0" 336 | 337 | [[JSON]] 338 | deps = ["Dates", "Mmap", "Parsers", "Unicode"] 339 | git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" 340 | uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" 341 | version = "0.21.4" 342 | 343 | [[LibCURL]] 344 | deps = ["LibCURL_jll", "MozillaCACerts_jll"] 345 | uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" 346 | version = "0.6.4" 347 | 348 | [[LibCURL_jll]] 349 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] 350 | uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" 351 | version = "8.6.0+0" 352 | 353 | [[LibGit2]] 354 | deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] 355 | uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" 356 | version = "1.11.0" 357 | 358 | [[LibGit2_jll]] 359 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] 360 | uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" 361 | version = "1.7.2+0" 362 | 363 | [[LibSSH2_jll]] 364 | deps = ["Artifacts", "Libdl", "MbedTLS_jll"] 365 | uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" 366 | version = "1.11.0+1" 367 | 368 | [[Libdl]] 369 | uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" 370 | version = "1.11.0" 371 | 372 | [[LinearAlgebra]] 373 | deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] 374 | uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 375 | version = "1.11.0" 376 | 377 | [[Logging]] 378 | uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" 379 | version = "1.11.0" 380 | 381 | [[MIMEs]] 382 | git-tree-sha1 = "c64d943587f7187e751162b3b84445bbbd79f691" 383 | uuid = "6c6e2e6c-3030-632d-7369-2d6c69616d65" 384 | version = "1.1.0" 385 | 386 | [[Markdown]] 387 | deps = ["Base64"] 388 | uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" 389 | version = "1.11.0" 390 | 391 | [[MbedTLS_jll]] 392 | deps = ["Artifacts", "Libdl"] 393 | uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" 394 | version = "2.28.6+0" 395 | 396 | [[Mmap]] 397 | uuid = "a63ad114-7e13-5084-954f-fe012c677804" 398 | version = "1.11.0" 399 | 400 | [[MozillaCACerts_jll]] 401 | uuid = "14a3606d-f60d-562e-9121-12d972cd8159" 402 | version = "2023.12.12" 403 | 404 | [[NetworkOptions]] 405 | uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" 406 | version = "1.2.0" 407 | 408 | [[OpenBLAS_jll]] 409 | deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] 410 | uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" 411 | version = "0.3.27+1" 412 | 413 | [[Parsers]] 414 | deps = ["Dates", "PrecompileTools", "UUIDs"] 415 | git-tree-sha1 = "7d2f8f21da5db6a806faf7b9b292296da42b2810" 416 | uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" 417 | version = "2.8.3" 418 | 419 | [[Pkg]] 420 | deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] 421 | uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" 422 | version = "1.11.0" 423 | 424 | [Pkg.extensions] 425 | REPLExt = "REPL" 426 | 427 | [Pkg.weakdeps] 428 | REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" 429 | 430 | [[PlutoTurtles]] 431 | deps = ["AbstractPlutoDingetjes", "Compat", "HypertextLiteral", "InteractiveUtils", "Markdown", "PlutoUI"] 432 | git-tree-sha1 = "467866275ad02b4abf63c80bad78ad4f92744473" 433 | uuid = "67697473-756c-6b61-6172-6b407461726b" 434 | version = "1.0.1" 435 | 436 | [[PlutoUI]] 437 | deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "FixedPointNumbers", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "MIMEs", "Markdown", "Random", "Reexport", "URIs", "UUIDs"] 438 | git-tree-sha1 = "d3de2694b52a01ce61a036f18ea9c0f61c4a9230" 439 | uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8" 440 | version = "0.7.62" 441 | 442 | [[PrecompileTools]] 443 | deps = ["Preferences"] 444 | git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" 445 | uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" 446 | version = "1.2.1" 447 | 448 | [[Preferences]] 449 | deps = ["TOML"] 450 | git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" 451 | uuid = "21216c6a-2e73-6563-6e65-726566657250" 452 | version = "1.4.3" 453 | 454 | [[Printf]] 455 | deps = ["Unicode"] 456 | uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" 457 | version = "1.11.0" 458 | 459 | [[Random]] 460 | deps = ["SHA"] 461 | uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 462 | version = "1.11.0" 463 | 464 | [[Reexport]] 465 | git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" 466 | uuid = "189a3867-3050-52da-a836-e630ba90ab69" 467 | version = "1.2.2" 468 | 469 | [[SHA]] 470 | uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" 471 | version = "0.7.0" 472 | 473 | [[Serialization]] 474 | uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" 475 | version = "1.11.0" 476 | 477 | [[Statistics]] 478 | deps = ["LinearAlgebra"] 479 | git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0" 480 | uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" 481 | version = "1.11.1" 482 | 483 | [Statistics.extensions] 484 | SparseArraysExt = ["SparseArrays"] 485 | 486 | [Statistics.weakdeps] 487 | SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" 488 | 489 | [[TOML]] 490 | deps = ["Dates"] 491 | uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" 492 | version = "1.0.3" 493 | 494 | [[Tar]] 495 | deps = ["ArgTools", "SHA"] 496 | uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" 497 | version = "1.10.0" 498 | 499 | [[Test]] 500 | deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] 501 | uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" 502 | version = "1.11.0" 503 | 504 | [[Tricks]] 505 | git-tree-sha1 = "6cae795a5a9313bbb4f60683f7263318fc7d1505" 506 | uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" 507 | version = "0.1.10" 508 | 509 | [[URIs]] 510 | git-tree-sha1 = "cbbebadbcc76c5ca1cc4b4f3b0614b3e603b5000" 511 | uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" 512 | version = "1.5.2" 513 | 514 | [[UUIDs]] 515 | deps = ["Random", "SHA"] 516 | uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" 517 | version = "1.11.0" 518 | 519 | [[Unicode]] 520 | uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" 521 | version = "1.11.0" 522 | 523 | [[Zlib_jll]] 524 | deps = ["Libdl"] 525 | uuid = "83775a58-1f1d-513f-b197-d71354ab007a" 526 | version = "1.2.13+1" 527 | 528 | [[libblastrampoline_jll]] 529 | deps = ["Artifacts", "Libdl"] 530 | uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" 531 | version = "5.11.0+0" 532 | 533 | [[nghttp2_jll]] 534 | deps = ["Artifacts", "Libdl"] 535 | uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" 536 | version = "1.59.0+0" 537 | 538 | [[p7zip_jll]] 539 | deps = ["Artifacts", "Libdl"] 540 | uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" 541 | version = "17.4.0+2" 542 | """ 543 | 544 | # ╔═╡ Cell order: 545 | # ╟─86e25a9c-b877-45cb-8a57-4643dd1fc266 546 | # ╠═1ff23021-4eb3-458d-a07e-0c5083eb4c4f 547 | # ╟─0d7fb9e7-3437-4ff9-9de6-1f3f8a93dfff 548 | # ╟─abe23881-0354-4068-8115-451f7b3307c7 549 | # ╟─70402e12-22c2-47fd-99be-aa6cd15ce2c3 550 | # ╠═75b23160-aada-4e48-8b16-ddd2c6c8df1f 551 | # ╟─426a1f52-32dd-4b63-a274-27e1cf139742 552 | # ╟─f30d72d7-7894-4229-8f25-509195563097 553 | # ╟─d400d8d6-de2c-4886-86b9-ffd9e5f4e073 554 | # ╟─ab4d46eb-d441-47c3-b061-2611b2e44009 555 | # ╟─ff2294a6-2bd0-461c-bc38-02f157d86660 556 | # ╟─b6b1690b-6427-4ff3-9abf-b499f4661c39 557 | # ╟─59963c46-ee42-4989-bff4-90f12606193e 558 | # ╟─5f6beed8-33ae-463c-9d28-09e3a4235936 559 | # ╟─83cd894b-2be0-48c7-b5e7-8db7ed96c13f 560 | # ╟─18a97ce6-ae85-46a2-b294-830473fe80cd 561 | # ╟─e51d4b19-fa30-4643-8d12-407941a4757d 562 | # ╠═6deab6a2-f298-42a8-9c86-db8a2a26ac17 563 | # ╠═c668c791-9c3b-4eed-babe-9a484a88b68e 564 | # ╠═897cc639-5ab6-48fe-bdba-19aa4e8bad15 565 | # ╟─00000000-0000-0000-0000-000000000001 566 | # ╟─00000000-0000-0000-0000-000000000002 567 | -------------------------------------------------------------------------------- /src/puzzles-games/Traveling Salesman Game.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://opensource.org/license/unlicense/" 6 | #> image = "https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Travelling_salesman_problem_solved_with_simulated_annealing.gif/640px-Travelling_salesman_problem_solved_with_simulated_annealing.gif" 7 | #> title = "Traveling Salesman Game" 8 | #> tags = ["optimization", "puzzle", "traveling-salesman"] 9 | #> license = "Unlicense" 10 | #> description = "A fun game to learn about the traveling salesman problem and the simulated annealing algorithm." 11 | #> date = "2024-02-16" 12 | #> 13 | #> [[frontmatter.author]] 14 | #> name = "Matt Helm" 15 | #> url = "https://github.com/mthelm85" 16 | 17 | using Markdown 18 | using InteractiveUtils 19 | 20 | # ╔═╡ 5bf31410-c914-11ee-33f0-c5c134d6b4d8 21 | begin 22 | using Distances 23 | using HypertextLiteral 24 | using Random 25 | using Statistics 26 | end 27 | 28 | # ╔═╡ 2ee01ff1-a85f-4ff9-8d25-6af053b2d8aa 29 | md""" 30 | ## The Traveling Salesman Game 31 | 32 | The Traveling Salesman Problem (TSP) is a classic optimization problem in the fields of computer science and operations research. It involves finding the shortest possible route that visits a set of given cities once, and then returns to the original city. The challenge is to determine the optimal ordering of the cities to minimize the total distance traveled by the salesman. 33 | 34 | In this notebook, you get a chance to try to solve the problem while competing against the computer, which solves it using an algorithm known as *Simulated Annealing*, an optimization algorithm inspired by the annealing process in metallurgy. It is used to solve combinatorial optimization problems like the TSP. 35 | 36 | #### How to Play 37 | 38 | In the cell below, set `N` to the number of cities (or houses in our case) that you would like to start with. These will be generated randomly. Then, set `your_solution` to the path that you believe is the shortest. There is no need to add the starting point to the end of the vector; there is code below that handles that for you. Once you have entered your solution, push the `Go!` button and see if you beat the computer! 39 | 40 | To play another round, or to generate new points, re-run the cell that defines `N`. 41 | """ 42 | 43 | # ╔═╡ 243063ab-0556-4fcb-950a-f7533a2f88fa 44 | N = 5 45 | 46 | # ╔═╡ 069a3cdc-6f8e-4470-a6a8-8312eb6b5df5 47 | your_solution = [1,2,3,4,5] 48 | 49 | # ╔═╡ d25e7bed-3aae-43a1-aa5c-ef44cca55242 50 | begin 51 | truck_url = "https://raw.githubusercontent.com/mthelm85/travelling-salesman-game/main/assets/car2.png" 52 | truck2_url = "https://raw.githubusercontent.com/mthelm85/travelling-salesman-game/main/assets/car5.png" 53 | house_url = "https://raw.githubusercontent.com/mthelm85/travelling-salesman-game/main/assets/house1.png" 54 | map_url = "https://raw.githubusercontent.com/mthelm85/travelling-salesman-game/main/assets/grass.png" 55 | end; 56 | 57 | # ╔═╡ d9ca9f51-d5dd-4321-bae8-fec16a53d250 58 | begin 59 | struct Bounds 60 | x::Int 61 | y::Int 62 | width::Int 63 | height::Int 64 | end 65 | 66 | struct Point 67 | x::Int 68 | y::Int 69 | end 70 | end 71 | 72 | # ╔═╡ c5a0d444-770d-4dc8-8267-963d9f2be545 73 | function random_point(bounds, points) 74 | x = rand(bounds.x:bounds.x + bounds.width - 1) 75 | y = rand(bounds.y:bounds.y + bounds.height - 1) 76 | 77 | # make sure points aren't too close together 78 | threshold = 20 79 | 80 | for point in points 81 | if abs(point.x - x) < threshold || abs(point.y - y) < threshold 82 | return random_point(bounds, points) 83 | end 84 | end 85 | 86 | return Point(x, y) 87 | end; 88 | 89 | # ╔═╡ 739b8137-f6b6-4516-b28d-acdb79828be6 90 | function create_points(b, N) 91 | points = [] 92 | for i in 1:N 93 | push!(points, random_point(b, points)) 94 | end 95 | return points 96 | end; 97 | 98 | # ╔═╡ fdfdbb5c-2204-434c-8249-bc9ad3e72531 99 | begin 100 | get_points_xs(points) = [point.x for point in points] 101 | get_points_ys(points) = [point.y for point in points] 102 | end; 103 | 104 | # ╔═╡ 7c0f26a0-a478-4887-91c8-e5a747b97c19 105 | function total_distance(points, tour) 106 | total_distance = 0.0 107 | n = length(points) 108 | 109 | for i in 1:n-1 110 | p1 = points[tour[i]] 111 | p2 = points[tour[i+1]] 112 | total_distance += evaluate(Euclidean(), [p1.x, p1.y], [p2.x, p2.y]) 113 | end 114 | 115 | p_last = points[tour[end]] 116 | p_first = points[tour[1]] 117 | # Return to the starting point 118 | total_distance += evaluate(Euclidean(), [p_last.x, p_last.y], [p_first.x, p_first.y]) 119 | return total_distance 120 | end; 121 | 122 | # ╔═╡ 39556336-9d1c-417a-b3d7-4e424710902d 123 | function simulated_annealing_tsp(points, max_iter, initial_temperature, cooling_rate) 124 | n = length(points) 125 | current_tour = randperm(n) # Initialize with a random tour 126 | best_tour = copy(current_tour) # Keep track of the best tour found 127 | current_distance = total_distance(points, current_tour) 128 | best_distance = current_distance 129 | temperature = initial_temperature 130 | 131 | for iter in 1:max_iter 132 | next_tour = copy(current_tour) # Make a copy of the current tour to modify 133 | i, j = rand(1:n, 2) # Select two random indices 134 | next_tour[i], next_tour[j] = next_tour[j], next_tour[i] # Swap the cities at these indices 135 | next_distance = total_distance(points, next_tour) 136 | delta = next_distance - current_distance 137 | 138 | # If the new tour is shorter, or if it is longer but accepted by the annealing probability 139 | if delta < 0 || exp(-delta / temperature) > rand() 140 | current_tour = copy(next_tour) 141 | current_distance = next_distance 142 | # If the new tour is the best found so far, update the best tour and distance 143 | if current_distance < best_distance 144 | best_tour = copy(current_tour) 145 | best_distance = current_distance 146 | end 147 | end 148 | 149 | temperature *= cooling_rate # Cool down the temperature 150 | end 151 | 152 | return best_tour 153 | end; 154 | 155 | # ╔═╡ bb9d1888-9214-43d2-b002-b31ded8715a9 156 | begin 157 | b = Bounds(100, 100, 450, 280) 158 | points = create_points(b, N) 159 | end; 160 | 161 | # ╔═╡ 624c3dc0-2186-4185-9fba-87e522d4a163 162 | begin 163 | points_xs = get_points_xs(points) 164 | points_ys = get_points_ys(points) 165 | distances = pairwise(Euclidean(), [points_xs points_ys], dims=1) 166 | max_iter = 1000 167 | initial_temperature = mean(distances) + 3 * std(distances) 168 | cooling_rate = 0.99 169 | solution_player = vcat(your_solution, your_solution[1]) 170 | player_xs = get_points_xs(points[solution_player]) 171 | player_ys = get_points_ys(points[solution_player]) 172 | solution_computer = simulated_annealing_tsp(points, max_iter, initial_temperature, cooling_rate) 173 | push!(solution_computer, solution_computer[1]) # return to start 174 | computer_xs = get_points_xs(points[solution_computer]) 175 | computer_ys = get_points_ys(points[solution_computer]) 176 | player_distance = total_distance([Point(z[1], z[2]) for z in zip(player_xs, player_ys)], 1:size(player_xs, 1)) 177 | computer_distance = total_distance([Point(z[1], z[2]) for z in zip(computer_xs, computer_ys)], 1:size(computer_xs, 1)) 178 | end; 179 | 180 | # ╔═╡ f3bf1b25-cb37-4594-b92b-fcd3f44429e9 181 | if length(your_solution) == N 182 | @htl(""" 183 | 184 |
185 | 186 | 359 | """) 360 | else 361 | @htl(""" 362 |
Make sure  
length(your_solution) == length(N)
363 | """) 364 | end 365 | 366 | # ╔═╡ 00000000-0000-0000-0000-000000000001 367 | PLUTO_PROJECT_TOML_CONTENTS = """ 368 | [deps] 369 | Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" 370 | HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" 371 | Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 372 | Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" 373 | 374 | [compat] 375 | Distances = "~0.10.12" 376 | HypertextLiteral = "~0.9.5" 377 | """ 378 | 379 | # ╔═╡ 00000000-0000-0000-0000-000000000002 380 | PLUTO_MANIFEST_TOML_CONTENTS = """ 381 | # This file is machine-generated - editing it directly is not advised 382 | 383 | julia_version = "1.11.3" 384 | manifest_format = "2.0" 385 | project_hash = "18c97f20a700ea1470257177064fa52d2dc1c969" 386 | 387 | [[deps.Artifacts]] 388 | uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" 389 | version = "1.11.0" 390 | 391 | [[deps.CompilerSupportLibraries_jll]] 392 | deps = ["Artifacts", "Libdl"] 393 | uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" 394 | version = "1.1.1+0" 395 | 396 | [[deps.Distances]] 397 | deps = ["LinearAlgebra", "Statistics", "StatsAPI"] 398 | git-tree-sha1 = "c7e3a542b999843086e2f29dac96a618c105be1d" 399 | uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" 400 | version = "0.10.12" 401 | 402 | [deps.Distances.extensions] 403 | DistancesChainRulesCoreExt = "ChainRulesCore" 404 | DistancesSparseArraysExt = "SparseArrays" 405 | 406 | [deps.Distances.weakdeps] 407 | ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" 408 | SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" 409 | 410 | [[deps.HypertextLiteral]] 411 | deps = ["Tricks"] 412 | git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653" 413 | uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" 414 | version = "0.9.5" 415 | 416 | [[deps.Libdl]] 417 | uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" 418 | version = "1.11.0" 419 | 420 | [[deps.LinearAlgebra]] 421 | deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] 422 | uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 423 | version = "1.11.0" 424 | 425 | [[deps.OpenBLAS_jll]] 426 | deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] 427 | uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" 428 | version = "0.3.27+1" 429 | 430 | [[deps.Random]] 431 | deps = ["SHA"] 432 | uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 433 | version = "1.11.0" 434 | 435 | [[deps.SHA]] 436 | uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" 437 | version = "0.7.0" 438 | 439 | [[deps.Statistics]] 440 | deps = ["LinearAlgebra"] 441 | git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0" 442 | uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" 443 | version = "1.11.1" 444 | 445 | [deps.Statistics.extensions] 446 | SparseArraysExt = ["SparseArrays"] 447 | 448 | [deps.Statistics.weakdeps] 449 | SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" 450 | 451 | [[deps.StatsAPI]] 452 | deps = ["LinearAlgebra"] 453 | git-tree-sha1 = "1ff449ad350c9c4cbc756624d6f8a8c3ef56d3ed" 454 | uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" 455 | version = "1.7.0" 456 | 457 | [[deps.Tricks]] 458 | git-tree-sha1 = "6cae795a5a9313bbb4f60683f7263318fc7d1505" 459 | uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" 460 | version = "0.1.10" 461 | 462 | [[deps.libblastrampoline_jll]] 463 | deps = ["Artifacts", "Libdl"] 464 | uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" 465 | version = "5.11.0+0" 466 | """ 467 | 468 | # ╔═╡ Cell order: 469 | # ╟─2ee01ff1-a85f-4ff9-8d25-6af053b2d8aa 470 | # ╠═243063ab-0556-4fcb-950a-f7533a2f88fa 471 | # ╠═069a3cdc-6f8e-4470-a6a8-8312eb6b5df5 472 | # ╟─f3bf1b25-cb37-4594-b92b-fcd3f44429e9 473 | # ╠═5bf31410-c914-11ee-33f0-c5c134d6b4d8 474 | # ╠═d25e7bed-3aae-43a1-aa5c-ef44cca55242 475 | # ╠═d9ca9f51-d5dd-4321-bae8-fec16a53d250 476 | # ╠═c5a0d444-770d-4dc8-8267-963d9f2be545 477 | # ╠═739b8137-f6b6-4516-b28d-acdb79828be6 478 | # ╠═fdfdbb5c-2204-434c-8249-bc9ad3e72531 479 | # ╠═7c0f26a0-a478-4887-91c8-e5a747b97c19 480 | # ╠═39556336-9d1c-417a-b3d7-4e424710902d 481 | # ╠═bb9d1888-9214-43d2-b002-b31ded8715a9 482 | # ╠═624c3dc0-2186-4185-9fba-87e522d4a163 483 | # ╟─00000000-0000-0000-0000-000000000001 484 | # ╟─00000000-0000-0000-0000-000000000002 485 | -------------------------------------------------------------------------------- /src/web/Interactivity with HTML.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://github.com/JuliaPluto/featured/blob/2a6a9664e5428b37abe4957c1dca0994f4a8b7fd/LICENSES/Unlicense" 6 | #> image = "https://user-images.githubusercontent.com/6933510/174067982-904951c4-4bba-42c7-a340-102ceb7e8e10.png" 7 | #> order = "1" 8 | #> title = "Interactivity with HTML" 9 | #> tags = ["interactivity", "classic", "web"] 10 | #> license = "Unlicense" 11 | #> description = "Write your own interactive controls with HTML!" 12 | #> 13 | #> [[frontmatter.author]] 14 | #> name = "Pluto.jl" 15 | #> url = "https://github.com/JuliaPluto" 16 | 17 | using Markdown 18 | using InteractiveUtils 19 | 20 | # This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). 21 | macro bind(def, element) 22 | #! format: off 23 | return quote 24 | local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end 25 | local el = $(esc(element)) 26 | global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) 27 | el 28 | end 29 | #! format: on 30 | end 31 | 32 | # ╔═╡ 73c8532e-09a6-429b-b8f6-530c00d92428 33 | md""" 34 | # Interactivity with HTML 35 | 36 | Pluto notebooks can use the `@bind` macro for interactive inputs. Neat! 37 | 38 | If you're completely new to coding anything interactive in a web browser, the easiest way to get started is with the `PlutoUI` package in Julia. (Check out the [PlutoUI featured notebook](https://featured.plutojl.org/basic/plutoui.jl) if you'd like to learn more about that!) 39 | 40 | If you have some experience with HTML, or if you would like to learn how to make your own interactive elements, this notebook is for you! We'll cover the basics of using `@bind` with HTML elements. Let's get started! 41 | """ 42 | 43 | # ╔═╡ db24490e-7eac-11ea-094e-9d3fc8f22784 44 | md""" 45 | ## Bound variables 46 | 47 | A basic interactive cell looks like this: we use the `@bind` macro, define a Julia variable, and add a bit of HTML code that creates an `` element. The HTML element will be rendered as the cell's output. 48 | """ 49 | 50 | # ╔═╡ bd24d02c-7eac-11ea-14ab-95021678e71e 51 | @bind x html"" 52 | 53 | # ╔═╡ cf72c8a2-7ead-11ea-32b7-d31d5b2dacc2 54 | md""" 55 | That's all you need! Pluto will synchronise the value of `x` with the latest value of the HTML input. Try moving the slider! 👆 56 | """ 57 | 58 | # ╔═╡ cb1fd532-7eac-11ea-307c-ab16b1977819 59 | x 60 | 61 | # ╔═╡ 0a7018ca-2afe-42b1-850f-a649e570709f 62 | md""" 63 | A neat aspect of this `@bind` macro is that on the Julia side, `x` is just a normal integer: 64 | """ 65 | 66 | # ╔═╡ cb65a4ee-02e5-4779-8728-b994d8af645d 67 | typeof(x) 68 | 69 | # ╔═╡ 816ea402-7eae-11ea-2134-fb595cca3068 70 | md""" 71 | Not an observable, callback, or something else that you need to wrap your head around. You can use `x` like you would any other number, and Pluto's reactivity means anything depending on `x` will be updated with it. 🚀 72 | """ 73 | 74 | # ╔═╡ 1ebba747-47f8-4ecd-809d-359e6d803ddc 75 | y = x^2 76 | 77 | # ╔═╡ 5301eb68-7f14-11ea-3ff6-1f075bf73955 78 | md""" 79 | ## Input types 80 | 81 | You can use binds with anything that fires an [`input` event](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event). For example: 82 | """ 83 | 84 | # ╔═╡ 4a235d55-a80f-43c7-8f13-759976d88656 85 | @bind a html"" 86 | 87 | # ╔═╡ 33b5374c-91d1-4122-82c5-f793d063ffdc 88 | @bind b html"" 89 | 90 | # ╔═╡ d38d06f2-90ce-4e5a-9218-f5a52812e4a2 91 | @bind c html"" 92 | 93 | # ╔═╡ 9985a640-c1d3-48dc-b00b-d7500085a37b 94 | @bind d html""" 95 | 99 | """ 100 | 101 | # ╔═╡ b6501bfb-5e1d-40b9-bd16-d38085d2611d 102 | @bind e html"" 103 | 104 | # ╔═╡ f595bdb6-bd15-4c62-9de6-49f14c7d365a 105 | @bind f html"" 106 | 107 | # ╔═╡ ede8009e-7f15-11ea-192a-a5c6135a9dcf 108 | (a, b, c, d, e, f) 109 | 110 | # ╔═╡ c1b9fbbb-3629-4abf-b11a-b7345b01d403 111 | md""" 112 | ## Scripting inputs with Javascript 113 | 114 | You can also use Javascript to write more complicated inputs. 115 | 116 | To get started with this, add a ` 129 |
130 | """ 131 | 132 | # ╔═╡ de1b9643-66fa-4918-9a93-0f340c8548ba 133 | md""" 134 | Now we can use the script to handle whatever interaction we want. For a simple element, let's add a button and count the number of clicks. 135 | """ 136 | 137 | # ╔═╡ f1f53700-099b-4653-93f1-6b39acdc4c58 138 | html""" 139 |
140 | 141 | 142 | 151 |
152 | """ 153 | 154 | # ╔═╡ cf9d49cc-fc70-480c-9f6b-850b0ba4c01f 155 | md""" 156 | The script is now keeping track of clicks, but it's not sending that value anywhere. 157 | 158 | We need to: 159 | 160 | - Update the parent's element `value` property (this is what Pluto will be reading). 161 | - Dispatch an `"input"` event to trigger change detection. 162 | """ 163 | 164 | # ╔═╡ beb9a2bd-cbf5-4679-8403-fc249191f65e 165 | html""" 166 |
167 | 168 | 169 | 187 |
188 | """ 189 | 190 | # ╔═╡ 6b9a590b-ce24-4a9a-b5b4-5b353e6ccecf 191 | md""" 192 | Okay, now we can use this HTML snippet with a `@bind` macro and see the result! 193 | """ 194 | 195 | # ╔═╡ e3eb31ae-c512-426f-915c-01144edbc90d 196 | @bind counter html""" 197 |
198 | 199 | 200 | 218 |
219 | """ 220 | 221 | # ╔═╡ 5bd8b261-a89d-46a3-bb59-c95a1801c881 222 | counter 223 | 224 | # ╔═╡ 7b11caf2-1fc1-4e34-8b97-eab86e3557db 225 | md""" 226 | !!! tip 227 | 228 | In this example, we immediately call `update()` and trigger an input event with the initial value. If we didn't do that, the value of `counter` would be `nothing` until the first interaction. Whether that's appropriate, depends on the interaction you want. In this case, it made sense that the counter should start at 0! 229 | """ 230 | 231 | # ╔═╡ c50a5e52-7c95-445c-86ee-c60104a39dbd 232 | md""" 233 | ## Using Julia values in HTML 234 | 235 | We've seen how you can pass on values from an interactive HTML element on to Julia, but for proper interaction, we also want to do it the other way around! 236 | 237 | The most basic way to do this is string interpolation. In this example, you can change the value of `limit` in the code to affect the maximum value of the slider. Try it out! 238 | """ 239 | 240 | # ╔═╡ 2714a923-2be5-4cf9-97dd-75347968dfee 241 | limit = 5 242 | 243 | # ╔═╡ 1a338f77-d8f3-4569-a2d5-c174368a4761 244 | @bind limited HTML(""" 245 | 246 | """) 247 | 248 | # ╔═╡ f39435d3-ed67-45f1-ae56-49cf5ec69d6e 249 | limited 250 | 251 | # ╔═╡ e2854aa0-e3c5-423d-80d9-fc875c5dd54d 252 | md""" 253 | Keep in mind that changing the value of `limit` will re-evaluate the slider cell, so it will reset the value. 254 | """ 255 | 256 | # ╔═╡ 2cefd0de-db13-49c1-abeb-097792ef46f6 257 | md""" 258 | For something even fancier, you can also interpolate value in Javascript. For example, here I have adapted my counter so it won't count past `limit`: 259 | """ 260 | 261 | # ╔═╡ f558f689-bd7a-4c65-8b3d-b3681a4ed013 262 | @bind limited_counter HTML(""" 263 |
264 | 265 | 266 | 288 |
289 | """) 290 | 291 | # ╔═╡ 901c2b84-14b8-4deb-89d6-705a4972582c 292 | limited_counter 293 | 294 | # ╔═╡ d5b3adc5-2c99-4901-adf5-8d8579a32b51 295 | md""" 296 | !!! tip 297 | 298 | Interpolating values in Javascript is neat, but remember that we are just taking the string representation of the variable and pasting it in the javascript code. For some complex data types like dates, you will need to do a bit of conversion to turn them into proper javascript expressions. 299 | """ 300 | 301 | # ╔═╡ 788c0b9b-238f-4402-b24f-52648103512e 302 | md""" 303 | If you're looking for something more sophisticated than simple string interpolation, check out the [HyperTextLiteral package](https://juliapluto.github.io/HypertextLiteral.jl/stable/)! 304 | """ 305 | 306 | # ╔═╡ bb4b557b-e4fc-45f3-9d1f-060198167bfa 307 | md""" 308 | ## Reusing elements 309 | 310 | Once you've written some neat interactive element, you may want to use it a few times in notebook. The easiest way is to put the HTML literal in a variable. 311 | """ 312 | 313 | # ╔═╡ 2d8661f1-6f78-4161-a306-982e3ddf3646 314 | myslider = html""""""; 315 | 316 | # ╔═╡ c5a5e243-39d6-43d9-8de7-887661ba99cd 317 | @bind x1 myslider 318 | 319 | # ╔═╡ 3b6dc6d5-ce96-40f6-97f7-511ea6d49122 320 | @bind x2 myslider 321 | 322 | # ╔═╡ 3297233b-9567-4d5e-8138-93ebe20fed48 323 | x1, x2 324 | 325 | # ╔═╡ 82c7b1ea-08c0-495f-baba-37e5497abde2 326 | md""" 327 | It's as simple as that! 328 | """ 329 | 330 | # ╔═╡ 863c5996-9892-4bfc-96ba-225fa4a2266c 331 | md""" 332 | !!! tip 333 | 334 | To avoid confusing your readers, it's a good idea to put a `;` at the end of the cell where you define the interactive element, like we did here. This way, we only show sliders that are actually bound to something. 335 | """ 336 | 337 | # ╔═╡ ff3abf71-cff6-459d-a622-0ec0ca8f164b 338 | md""" 339 | This is is how the `PlutoUI` package works - it defines HTML literals - sometimes with their own scripts. 340 | 341 | If you've written some cool HTML inputs and you want to share them with others, you can also make a UI package! Just publish those definitions as a Julia package and you're done! ✨ 342 | """ 343 | 344 | # ╔═╡ 582769e6-7eb1-11ea-077d-d9b4a3226aac 345 | md""" 346 | ## Behind the scenes 347 | 348 | If you're curious to learn a bit more about how this all works, keep reading! 349 | 350 | ### The output value 351 | 352 | As we've mentioned, bound values are just the latest value of the input element, rather than some kind of observable. 353 | 354 | The update mechanism is _lossy_ and _lazy_, which means that it will skip values if your code is still running - and **only send the latest value when your code is ready again**. This is important when changing a slider from `0` to `100`, for example. If it would send all intermediate values, it might take a while for your code to process everything, causing a noticeable lag. 355 | """ 356 | 357 | # ╔═╡ 8f829274-7eb1-11ea-3888-13c00b3ba70f 358 | md"""### What does the macro do? 359 | 360 | The `@bind` macro does not actually contain the interactivity mechanism, this is built into Pluto itself. Still, it does two things: it assigns a _default value_ to the variable (`missing` in most cases), and it wraps the second argument in a `PlutoRunner.Bond` object. 361 | 362 | For example, _expanding_ the `@bind` macro turns this expression: 363 | 364 | ```julia 365 | @bind x Slider(5:15) 366 | ``` 367 | 368 | into (simplified): 369 | ```julia 370 | begin 371 | local el = Slider(5:15) 372 | global x = AbstractPlutoDingetjes.intial_value(el) 373 | PlutoRunner.create_bond(el, :x) 374 | end 375 | ``` 376 | 377 | We see that the macro creates a variable `x`, which is given the value `AbstractPlutoDingetjes.intial_value(el)`. This function returns `missing` by default, unless a method was implemented for your widget type. For example, `PlutoUI` has a `Slider` type, and it defines a method for `intial_value(slider::Slider)` that returns the default number. 378 | 379 | Declaring a default value using `AbstractPlutoDingetjes` is **not necessary**, as shown by the earlier examples in this notebook, but the default value will be used for `x` if the `notebook.jl` file is _run as a plain julia file_, without Pluto's interactivity. 380 | 381 | You don't need to worry about this if you are just getting started with Pluto and interactive elements, but more advanced users should take a look at [`AbstractPlutoDingetjes.jl`](https://github.com/JuliaPluto/AbstractPlutoDingetjes.jl). 382 | 383 | """ 384 | 385 | # ╔═╡ ced18648-7eb2-11ea-2052-07795685f0da 386 | md"#### JavaScript? 387 | 388 | Yes! We are using `Generator.input` from [`observablehq/stdlib`](https://github.com/observablehq/stdlib#Generators_input) to create a JS _Generator_ (kind of like an Observable) that listens to `onchange`, `onclick` or `oninput` events, [depending on the element type](https://github.com/observablehq/stdlib#Generators_input). 389 | 390 | This makes it super easy to create nice HTML/JS-based interaction elements - a package creator simply has to write a `show` method for MIME type `text/html` that creates a DOM object that triggers the `input` event. In other words, _Pluto's `@bind` will behave exactly like [`viewof` in observablehq](https://observablehq.com/@observablehq/introduction-to-views)_. 391 | 392 | _If you want to learn more about using Javascript in Pluto, check out the [JavaScript sample notebook](https://featured.plutojl.org/web/javascript)!_" 393 | 394 | # ╔═╡ 00000000-0000-0000-0000-000000000001 395 | PLUTO_PROJECT_TOML_CONTENTS = """ 396 | [deps] 397 | """ 398 | 399 | # ╔═╡ 00000000-0000-0000-0000-000000000002 400 | PLUTO_MANIFEST_TOML_CONTENTS = """ 401 | # This file is machine-generated - editing it directly is not advised 402 | 403 | julia_version = "1.11.3" 404 | manifest_format = "2.0" 405 | project_hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709" 406 | 407 | [deps] 408 | """ 409 | 410 | # ╔═╡ Cell order: 411 | # ╟─73c8532e-09a6-429b-b8f6-530c00d92428 412 | # ╟─db24490e-7eac-11ea-094e-9d3fc8f22784 413 | # ╠═bd24d02c-7eac-11ea-14ab-95021678e71e 414 | # ╟─cf72c8a2-7ead-11ea-32b7-d31d5b2dacc2 415 | # ╠═cb1fd532-7eac-11ea-307c-ab16b1977819 416 | # ╟─0a7018ca-2afe-42b1-850f-a649e570709f 417 | # ╠═cb65a4ee-02e5-4779-8728-b994d8af645d 418 | # ╟─816ea402-7eae-11ea-2134-fb595cca3068 419 | # ╠═1ebba747-47f8-4ecd-809d-359e6d803ddc 420 | # ╟─5301eb68-7f14-11ea-3ff6-1f075bf73955 421 | # ╠═4a235d55-a80f-43c7-8f13-759976d88656 422 | # ╠═33b5374c-91d1-4122-82c5-f793d063ffdc 423 | # ╠═d38d06f2-90ce-4e5a-9218-f5a52812e4a2 424 | # ╠═9985a640-c1d3-48dc-b00b-d7500085a37b 425 | # ╠═b6501bfb-5e1d-40b9-bd16-d38085d2611d 426 | # ╠═f595bdb6-bd15-4c62-9de6-49f14c7d365a 427 | # ╠═ede8009e-7f15-11ea-192a-a5c6135a9dcf 428 | # ╟─c1b9fbbb-3629-4abf-b11a-b7345b01d403 429 | # ╠═2969d603-9b6c-403e-abdc-af078c2e53f1 430 | # ╟─de1b9643-66fa-4918-9a93-0f340c8548ba 431 | # ╠═f1f53700-099b-4653-93f1-6b39acdc4c58 432 | # ╟─cf9d49cc-fc70-480c-9f6b-850b0ba4c01f 433 | # ╠═beb9a2bd-cbf5-4679-8403-fc249191f65e 434 | # ╟─6b9a590b-ce24-4a9a-b5b4-5b353e6ccecf 435 | # ╠═e3eb31ae-c512-426f-915c-01144edbc90d 436 | # ╠═5bd8b261-a89d-46a3-bb59-c95a1801c881 437 | # ╟─7b11caf2-1fc1-4e34-8b97-eab86e3557db 438 | # ╟─c50a5e52-7c95-445c-86ee-c60104a39dbd 439 | # ╠═2714a923-2be5-4cf9-97dd-75347968dfee 440 | # ╠═1a338f77-d8f3-4569-a2d5-c174368a4761 441 | # ╠═f39435d3-ed67-45f1-ae56-49cf5ec69d6e 442 | # ╟─e2854aa0-e3c5-423d-80d9-fc875c5dd54d 443 | # ╟─2cefd0de-db13-49c1-abeb-097792ef46f6 444 | # ╠═f558f689-bd7a-4c65-8b3d-b3681a4ed013 445 | # ╠═901c2b84-14b8-4deb-89d6-705a4972582c 446 | # ╟─d5b3adc5-2c99-4901-adf5-8d8579a32b51 447 | # ╟─788c0b9b-238f-4402-b24f-52648103512e 448 | # ╟─bb4b557b-e4fc-45f3-9d1f-060198167bfa 449 | # ╠═2d8661f1-6f78-4161-a306-982e3ddf3646 450 | # ╠═c5a5e243-39d6-43d9-8de7-887661ba99cd 451 | # ╠═3b6dc6d5-ce96-40f6-97f7-511ea6d49122 452 | # ╠═3297233b-9567-4d5e-8138-93ebe20fed48 453 | # ╟─82c7b1ea-08c0-495f-baba-37e5497abde2 454 | # ╟─863c5996-9892-4bfc-96ba-225fa4a2266c 455 | # ╟─ff3abf71-cff6-459d-a622-0ec0ca8f164b 456 | # ╟─582769e6-7eb1-11ea-077d-d9b4a3226aac 457 | # ╟─8f829274-7eb1-11ea-3888-13c00b3ba70f 458 | # ╟─ced18648-7eb2-11ea-2052-07795685f0da 459 | # ╟─00000000-0000-0000-0000-000000000001 460 | # ╟─00000000-0000-0000-0000-000000000002 461 | -------------------------------------------------------------------------------- /pluto-deployment-environment/Manifest.toml: -------------------------------------------------------------------------------- 1 | # This file is machine-generated - editing it directly is not advised 2 | 3 | julia_version = "1.11.7" 4 | manifest_format = "2.0" 5 | project_hash = "13a51ad2b377d764861ea553e631182e0e81a599" 6 | 7 | [[deps.AbstractPlutoDingetjes]] 8 | deps = ["Pkg"] 9 | git-tree-sha1 = "6e1d2a35f2f90a4bc7c2ed98079b2ba09c35b83a" 10 | uuid = "6e696c72-6542-2067-7265-42206c756150" 11 | version = "1.3.2" 12 | 13 | [[deps.AbstractTrees]] 14 | git-tree-sha1 = "2d9c9a55f9c93e8887ad391fbae72f8ef55e1177" 15 | uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" 16 | version = "0.4.5" 17 | 18 | [[deps.ArgTools]] 19 | uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" 20 | version = "1.1.2" 21 | 22 | [[deps.Artifacts]] 23 | uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" 24 | version = "1.11.0" 25 | 26 | [[deps.Base64]] 27 | uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" 28 | version = "1.11.0" 29 | 30 | [[deps.BetterFileWatching]] 31 | deps = ["Deno_jll", "JSON"] 32 | git-tree-sha1 = "0d7ee0a1acad90d544fa87cc3d6f463e99abb77a" 33 | uuid = "c9fd44ac-77b5-486c-9482-9798bd063cc6" 34 | version = "0.1.5" 35 | 36 | [[deps.BitFlags]] 37 | git-tree-sha1 = "0691e34b3bb8be9307330f88d1a3c3f25466c24d" 38 | uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" 39 | version = "0.1.9" 40 | 41 | [[deps.CodecZlib]] 42 | deps = ["TranscodingStreams", "Zlib_jll"] 43 | git-tree-sha1 = "962834c22b66e32aa10f7611c08c8ca4e20749a9" 44 | uuid = "944b1d66-785c-5afd-91f1-9de20f533193" 45 | version = "0.7.8" 46 | 47 | [[deps.Compat]] 48 | deps = ["TOML", "UUIDs"] 49 | git-tree-sha1 = "9d8a54ce4b17aa5bdce0ea5c34bc5e7c340d16ad" 50 | uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" 51 | version = "4.18.1" 52 | 53 | [deps.Compat.extensions] 54 | CompatLinearAlgebraExt = "LinearAlgebra" 55 | 56 | [deps.Compat.weakdeps] 57 | Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" 58 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 59 | 60 | [[deps.ConcurrentUtilities]] 61 | deps = ["Serialization", "Sockets"] 62 | git-tree-sha1 = "d9d26935a0bcffc87d2613ce14c527c99fc543fd" 63 | uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb" 64 | version = "2.5.0" 65 | 66 | [[deps.Configurations]] 67 | deps = ["ExproniconLite", "OrderedCollections", "TOML"] 68 | git-tree-sha1 = "4358750bb58a3caefd5f37a4a0c5bfdbbf075252" 69 | uuid = "5218b696-f38b-4ac9-8b61-a12ec717816d" 70 | version = "0.17.6" 71 | 72 | [[deps.DataAPI]] 73 | git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe" 74 | uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" 75 | version = "1.16.0" 76 | 77 | [[deps.DataValueInterfaces]] 78 | git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" 79 | uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" 80 | version = "1.0.0" 81 | 82 | [[deps.Dates]] 83 | deps = ["Printf"] 84 | uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" 85 | version = "1.11.0" 86 | 87 | [[deps.Deno_jll]] 88 | deps = ["Artifacts", "JLLWrappers", "Libdl"] 89 | git-tree-sha1 = "cd6756e833c377e0ce9cd63fb97689a255f12323" 90 | uuid = "04572ae6-984a-583e-9378-9577a1c2574d" 91 | version = "1.33.4+0" 92 | 93 | [[deps.Distributed]] 94 | deps = ["Random", "Serialization", "Sockets"] 95 | uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" 96 | version = "1.11.0" 97 | 98 | [[deps.Downloads]] 99 | deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] 100 | uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" 101 | version = "1.6.0" 102 | 103 | [[deps.ExceptionUnwrapping]] 104 | deps = ["Test"] 105 | git-tree-sha1 = "d36f682e590a83d63d1c7dbd287573764682d12a" 106 | uuid = "460bff9d-24e4-43bc-9d9f-a8973cb893f4" 107 | version = "0.1.11" 108 | 109 | [[deps.Expat_jll]] 110 | deps = ["Artifacts", "JLLWrappers", "Libdl"] 111 | git-tree-sha1 = "7bb1361afdb33c7f2b085aa49ea8fe1b0fb14e58" 112 | uuid = "2e619515-83b5-522b-bb60-26c02a35a201" 113 | version = "2.7.1+0" 114 | 115 | [[deps.ExpressionExplorer]] 116 | git-tree-sha1 = "4a8c0a9eebf807ac42f0f6de758e60a20be25ffb" 117 | uuid = "21656369-7473-754a-2065-74616d696c43" 118 | version = "1.1.3" 119 | 120 | [[deps.ExproniconLite]] 121 | git-tree-sha1 = "c13f0b150373771b0fdc1713c97860f8df12e6c2" 122 | uuid = "55351af7-c7e9-48d6-89ff-24e801d99491" 123 | version = "0.10.14" 124 | 125 | [[deps.FileWatching]] 126 | uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" 127 | version = "1.11.0" 128 | 129 | [[deps.FromFile]] 130 | deps = ["Downloads", "Requires"] 131 | git-tree-sha1 = "fd1b6f327472d0faf28b4d1fda8d9b582ab136df" 132 | uuid = "ff7dd447-1dcb-4ce3-b8ac-22a812192de7" 133 | version = "0.1.6" 134 | 135 | [[deps.Git]] 136 | deps = ["Git_LFS_jll", "Git_jll", "JLLWrappers", "OpenSSH_jll"] 137 | git-tree-sha1 = "824a1890086880696fc908fe12a17bcf61738bd8" 138 | uuid = "d7ba0133-e1db-5d97-8f8c-041e4b3a1eb2" 139 | version = "1.5.0" 140 | 141 | [[deps.Git_LFS_jll]] 142 | deps = ["Artifacts", "JLLWrappers", "Libdl"] 143 | git-tree-sha1 = "bb8471f313ed941f299aa53d32a94ab3bee08844" 144 | uuid = "020c3dae-16b3-5ae5-87b3-4cb189e250b2" 145 | version = "3.7.0+0" 146 | 147 | [[deps.Git_jll]] 148 | deps = ["Artifacts", "Expat_jll", "JLLWrappers", "LibCURL_jll", "Libdl", "Libiconv_jll", "OpenSSL_jll", "PCRE2_jll", "Zlib_jll"] 149 | git-tree-sha1 = "e2aef26f7d273f1e5b1daba56837c47b49b4388f" 150 | uuid = "f8c6e375-362e-5223-8a59-34ff63f689eb" 151 | version = "2.51.1+0" 152 | 153 | [[deps.Glob]] 154 | git-tree-sha1 = "97285bbd5230dd766e9ef6749b80fc617126d496" 155 | uuid = "c27321d9-0574-5035-807b-f59d2c89b15c" 156 | version = "1.3.1" 157 | 158 | [[deps.GracefulPkg]] 159 | deps = ["Compat", "Pkg", "TOML"] 160 | git-tree-sha1 = "698050b04f3cc0906d0817329d6e96484bf238eb" 161 | uuid = "828d9ff0-206c-6161-646e-6576656f7244" 162 | version = "2.3.0" 163 | 164 | [[deps.HTTP]] 165 | deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "PrecompileTools", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"] 166 | git-tree-sha1 = "5e6fe50ae7f23d171f44e311c2960294aaa0beb5" 167 | uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" 168 | version = "1.10.19" 169 | 170 | [[deps.HypertextLiteral]] 171 | deps = ["Tricks"] 172 | git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653" 173 | uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" 174 | version = "0.9.5" 175 | 176 | [[deps.InteractiveUtils]] 177 | deps = ["Markdown"] 178 | uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" 179 | version = "1.11.0" 180 | 181 | [[deps.IteratorInterfaceExtensions]] 182 | git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" 183 | uuid = "82899510-4779-5014-852e-03e436cf321d" 184 | version = "1.0.0" 185 | 186 | [[deps.JLLWrappers]] 187 | deps = ["Artifacts", "Preferences"] 188 | git-tree-sha1 = "0533e564aae234aff59ab625543145446d8b6ec2" 189 | uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" 190 | version = "1.7.1" 191 | 192 | [[deps.JSON]] 193 | deps = ["Dates", "Mmap", "Parsers", "Unicode"] 194 | git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" 195 | uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" 196 | version = "0.21.4" 197 | 198 | [[deps.LRUCache]] 199 | git-tree-sha1 = "5519b95a490ff5fe629c4a7aa3b3dfc9160498b3" 200 | uuid = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637" 201 | version = "1.6.2" 202 | weakdeps = ["Serialization"] 203 | 204 | [deps.LRUCache.extensions] 205 | SerializationExt = ["Serialization"] 206 | 207 | [[deps.LazilyInitializedFields]] 208 | git-tree-sha1 = "0f2da712350b020bc3957f269c9caad516383ee0" 209 | uuid = "0e77f7df-68c5-4e49-93ce-4cd80f5598bf" 210 | version = "1.3.0" 211 | 212 | [[deps.LeftChildRightSiblingTrees]] 213 | deps = ["AbstractTrees"] 214 | git-tree-sha1 = "95ba48564903b43b2462318aa243ee79d81135ff" 215 | uuid = "1d6d02ad-be62-4b6b-8a6d-2f90e265016e" 216 | version = "0.2.1" 217 | 218 | [[deps.LibCURL]] 219 | deps = ["LibCURL_jll", "MozillaCACerts_jll"] 220 | uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" 221 | version = "0.6.4" 222 | 223 | [[deps.LibCURL_jll]] 224 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] 225 | uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" 226 | version = "8.6.0+0" 227 | 228 | [[deps.LibGit2]] 229 | deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] 230 | uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" 231 | version = "1.11.0" 232 | 233 | [[deps.LibGit2_jll]] 234 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] 235 | uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" 236 | version = "1.7.2+0" 237 | 238 | [[deps.LibSSH2_jll]] 239 | deps = ["Artifacts", "Libdl", "MbedTLS_jll"] 240 | uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" 241 | version = "1.11.0+1" 242 | 243 | [[deps.Libdl]] 244 | uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" 245 | version = "1.11.0" 246 | 247 | [[deps.Libiconv_jll]] 248 | deps = ["Artifacts", "JLLWrappers", "Libdl"] 249 | git-tree-sha1 = "be484f5c92fad0bd8acfef35fe017900b0b73809" 250 | uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" 251 | version = "1.18.0+0" 252 | 253 | [[deps.Logging]] 254 | uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" 255 | version = "1.11.0" 256 | 257 | [[deps.LoggingExtras]] 258 | deps = ["Dates", "Logging"] 259 | git-tree-sha1 = "f00544d95982ea270145636c181ceda21c4e2575" 260 | uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36" 261 | version = "1.2.0" 262 | 263 | [[deps.MIMEs]] 264 | git-tree-sha1 = "c64d943587f7187e751162b3b84445bbbd79f691" 265 | uuid = "6c6e2e6c-3030-632d-7369-2d6c69616d65" 266 | version = "1.1.0" 267 | 268 | [[deps.Malt]] 269 | deps = ["Distributed", "Logging", "RelocatableFolders", "Serialization", "Sockets"] 270 | git-tree-sha1 = "bcb29cc7ba00900bc2d0e630f5116f32001eee6b" 271 | uuid = "36869731-bdee-424d-aa32-cab38c994e3b" 272 | version = "1.2.1" 273 | 274 | [[deps.Markdown]] 275 | deps = ["Base64"] 276 | uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" 277 | version = "1.11.0" 278 | 279 | [[deps.MbedTLS]] 280 | deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"] 281 | git-tree-sha1 = "c067a280ddc25f196b5e7df3877c6b226d390aaf" 282 | uuid = "739be429-bea8-5141-9913-cc70e7f3736d" 283 | version = "1.1.9" 284 | 285 | [[deps.MbedTLS_jll]] 286 | deps = ["Artifacts", "Libdl"] 287 | uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" 288 | version = "2.28.6+0" 289 | 290 | [[deps.Mmap]] 291 | uuid = "a63ad114-7e13-5084-954f-fe012c677804" 292 | version = "1.11.0" 293 | 294 | [[deps.MozillaCACerts_jll]] 295 | uuid = "14a3606d-f60d-562e-9121-12d972cd8159" 296 | version = "2023.12.12" 297 | 298 | [[deps.MsgPack]] 299 | deps = ["Serialization"] 300 | git-tree-sha1 = "f5db02ae992c260e4826fe78c942954b48e1d9c2" 301 | uuid = "99f44e22-a591-53d1-9472-aa23ef4bd671" 302 | version = "1.2.1" 303 | 304 | [[deps.NetworkOptions]] 305 | uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" 306 | version = "1.2.0" 307 | 308 | [[deps.OpenSSH_jll]] 309 | deps = ["Artifacts", "JLLWrappers", "Libdl", "OpenSSL_jll", "Zlib_jll"] 310 | git-tree-sha1 = "1f2f0911e1c02f28a390bb720f97f3349c4dcefb" 311 | uuid = "9bd350c2-7e96-507f-8002-3f2e150b4e1b" 312 | version = "10.0.2+0" 313 | 314 | [[deps.OpenSSL]] 315 | deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"] 316 | git-tree-sha1 = "f1a7e086c677df53e064e0fdd2c9d0b0833e3f6e" 317 | uuid = "4d8831e6-92b7-49fb-bdf8-b643e874388c" 318 | version = "1.5.0" 319 | 320 | [[deps.OpenSSL_jll]] 321 | deps = ["Artifacts", "JLLWrappers", "Libdl"] 322 | git-tree-sha1 = "f19301ae653233bc88b1810ae908194f07f8db9d" 323 | uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" 324 | version = "3.5.4+0" 325 | 326 | [[deps.OrderedCollections]] 327 | git-tree-sha1 = "05868e21324cede2207c6f0f466b4bfef6d5e7ee" 328 | uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" 329 | version = "1.8.1" 330 | 331 | [[deps.PCRE2_jll]] 332 | deps = ["Artifacts", "Libdl"] 333 | uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15" 334 | version = "10.42.0+1" 335 | 336 | [[deps.Parsers]] 337 | deps = ["Dates", "PrecompileTools", "UUIDs"] 338 | git-tree-sha1 = "7d2f8f21da5db6a806faf7b9b292296da42b2810" 339 | uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" 340 | version = "2.8.3" 341 | 342 | [[deps.Pkg]] 343 | deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] 344 | uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" 345 | version = "1.11.0" 346 | weakdeps = ["REPL"] 347 | 348 | [deps.Pkg.extensions] 349 | REPLExt = "REPL" 350 | 351 | [[deps.Pluto]] 352 | deps = ["Base64", "Configurations", "Dates", "Downloads", "ExpressionExplorer", "FileWatching", "GracefulPkg", "HTTP", "HypertextLiteral", "InteractiveUtils", "LRUCache", "Logging", "LoggingExtras", "MIMEs", "Malt", "Markdown", "MsgPack", "Pkg", "PlutoDependencyExplorer", "PrecompileSignatures", "PrecompileTools", "REPL", "Random", "RegistryInstances", "RelocatableFolders", "Scratch", "Sockets", "TOML", "Tables", "URIs", "UUIDs"] 353 | git-tree-sha1 = "9d1df1e072a237e182187f1b480d2eedb3cf2f0b" 354 | uuid = "c3e4b0f8-55cb-11ea-2926-15256bba5781" 355 | version = "0.20.19" 356 | 357 | [[deps.PlutoDependencyExplorer]] 358 | deps = ["ExpressionExplorer", "InteractiveUtils", "Markdown"] 359 | git-tree-sha1 = "c3e5073a977b1c58b2d55c1ec187c3737e64e6af" 360 | uuid = "72656b73-756c-7461-726b-72656b6b696b" 361 | version = "1.2.2" 362 | 363 | [[deps.PlutoSliderServer]] 364 | deps = ["AbstractPlutoDingetjes", "Base64", "BetterFileWatching", "Configurations", "Distributed", "FromFile", "Git", "Glob", "GracefulPkg", "HTTP", "JSON", "Logging", "Pkg", "Pluto", "PlutoDependencyExplorer", "SHA", "Serialization", "Sockets", "TOML", "TerminalLoggers", "UUIDs"] 365 | git-tree-sha1 = "c93f87e90007dd15535b5e209b668f19a0b67d5c" 366 | uuid = "2fc8631c-6f24-4c5b-bca7-cbb509c42db4" 367 | version = "1.6.0" 368 | 369 | [[deps.PrecompileSignatures]] 370 | git-tree-sha1 = "18ef344185f25ee9d51d80e179f8dad33dc48eb1" 371 | uuid = "91cefc8d-f054-46dc-8f8c-26e11d7c5411" 372 | version = "3.0.3" 373 | 374 | [[deps.PrecompileTools]] 375 | deps = ["Preferences"] 376 | git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" 377 | uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" 378 | version = "1.2.1" 379 | 380 | [[deps.Preferences]] 381 | deps = ["TOML"] 382 | git-tree-sha1 = "0f27480397253da18fe2c12a4ba4eb9eb208bf3d" 383 | uuid = "21216c6a-2e73-6563-6e65-726566657250" 384 | version = "1.5.0" 385 | 386 | [[deps.Printf]] 387 | deps = ["Unicode"] 388 | uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" 389 | version = "1.11.0" 390 | 391 | [[deps.ProgressLogging]] 392 | deps = ["Logging", "SHA", "UUIDs"] 393 | git-tree-sha1 = "d95ed0324b0799843ac6f7a6a85e65fe4e5173f0" 394 | uuid = "33c8b6b6-d38a-422a-b730-caa89a2f386c" 395 | version = "0.1.5" 396 | 397 | [[deps.REPL]] 398 | deps = ["InteractiveUtils", "Markdown", "Sockets", "StyledStrings", "Unicode"] 399 | uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" 400 | version = "1.11.0" 401 | 402 | [[deps.Random]] 403 | deps = ["SHA"] 404 | uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 405 | version = "1.11.0" 406 | 407 | [[deps.RegistryInstances]] 408 | deps = ["LazilyInitializedFields", "Pkg", "TOML", "Tar"] 409 | git-tree-sha1 = "ffd19052caf598b8653b99404058fce14828be51" 410 | uuid = "2792f1a3-b283-48e8-9a74-f99dce5104f3" 411 | version = "0.1.0" 412 | 413 | [[deps.RelocatableFolders]] 414 | deps = ["SHA", "Scratch"] 415 | git-tree-sha1 = "ffdaf70d81cf6ff22c2b6e733c900c3321cab864" 416 | uuid = "05181044-ff0b-4ac5-8273-598c1e38db00" 417 | version = "1.0.1" 418 | 419 | [[deps.Requires]] 420 | deps = ["UUIDs"] 421 | git-tree-sha1 = "62389eeff14780bfe55195b7204c0d8738436d64" 422 | uuid = "ae029012-a4dd-5104-9daa-d747884805df" 423 | version = "1.3.1" 424 | 425 | [[deps.SHA]] 426 | uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" 427 | version = "0.7.0" 428 | 429 | [[deps.Scratch]] 430 | deps = ["Dates"] 431 | git-tree-sha1 = "9b81b8393e50b7d4e6d0a9f14e192294d3b7c109" 432 | uuid = "6c6a2e73-6563-6170-7368-637461726353" 433 | version = "1.3.0" 434 | 435 | [[deps.Serialization]] 436 | uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" 437 | version = "1.11.0" 438 | 439 | [[deps.SimpleBufferStream]] 440 | git-tree-sha1 = "f305871d2f381d21527c770d4788c06c097c9bc1" 441 | uuid = "777ac1f9-54b0-4bf8-805c-2214025038e7" 442 | version = "1.2.0" 443 | 444 | [[deps.Sockets]] 445 | uuid = "6462fe0b-24de-5631-8697-dd941f90decc" 446 | version = "1.11.0" 447 | 448 | [[deps.StyledStrings]] 449 | uuid = "f489334b-da3d-4c2e-b8f0-e476e12c162b" 450 | version = "1.11.0" 451 | 452 | [[deps.TOML]] 453 | deps = ["Dates"] 454 | uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" 455 | version = "1.0.3" 456 | 457 | [[deps.TableTraits]] 458 | deps = ["IteratorInterfaceExtensions"] 459 | git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" 460 | uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" 461 | version = "1.0.1" 462 | 463 | [[deps.Tables]] 464 | deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "OrderedCollections", "TableTraits"] 465 | git-tree-sha1 = "f2c1efbc8f3a609aadf318094f8fc5204bdaf344" 466 | uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" 467 | version = "1.12.1" 468 | 469 | [[deps.Tar]] 470 | deps = ["ArgTools", "SHA"] 471 | uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" 472 | version = "1.10.0" 473 | 474 | [[deps.TerminalLoggers]] 475 | deps = ["LeftChildRightSiblingTrees", "Logging", "Markdown", "Printf", "ProgressLogging", "UUIDs"] 476 | git-tree-sha1 = "f133fab380933d042f6796eda4e130272ba520ca" 477 | uuid = "5d786b92-1e48-4d6f-9151-6b4477ca9bed" 478 | version = "0.1.7" 479 | 480 | [[deps.Test]] 481 | deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] 482 | uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" 483 | version = "1.11.0" 484 | 485 | [[deps.TranscodingStreams]] 486 | git-tree-sha1 = "0c45878dcfdcfa8480052b6ab162cdd138781742" 487 | uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" 488 | version = "0.11.3" 489 | 490 | [[deps.Tricks]] 491 | git-tree-sha1 = "372b90fe551c019541fafc6ff034199dc19c8436" 492 | uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" 493 | version = "0.1.12" 494 | 495 | [[deps.URIs]] 496 | git-tree-sha1 = "bef26fb046d031353ef97a82e3fdb6afe7f21b1a" 497 | uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" 498 | version = "1.6.1" 499 | 500 | [[deps.UUIDs]] 501 | deps = ["Random", "SHA"] 502 | uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" 503 | version = "1.11.0" 504 | 505 | [[deps.Unicode]] 506 | uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" 507 | version = "1.11.0" 508 | 509 | [[deps.Zlib_jll]] 510 | deps = ["Libdl"] 511 | uuid = "83775a58-1f1d-513f-b197-d71354ab007a" 512 | version = "1.2.13+1" 513 | 514 | [[deps.nghttp2_jll]] 515 | deps = ["Artifacts", "Libdl"] 516 | uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" 517 | version = "1.59.0+0" 518 | 519 | [[deps.p7zip_jll]] 520 | deps = ["Artifacts", "Libdl"] 521 | uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" 522 | version = "17.4.0+2" 523 | -------------------------------------------------------------------------------- /src/basic/turtles.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://github.com/JuliaPluto/featured/blob/2a6a9664e5428b37abe4957c1dca0994f4a8b7fd/LICENSES/Unlicense" 6 | #> image = "https://github.com/user-attachments/assets/5eb767e4-2f9c-44ff-ace6-eb7bfaee8fcf" 7 | #> order = "5" 8 | #> title = "Turtles – introduction" 9 | #> date = "2024-08-10" 10 | #> tags = ["turtle", "basic"] 11 | #> description = "🐢 Use simple Julia code to make a painting!" 12 | #> license = "Unlicense" 13 | #> 14 | #> [[frontmatter.author]] 15 | #> name = "Pluto.jl" 16 | #> url = "https://github.com/JuliaPluto" 17 | 18 | using Markdown 19 | using InteractiveUtils 20 | 21 | # This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). 22 | macro bind(def, element) 23 | #! format: off 24 | return quote 25 | local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end 26 | local el = $(esc(element)) 27 | global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) 28 | el 29 | end 30 | #! format: on 31 | end 32 | 33 | # ╔═╡ 30543e65-4cfb-41e0-80a8-fa3250ff0adb 34 | using PlutoTurtles 35 | 36 | # ╔═╡ e814a124-f038-11ea-3b22-f109c99dbe03 37 | using PlutoUI 38 | 39 | # ╔═╡ 105b069a-9052-49a5-8f0e-61986775ebb4 40 | md""" 41 | # Turtle drawing! 42 | 43 | This notebook lets you make drawings with a **Turtle** 🐢! You can use **simple Julia code** to make pretty drawings, so this is a great way to practice some Julia. 44 | """ 45 | 46 | # ╔═╡ 1da39e13-45e2-4d27-822a-0bacbd7b416a 47 | md""" 48 | ## Moving around 49 | Every drawing is written with `turtle_drawing` like this: 50 | 51 | ```julia 52 | @steps turtle_drawing() do t 53 | 54 | # your code here! 55 | 56 | end 57 | ``` 58 | 59 | This code creates an empty drawing, with a turtle `t` in the middle. The turtle is holding a pencil, and so when the turtle walks around, they leave a trail. 60 | 61 | Let's make our first drawing by moving the turtle. 62 | """ 63 | 64 | # ╔═╡ e18d7225-5a06-4fbc-b836-17798c0eb198 65 | @steps turtle_drawing() do t 66 | 67 | # take 5 steps 68 | forward!(t, 5) 69 | 70 | # turn left, 90 degrees 71 | left!(t, 90) 72 | 73 | # take 10 steps 74 | forward!(t, 10) 75 | 76 | end 77 | 78 | # ╔═╡ 1ac7cee2-4aa7-497e-befe-8135d1d27d8d 79 | md""" 80 | !!! info "🙋 Does this make sense?" 81 | Take a look at the code above. Can you see how the **code corresponds to the picture**? Which step does what? 82 | """ 83 | 84 | # ╔═╡ 46eebe4b-340b-468c-97c7-a4b5627b7163 85 | md""" 86 | ### Let's make a square! 87 | 88 | Your turn! Edit the code below to draw a square. 🟥 89 | """ 90 | 91 | # ╔═╡ 90b40abf-caa3-4274-b164-e8c6d2f5b920 92 | @steps turtle_drawing() do t 93 | 94 | forward!(t, 5) 95 | 96 | left!(t, 90) 97 | 98 | forward!(t, 5) 99 | 100 | # what's next? 101 | 102 | end 103 | 104 | # ╔═╡ d78b93aa-ae37-4588-a975-575dbd9d1070 105 | md""" 106 | Can you make the square bigger? Smaller? 107 | """ 108 | 109 | # ╔═╡ 04b3d54b-4e0b-46ad-bc92-f94ddfa890ef 110 | md""" 111 | !!! warning "Bonus exercise!" 112 | Did you manage to make a square? Can you also make a triangle? 🔺 113 | """ 114 | 115 | # ╔═╡ 04ac9226-c32a-4efd-b0b5-b896d218e5a1 116 | md""" 117 | ### Turning right 118 | 119 | We know two commands, `forward!` and `left!`. You can also use `backward!` and `right!` 120 | 121 | Can you make a star? 🤩 122 | """ 123 | 124 | # ╔═╡ 3a485abf-8a9c-4ce6-a4a8-49a1be3f6b5f 125 | @steps turtle_drawing() do t 126 | 127 | right!(t, 10) 128 | 129 | 130 | forward!(t, 5) 131 | right!(t, 160) 132 | forward!(t, 5) 133 | 134 | # what's next? 135 | 136 | end 137 | 138 | # ╔═╡ 3733bed0-5490-4d08-bfa6-45f7cc18051b 139 | md""" 140 | ## Seeing the `@steps` 141 | 142 | If you want to see which code line corresponds to which step, then you can use our handy `@steps` macro. Put it at the very start of the cell: 143 | 144 | Instead of this: 145 | 146 | 147 | ```julia 148 | turtle_drawing() do t 149 | 150 | # your code here! 151 | 152 | end 153 | ``` 154 | 155 | You write this: 156 | 157 | ```julia 158 | @steps turtle_drawing() do t 159 | 160 | # your code here! 161 | 162 | end 163 | ``` 164 | 165 | Restart the cell below to see it in action! 166 | """ 167 | 168 | # ╔═╡ 15738a72-008d-4fe0-9f31-d0c7a94b9b61 169 | @steps turtle_drawing() do t 170 | 171 | # take 5 steps 172 | forward!(t, 5) 173 | 174 | # turn left, 90 degrees 175 | left!(t, 90) 176 | 177 | # take 10 steps 178 | forward!(t, 10) 179 | 180 | end 181 | 182 | # ╔═╡ 634309bc-64e7-47ef-888b-a083a485e105 183 | md""" 184 | ## Using the `for` loop 185 | 186 | Let's make a zig-zag line! 187 | """ 188 | 189 | # ╔═╡ 19abbdeb-efe3-4a26-85c9-011ae5939c8e 190 | @steps turtle_drawing() do t 191 | 192 | forward!(t, 5) 193 | right!(t, 160) # turn right, 160 degrees (almost a 180 degree half turn) 194 | forward!(t, 5) 195 | left!(t, 160) # turn back 196 | 197 | 198 | ### REPEAT 199 | forward!(t, 5) 200 | right!(t, 160) 201 | forward!(t, 5) 202 | left!(t, 160) 203 | 204 | ### REPEAT 205 | forward!(t, 5) 206 | right!(t, 160) 207 | forward!(t, 5) 208 | left!(t, 160) 209 | 210 | ### REPEAT 211 | forward!(t, 5) 212 | right!(t, 160) 213 | forward!(t, 5) 214 | left!(t, 160) 215 | 216 | end 217 | 218 | # ╔═╡ 2b245c13-82d7-40f6-b26b-d702962b37f3 219 | md""" 220 | You see that we make a zig-zag by doing one up-down motion, and repeating this. But if we want to make the drawing very long, **our code will become very long**. 221 | 222 | This is why `for`-loops are useful: you can **repeat the same block of code multiple times**. Check it out: 223 | """ 224 | 225 | # ╔═╡ a84af845-7f7a-45eb-b1d4-dde8047cb8e8 226 | @steps turtle_drawing() do t 227 | 228 | for i in 1:10 229 | forward!(t, 5) 230 | right!(t, 160) 231 | forward!(t, 5) 232 | left!(t, 160) 233 | end 234 | 235 | end 236 | 237 | # ╔═╡ 42f262dd-4208-4a84-bd2d-5f4be5c78964 238 | md""" 239 | **Try it yourself!** Write some code in the `for` loop, and it will repeat 10 times. Try whatever you want! 240 | """ 241 | 242 | # ╔═╡ 5f0a4d6a-2545-4610-b827-6adc50204136 243 | @steps turtle_drawing() do t 244 | 245 | for i in 1:10 246 | # repeat something 10 times 247 | # write your code here! for example: 248 | forward!(t, 2) 249 | 250 | end 251 | 252 | end 253 | 254 | # ╔═╡ d742acd5-ad8d-4ee6-bab0-e54ab9313e0d 255 | md""" 256 | ### The iterator `i` 257 | 258 | Inside the `for` loop, you can use the variable `i`, which goes from `1` to `10`. In the playground above, write `forward!(t, i)` somewhere inside the `for` loop. This means: *"move the turtle `t` forward by `i` steps"*. 259 | 260 | Do you understand what happens? 261 | """ 262 | 263 | # ╔═╡ 71bb4346-7067-4db4-9a70-ab232e7c2ebc 264 | md""" 265 | ## Adding color 266 | 267 | You can use the `color!` function to set the color of the turtle. This will determine the color of all future lines that you draw! 268 | """ 269 | 270 | # ╔═╡ 448dc68d-cd0a-4491-82ad-0e7cc00782ad 271 | @steps turtle_drawing() do t 272 | 273 | color!(t, "red") 274 | forward!(t, 5) 275 | 276 | right!(t, 90) 277 | 278 | color!(t, "pink") 279 | forward!(t, 10) 280 | 281 | end 282 | 283 | # ╔═╡ 14c803ff-268b-48bc-90c9-faa88010f5fe 284 | md""" 285 | ### Which colors can I use? 286 | Most English words for colors will work! Like **`"red"`**, **`"gray"`** and **`"darkviolet"`**. For a complete list, see [this table](https://developer.mozilla.org/en-US/docs/Web/CSS/named-color#value). You can also use [sytnax like **`"rgb(255 100 0)"`**](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#syntax). 287 | """ 288 | 289 | # ╔═╡ 45e31b3e-7f25-411a-b7c7-a1a8a7c77ddd 290 | turtle_drawing() do t 291 | for color in ["red", "orange", "yellow", "green", "turquoise", "blue", "purple"] 292 | # draw the line 293 | color!(t, color) 294 | forward!(t, 10) 295 | backward!(t, 10) 296 | 297 | # take a step left 298 | penup!(t) 299 | left!(t, 90) 300 | forward!(t, 0.4) 301 | right!(t, 90) 302 | pendown!(t) 303 | end 304 | end 305 | 306 | # ╔═╡ 01b73386-ce68-4ad7-92af-17d91930f8f5 307 | md""" 308 | ## Using global variables 309 | 310 | In a code cell, you can also create a **variable**, and use the value multiple times. For example: 311 | """ 312 | 313 | # ╔═╡ aa3d15c6-f6c2-49cd-9a77-7d9951157897 314 | example_step = 1.5 315 | 316 | # ╔═╡ f3ced552-1b2e-47a1-be8a-6a0c20561ae1 317 | md""" 318 | You can use this variable in other cells: 319 | """ 320 | 321 | # ╔═╡ 93fc3d23-9d7d-42ac-83fe-1cd568624a87 322 | example_step + example_step 323 | 324 | # ╔═╡ 160a5b22-6f1e-446d-861a-747cfe25bfda 325 | md""" 326 | We can also use variables in our drawings! Do you see where `example_step` is used in the example below? 327 | """ 328 | 329 | # ╔═╡ 31847740-bb0b-41cc-9d4f-a42ee33bbc62 330 | turtle_drawing() do t 331 | 332 | for i in 1:10 333 | color!(t, "black") 334 | forward!(t, example_step) 335 | 336 | color!(t, "red") 337 | forward!(t, example_step) 338 | end 339 | 340 | end 341 | 342 | # ╔═╡ 468eb41d-fa5a-46cd-a5ef-2708c74e5ee0 343 | md""" 344 | Now, go to [the definition of `example_step`](#example_step) and change the value from `1.5` to another number. 345 | 346 | Do you see the drawing change? 347 | """ 348 | 349 | # ╔═╡ 5a32b0d4-6a72-4b11-96ab-b6c8374153ba 350 | md""" 351 | ## Interactivity with PlutoUI 352 | 353 | Let's do something fun! In the example above, you saw how you can change variables to control the image. In this section, we will use interactive elements from the package PlutoUI to **control Julia variables**. Let's try it! 354 | 355 | **👇 Move the slider and color picker below:** 356 | """ 357 | 358 | # ╔═╡ 925a66b2-3564-480c-be12-0e626b01362f 359 | @bind fun_angle Slider(0:180) 360 | 361 | # ╔═╡ c347a8ad-c859-4eb2-8fdc-bb7f04c7f70e 362 | @bind second_color ColorStringPicker() 363 | 364 | # ╔═╡ fac4f50a-ce65-4f22-af23-0fc73af936f2 365 | fun_angle, second_color 366 | 367 | # ╔═╡ aa724bc5-563f-4421-a55c-84ebd766f364 368 | turtle_drawing() do t 369 | 370 | for i in 1:10 371 | color!(t, "black") 372 | forward!(t, 3) 373 | 374 | right!(t, fun_angle) 375 | 376 | color!(t, second_color) 377 | forward!(t, 3) 378 | end 379 | 380 | end 381 | 382 | # ╔═╡ ea5f57d5-1396-4d66-885e-bc08864475c1 383 | md""" 384 | ## Functions 385 | 386 | You can extract some code into a function, and reuse it later! Here is some code that draws a house, and we can use it to make a street! 387 | """ 388 | 389 | # ╔═╡ 8f55e3f7-4082-4df9-b290-2b9183b067d8 390 | function drawhouse(t) 391 | # floor 392 | forward!(t, 6) 393 | 394 | # wall 395 | left!(t, 90) 396 | forward!(t, 6) 397 | 398 | # roof 399 | left!(t, 45) 400 | forward!(t, sqrt(2) * 3) 401 | left!(t, 90) 402 | forward!(t, sqrt(2) * 3) 403 | left!(t, 45) 404 | 405 | # wall 406 | forward!(t, 6) 407 | left!(t, 90) 408 | end 409 | 410 | # ╔═╡ 1f3a56d1-0756-410d-be55-504398052149 411 | @steps turtle_drawing() do t 412 | penup!(t) 413 | right!(t, 90) 414 | backward!(t, 14) 415 | pendown!(t) 416 | 417 | for i in 1:4 418 | drawhouse(t) 419 | 420 | penup!(t) 421 | forward!(t, 7) 422 | pendown!(t) 423 | end 424 | end 425 | 426 | # ╔═╡ adce0892-05bd-45da-9e1f-3877af5e8f7f 427 | md""" 428 | ## Write your own notebook! 429 | 430 | That's it for now! If you would like to play more with turtle code, just open a new Pluto notebook and use the [PlutoTurtles.jl](https://github.com/JuliaPluto/PlutoTurtles.jl) package: 431 | 432 | ```julia 433 | using PlutoTurtles 434 | ``` 435 | """ 436 | 437 | # ╔═╡ 00000000-0000-0000-0000-000000000001 438 | PLUTO_PROJECT_TOML_CONTENTS = """ 439 | [deps] 440 | PlutoTurtles = "67697473-756c-6b61-6172-6b407461726b" 441 | PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" 442 | 443 | [compat] 444 | PlutoTurtles = "~1.0.1" 445 | PlutoUI = "~0.7.55" 446 | """ 447 | 448 | # ╔═╡ 00000000-0000-0000-0000-000000000002 449 | PLUTO_MANIFEST_TOML_CONTENTS = """ 450 | # This file is machine-generated - editing it directly is not advised 451 | 452 | [[AbstractPlutoDingetjes]] 453 | deps = ["Pkg"] 454 | git-tree-sha1 = "6e1d2a35f2f90a4bc7c2ed98079b2ba09c35b83a" 455 | uuid = "6e696c72-6542-2067-7265-42206c756150" 456 | version = "1.3.2" 457 | 458 | [[ArgTools]] 459 | uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" 460 | version = "1.1.2" 461 | 462 | [[Artifacts]] 463 | uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" 464 | version = "1.11.0" 465 | 466 | [[Base64]] 467 | uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" 468 | version = "1.11.0" 469 | 470 | [[ColorTypes]] 471 | deps = ["FixedPointNumbers", "Random"] 472 | git-tree-sha1 = "b10d0b65641d57b8b4d5e234446582de5047050d" 473 | uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" 474 | version = "0.11.5" 475 | 476 | [[Compat]] 477 | deps = ["TOML", "UUIDs"] 478 | git-tree-sha1 = "8ae8d32e09f0dcf42a36b90d4e17f5dd2e4c4215" 479 | uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" 480 | version = "4.16.0" 481 | weakdeps = ["Dates", "LinearAlgebra"] 482 | 483 | [Compat.extensions] 484 | CompatLinearAlgebraExt = "LinearAlgebra" 485 | 486 | [[CompilerSupportLibraries_jll]] 487 | deps = ["Artifacts", "Libdl"] 488 | uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" 489 | version = "1.1.1+0" 490 | 491 | [[Dates]] 492 | deps = ["Printf"] 493 | uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" 494 | version = "1.11.0" 495 | 496 | [[Downloads]] 497 | deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] 498 | uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" 499 | version = "1.6.0" 500 | 501 | [[FileWatching]] 502 | uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" 503 | version = "1.11.0" 504 | 505 | [[FixedPointNumbers]] 506 | deps = ["Statistics"] 507 | git-tree-sha1 = "05882d6995ae5c12bb5f36dd2ed3f61c98cbb172" 508 | uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" 509 | version = "0.8.5" 510 | 511 | [[Hyperscript]] 512 | deps = ["Test"] 513 | git-tree-sha1 = "179267cfa5e712760cd43dcae385d7ea90cc25a4" 514 | uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91" 515 | version = "0.0.5" 516 | 517 | [[HypertextLiteral]] 518 | deps = ["Tricks"] 519 | git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653" 520 | uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" 521 | version = "0.9.5" 522 | 523 | [[IOCapture]] 524 | deps = ["Logging", "Random"] 525 | git-tree-sha1 = "b6d6bfdd7ce25b0f9b2f6b3dd56b2673a66c8770" 526 | uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" 527 | version = "0.2.5" 528 | 529 | [[InteractiveUtils]] 530 | deps = ["Markdown"] 531 | uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" 532 | version = "1.11.0" 533 | 534 | [[JSON]] 535 | deps = ["Dates", "Mmap", "Parsers", "Unicode"] 536 | git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" 537 | uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" 538 | version = "0.21.4" 539 | 540 | [[LibCURL]] 541 | deps = ["LibCURL_jll", "MozillaCACerts_jll"] 542 | uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" 543 | version = "0.6.4" 544 | 545 | [[LibCURL_jll]] 546 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] 547 | uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" 548 | version = "8.6.0+0" 549 | 550 | [[LibGit2]] 551 | deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] 552 | uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" 553 | version = "1.11.0" 554 | 555 | [[LibGit2_jll]] 556 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] 557 | uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" 558 | version = "1.7.2+0" 559 | 560 | [[LibSSH2_jll]] 561 | deps = ["Artifacts", "Libdl", "MbedTLS_jll"] 562 | uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" 563 | version = "1.11.0+1" 564 | 565 | [[Libdl]] 566 | uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" 567 | version = "1.11.0" 568 | 569 | [[LinearAlgebra]] 570 | deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] 571 | uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 572 | version = "1.11.0" 573 | 574 | [[Logging]] 575 | uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" 576 | version = "1.11.0" 577 | 578 | [[MIMEs]] 579 | git-tree-sha1 = "c64d943587f7187e751162b3b84445bbbd79f691" 580 | uuid = "6c6e2e6c-3030-632d-7369-2d6c69616d65" 581 | version = "1.1.0" 582 | 583 | [[Markdown]] 584 | deps = ["Base64"] 585 | uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" 586 | version = "1.11.0" 587 | 588 | [[MbedTLS_jll]] 589 | deps = ["Artifacts", "Libdl"] 590 | uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" 591 | version = "2.28.6+0" 592 | 593 | [[Mmap]] 594 | uuid = "a63ad114-7e13-5084-954f-fe012c677804" 595 | version = "1.11.0" 596 | 597 | [[MozillaCACerts_jll]] 598 | uuid = "14a3606d-f60d-562e-9121-12d972cd8159" 599 | version = "2023.12.12" 600 | 601 | [[NetworkOptions]] 602 | uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" 603 | version = "1.2.0" 604 | 605 | [[OpenBLAS_jll]] 606 | deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] 607 | uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" 608 | version = "0.3.27+1" 609 | 610 | [[Parsers]] 611 | deps = ["Dates", "PrecompileTools", "UUIDs"] 612 | git-tree-sha1 = "7d2f8f21da5db6a806faf7b9b292296da42b2810" 613 | uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" 614 | version = "2.8.3" 615 | 616 | [[Pkg]] 617 | deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] 618 | uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" 619 | version = "1.11.0" 620 | 621 | [Pkg.extensions] 622 | REPLExt = "REPL" 623 | 624 | [Pkg.weakdeps] 625 | REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" 626 | 627 | [[PlutoTurtles]] 628 | deps = ["AbstractPlutoDingetjes", "Compat", "HypertextLiteral", "InteractiveUtils", "Markdown", "PlutoUI"] 629 | git-tree-sha1 = "467866275ad02b4abf63c80bad78ad4f92744473" 630 | uuid = "67697473-756c-6b61-6172-6b407461726b" 631 | version = "1.0.1" 632 | 633 | [[PlutoUI]] 634 | deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "FixedPointNumbers", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "MIMEs", "Markdown", "Random", "Reexport", "URIs", "UUIDs"] 635 | git-tree-sha1 = "d3de2694b52a01ce61a036f18ea9c0f61c4a9230" 636 | uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8" 637 | version = "0.7.62" 638 | 639 | [[PrecompileTools]] 640 | deps = ["Preferences"] 641 | git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" 642 | uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" 643 | version = "1.2.1" 644 | 645 | [[Preferences]] 646 | deps = ["TOML"] 647 | git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" 648 | uuid = "21216c6a-2e73-6563-6e65-726566657250" 649 | version = "1.4.3" 650 | 651 | [[Printf]] 652 | deps = ["Unicode"] 653 | uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" 654 | version = "1.11.0" 655 | 656 | [[Random]] 657 | deps = ["SHA"] 658 | uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 659 | version = "1.11.0" 660 | 661 | [[Reexport]] 662 | git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" 663 | uuid = "189a3867-3050-52da-a836-e630ba90ab69" 664 | version = "1.2.2" 665 | 666 | [[SHA]] 667 | uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" 668 | version = "0.7.0" 669 | 670 | [[Serialization]] 671 | uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" 672 | version = "1.11.0" 673 | 674 | [[Statistics]] 675 | deps = ["LinearAlgebra"] 676 | git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0" 677 | uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" 678 | version = "1.11.1" 679 | 680 | [Statistics.extensions] 681 | SparseArraysExt = ["SparseArrays"] 682 | 683 | [Statistics.weakdeps] 684 | SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" 685 | 686 | [[TOML]] 687 | deps = ["Dates"] 688 | uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" 689 | version = "1.0.3" 690 | 691 | [[Tar]] 692 | deps = ["ArgTools", "SHA"] 693 | uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" 694 | version = "1.10.0" 695 | 696 | [[Test]] 697 | deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] 698 | uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" 699 | version = "1.11.0" 700 | 701 | [[Tricks]] 702 | git-tree-sha1 = "6cae795a5a9313bbb4f60683f7263318fc7d1505" 703 | uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" 704 | version = "0.1.10" 705 | 706 | [[URIs]] 707 | git-tree-sha1 = "cbbebadbcc76c5ca1cc4b4f3b0614b3e603b5000" 708 | uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" 709 | version = "1.5.2" 710 | 711 | [[UUIDs]] 712 | deps = ["Random", "SHA"] 713 | uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" 714 | version = "1.11.0" 715 | 716 | [[Unicode]] 717 | uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" 718 | version = "1.11.0" 719 | 720 | [[Zlib_jll]] 721 | deps = ["Libdl"] 722 | uuid = "83775a58-1f1d-513f-b197-d71354ab007a" 723 | version = "1.2.13+1" 724 | 725 | [[libblastrampoline_jll]] 726 | deps = ["Artifacts", "Libdl"] 727 | uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" 728 | version = "5.11.0+0" 729 | 730 | [[nghttp2_jll]] 731 | deps = ["Artifacts", "Libdl"] 732 | uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" 733 | version = "1.59.0+0" 734 | 735 | [[p7zip_jll]] 736 | deps = ["Artifacts", "Libdl"] 737 | uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" 738 | version = "17.4.0+2" 739 | """ 740 | 741 | # ╔═╡ Cell order: 742 | # ╟─105b069a-9052-49a5-8f0e-61986775ebb4 743 | # ╠═30543e65-4cfb-41e0-80a8-fa3250ff0adb 744 | # ╟─1da39e13-45e2-4d27-822a-0bacbd7b416a 745 | # ╠═e18d7225-5a06-4fbc-b836-17798c0eb198 746 | # ╟─1ac7cee2-4aa7-497e-befe-8135d1d27d8d 747 | # ╟─46eebe4b-340b-468c-97c7-a4b5627b7163 748 | # ╠═90b40abf-caa3-4274-b164-e8c6d2f5b920 749 | # ╟─d78b93aa-ae37-4588-a975-575dbd9d1070 750 | # ╟─04b3d54b-4e0b-46ad-bc92-f94ddfa890ef 751 | # ╟─04ac9226-c32a-4efd-b0b5-b896d218e5a1 752 | # ╠═3a485abf-8a9c-4ce6-a4a8-49a1be3f6b5f 753 | # ╟─3733bed0-5490-4d08-bfa6-45f7cc18051b 754 | # ╠═15738a72-008d-4fe0-9f31-d0c7a94b9b61 755 | # ╟─634309bc-64e7-47ef-888b-a083a485e105 756 | # ╠═19abbdeb-efe3-4a26-85c9-011ae5939c8e 757 | # ╟─2b245c13-82d7-40f6-b26b-d702962b37f3 758 | # ╠═a84af845-7f7a-45eb-b1d4-dde8047cb8e8 759 | # ╟─42f262dd-4208-4a84-bd2d-5f4be5c78964 760 | # ╠═5f0a4d6a-2545-4610-b827-6adc50204136 761 | # ╟─d742acd5-ad8d-4ee6-bab0-e54ab9313e0d 762 | # ╟─71bb4346-7067-4db4-9a70-ab232e7c2ebc 763 | # ╠═448dc68d-cd0a-4491-82ad-0e7cc00782ad 764 | # ╟─14c803ff-268b-48bc-90c9-faa88010f5fe 765 | # ╠═45e31b3e-7f25-411a-b7c7-a1a8a7c77ddd 766 | # ╟─01b73386-ce68-4ad7-92af-17d91930f8f5 767 | # ╠═aa3d15c6-f6c2-49cd-9a77-7d9951157897 768 | # ╟─f3ced552-1b2e-47a1-be8a-6a0c20561ae1 769 | # ╠═93fc3d23-9d7d-42ac-83fe-1cd568624a87 770 | # ╟─160a5b22-6f1e-446d-861a-747cfe25bfda 771 | # ╠═31847740-bb0b-41cc-9d4f-a42ee33bbc62 772 | # ╟─468eb41d-fa5a-46cd-a5ef-2708c74e5ee0 773 | # ╟─5a32b0d4-6a72-4b11-96ab-b6c8374153ba 774 | # ╠═e814a124-f038-11ea-3b22-f109c99dbe03 775 | # ╠═925a66b2-3564-480c-be12-0e626b01362f 776 | # ╠═c347a8ad-c859-4eb2-8fdc-bb7f04c7f70e 777 | # ╠═fac4f50a-ce65-4f22-af23-0fc73af936f2 778 | # ╠═aa724bc5-563f-4421-a55c-84ebd766f364 779 | # ╟─ea5f57d5-1396-4d66-885e-bc08864475c1 780 | # ╠═8f55e3f7-4082-4df9-b290-2b9183b067d8 781 | # ╠═1f3a56d1-0756-410d-be55-504398052149 782 | # ╟─adce0892-05bd-45da-9e1f-3877af5e8f7f 783 | # ╟─00000000-0000-0000-0000-000000000001 784 | # ╟─00000000-0000-0000-0000-000000000002 785 | -------------------------------------------------------------------------------- /src/basic/Pluto for Jupyter users.jl: -------------------------------------------------------------------------------- 1 | ### A Pluto.jl notebook ### 2 | # v0.20.8 3 | 4 | #> [frontmatter] 5 | #> license_url = "https://github.com/JuliaPluto/featured/blob/main/LICENSES/Unlicense" 6 | #> image = "https://github.com/JuliaPluto/featured/assets/6933510/19a10d1d-2a3b-42d0-9804-c1fd41c83bcd" 7 | #> title = "Pluto for Jupyter users" 8 | #> tags = ["basic"] 9 | #> license = "Unlicense" 10 | #> description = "Coming to Pluto from Jupyter? Here's what you need to know!" 11 | #> 12 | #> [[frontmatter.author]] 13 | #> name = "Pluto.jl" 14 | #> url = "https://github.com/JuliaPluto" 15 | 16 | using Markdown 17 | using InteractiveUtils 18 | 19 | # This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). 20 | macro bind(def, element) 21 | #! format: off 22 | return quote 23 | local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end 24 | local el = $(esc(element)) 25 | global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el) 26 | el 27 | end 28 | #! format: on 29 | end 30 | 31 | # ╔═╡ db1ef6d1-7921-4035-8705-a0820048b785 32 | using PlutoUI 33 | 34 | # ╔═╡ cdbcc440-858c-11ee-25d2-dd9d69531eef 35 | md""" 36 | # Pluto for Jupyter users 37 | 38 | [Jupyter](https://jupyter.org/) is another open source notebook environment, that works with Julia, Python, and R. If you're already familiar with Jupyter and are now trying out Pluto, this notebook is for you! 39 | 40 | We'll go over some key differences between Pluto and Jupyter. Let's get started! 41 | """ 42 | 43 | # ╔═╡ a423fc4f-6000-4451-bc03-4035c9847753 44 | md""" 45 | ## Reactivity 46 | 47 | The most notable difference between Pluto and Jupyter is **reactivity**. 48 | 49 | Here we have two cells: one defines `apples`, and one defines `oranges`, which depends on `apples`. Try changing the value of `apples` here, and see what happens! 50 | """ 51 | 52 | # ╔═╡ b25c812b-7ec2-4e17-aa1b-e1a1407d29fb 53 | apples = 1 54 | 55 | # ╔═╡ 8e1faf5f-7b60-4b57-9902-e9d2531f0961 56 | oranges = apples + 50 57 | 58 | # ╔═╡ 03d3ade3-056a-4f16-9b31-d259879082c9 59 | md""" 60 | When you change `apples`, then `oranges` is immediately updated! ⚡ 61 | """ 62 | 63 | # ╔═╡ 1512a488-3d77-4161-9fd0-0ade53e75c34 64 | details("Can't change code?", md""" 65 | If you are reading this notebook online, you need to install Pluto to run the notebook. Here is a video recording! 66 | 67 | ![Screen capture video where I cange the value of apples, and oranges updates to match](https://github.com/user-attachments/assets/fade5851-8493-4f93-a960-766d3048acec) 68 | """) 69 | 70 | # ╔═╡ 3ed1ed94-8741-48a0-9d23-bb78499eec91 71 | md""" 72 | That's what we mean by reactivity in Pluto. Pluto analyses the _dependencies_ between your code, and reruns cells when needed to keep everything up to date. This is very different from Jupyter, where you were in charge of deciding when to rerun cells! 73 | """ 74 | 75 | # ╔═╡ 773ac617-4e5d-46b9-92ff-b0d9a23e42f1 76 | md""" 77 | > #### Why reactive? 78 | > Reactivity can save you some tedious work of having to rerun several cells when you change a variable, but it's more than a time-saver! 79 | > 80 | > Because the output of your cells is always kept up-to-date, you won't have weird errors that depend on some code that you ran in your session but deleted over an hour ago. Likewise, when you shut down Pluto and open it the next day, all your notebooks will work exactly like yesterday. 81 | > 82 | > 83 | > ##### Descriptive programming 84 | > Pluto offers an environment where changed code takes effect instantly and where deleted code leaves no trace. Unlike Jupyter or Matlab, there is **no mutable workspace**, but rather, an important guarantee: 85 | > 86 | > > _**At any instant**, the program state is **completely described** by the code you see._ 87 | 88 | ### Try it! 89 | 90 | Write your own code in the cells below! 91 | 92 | """ 93 | 94 | # ╔═╡ 6ba28587-3612-45bb-a5fa-5e1ce8fa3aa6 95 | 96 | 97 | # ╔═╡ f4d990a8-274a-4098-b4f9-ce1d39ec41a6 98 | 99 | 100 | # ╔═╡ 74a6102a-e09d-4ebb-9ef8-2511b0f46f58 101 | md""" 102 | ## Cell order 103 | 104 | You can put Pluto cells in **any order**, you code does not need to run top to bottom! Here the **`group_of_mice`** cell depends on **`mouse`**, but **`mouse`** comes second: 105 | """ 106 | 107 | # ╔═╡ 3bca136c-115f-4dd1-ac4d-d14c23c538ce 108 | mouse = "🐭" 109 | 110 | # ╔═╡ 807b1586-8b3e-4cb1-9a9d-8ca66a28ec3e 111 | group_of_mice = repeat(mouse, 3) 112 | 113 | # ╔═╡ 2b91d104-921a-4d66-ac1f-a940cdb2d14c 114 | md""" 115 | This is also fine in Jupyter, but it's discouraged. Running cells yourself is easier when you can run things top-to-bottom, and the "run all cells" command also requires your cells work like that. 116 | 117 | Because Pluto analyses the dependencies in your code, playing with the order of cells is no problem at all! You can place cells in the order that you want to *present* them in – you might want to show results first, and put your functions and calculations at the bottom of the notebook. 118 | """ 119 | 120 | # ╔═╡ 3103e636-3f0a-4e16-94f7-3da1a573ec3d 121 | md""" 122 | ## Hidden code 123 | In Pluto, you can **choose to hide/show** the code for any cell. 124 | 125 | **For example:** The cell below has **hidden code** – you only see the output. You need to edit this notebook to see the code behind the output. 126 | """ 127 | 128 | # ╔═╡ 0948181e-b26c-421b-83b5-c9dceb71e804 129 | train = let 130 | locomotive = "🚂" 131 | wagon = "🚃" 132 | 133 | Text("$(locomotive)$(join(fill(wagon, 6)))") 134 | end 135 | 136 | # ╔═╡ 9c3cfd5e-b89c-4df2-9982-d581e9fc3730 137 | md""" 138 | ## Hidden output 139 | Just like in Jupyter and the Julia REPL, you can **hide output** by adding a `;` at the end of you code. 140 | 141 | **For example:** this cell has **visible code** but **hidden output**. 142 | """ 143 | 144 | # ╔═╡ f6e66043-6773-470a-9a07-17283c878d79 145 | 1 + 1; 146 | 147 | # ╔═╡ 2a84a64a-b819-4246-8f77-99679691da61 148 | md""" 149 | ## Interactivity with `@bind` 150 | You can use **`@bind`** and [PlutoUI.jl](https://github.com/JuliaPluto/PlutoUI.jl) to write interactive notebooks! 151 | """ 152 | 153 | # ╔═╡ 3323e930-31be-4b0b-8cf2-71a07a017758 154 | @bind yourname TextField(default="Frida") 155 | 156 | # ╔═╡ c702dde3-6cb4-4444-ab1d-f1db95e6776a 157 | @bind count Slider(1:100) 158 | 159 | # ╔═╡ b04a791f-7eb9-40eb-9cab-ff38fbc6cca6 160 | md""" 161 | Now we have two global variables, **`yourname`** and **`count`** that we can use in other cells: 162 | """ 163 | 164 | # ╔═╡ def86a18-7106-490d-a1f0-c3e48b42b8f6 165 | repeat(yourname, count) 166 | 167 | # ╔═╡ ec2bcfd5-bd38-4801-ac38-2339bc782147 168 | 169 | 170 | # ╔═╡ 1086228a-e28d-45c7-9153-c79378239e54 171 | md""" 172 | To learn more, take a look at the other featured notebooks! 173 | """ 174 | 175 | # ╔═╡ 447f49ce-1738-4987-a976-094174971ccb 176 | md""" 177 | ## Re-assigning variables 178 | 179 | Here' s something that you **cannot do** in Pluto: 180 | """ 181 | 182 | # ╔═╡ c4ece2cd-31f4-4c91-a59b-e520de13dedd 183 | md""" 184 | We tried to create multiple cells that set the value of `greatness`, but that's not possible! 185 | 186 | > #### Why is this not allowed? 187 | > This is because Pluto's reactivity. What should the value of **`greatness`** be in this notebook? 188 | > 189 | > Pluto also can't decide the proper dependency order between the three cells. Should `greatness` be `(0 + 10) * 2)` or `(0 * 2) + 10` ? 190 | > 191 | > We can't give an answer that everyone will agree on in every situation - so for clarity, Pluto just prohibits this kind of ambiguity. So the restriction forces you to write a notebook that is **reproducible**: it will give the same result no matter when/how you run the cells. 192 | 193 | If you run into this error, you can do two things: 194 | 195 | - Wrap all definitions together into a single cell 196 | - Rename variables so they all have different names, e.g. `greatness_1`, `greatness_2`. 197 | """ 198 | 199 | # ╔═╡ 5200e802-8080-4394-aa85-e2604c7279c8 200 | md""" 201 | ## Multiple expressions per cell 202 | 203 | When you start programming your first Pluto notebook, you'll probably run in to this error: 204 | """ 205 | 206 | # ╔═╡ 94991d24-6aad-4361-a8e5-5e2c1f15c53c 207 | cat = "🐈" 208 | dog = "🐕" 209 | 210 | # ╔═╡ 244ca1ba-c2dc-4713-9dd0-57ed0d19ba70 211 | md""" 212 | Ah, Pluto cells must be a single expression. Not to worry - as you can see, the error message lets you pick a solution (you can click on the two options). Either split up the cell in two: 213 | 214 | ```julia 215 | cat = "🐈" 216 | ``` 217 | 218 | ```julia 219 | dog = "🐕" 220 | ``` 221 | 222 | ... or write a cell with a `begin` ... `end` block: 223 | 224 | ```julia 225 | begin 226 | cat = "🐈" 227 | dog = "🐕" 228 | end 229 | ``` 230 | """ 231 | 232 | # ╔═╡ 4df1d31c-db13-49a1-963b-337550cd2bda 233 | md""" 234 | > #### Why is this not allowed? 235 | > Coming from Jupyter, this can feel a bit frustrating. Jupyter programmers often divide up their notebook in "sections" or code, with each cell containing 3-10 expressions. Grouping expressions like this makes sense in Jupyter because you're in charge of rerunning cells. It's just more efficient and less error-prone to group related statements in a single cell. 236 | > 237 | > In Pluto, you don't have to worry about that! Instead, Pluto's analysis of dependencies in your code works best when each cell defines only a single variable. 238 | > 239 | > We find that it is **almost always a good idea to split your code into more cells**. The more cells, the more intermediate results that you can see. 240 | """ 241 | 242 | # ╔═╡ a7ea9146-86f6-4d2a-85a3-950f2e7bc102 243 | md""" 244 | ## Package management 245 | 246 | Here is a neat thing in Pluto: it will manage your packages for you! 247 | 248 | **To use a package to your notebook, just write a cell importing it**, and Pluto will automatically make sure that the right packages are installed. If you import a new package, it will be installed behind the scenes. If you remove the import, then Pluto will uninstall it. 249 | 250 | In the cell below, click the ✔ button next to `using PlutoUI` to learn more about its status. 251 | """ 252 | 253 | # ╔═╡ d8b4d774-258d-4ef8-9bd9-586d19c785d2 254 | md""" 255 | Try importing another package (like `Measurements`): 256 | """ 257 | 258 | # ╔═╡ 4e75b797-dbba-4d2e-843e-4abb0f8de22c 259 | 260 | 261 | # ╔═╡ 4720cedc-502b-4c66-9c4a-98622c87cb04 262 | md""" 263 | ### But that's slow! 264 | 265 | In Julia, packages are always installed globally, while _environments_ (including notebooks) only store **version information**, not the package code itself. This means that multiple notebooks that use the same version of `Plots` will not lead to more disk usage or precompile time. 266 | 267 | This is different from `venv` in Python/pip, or `node_modules` in NodeJS/npm, where every environment contains copies of package code by default. Julia's package manager is designed to work well with many package environments on the same computer. 268 | """ 269 | 270 | # ╔═╡ 74ff3d85-a6f4-4ae4-8502-18cf7a180ac5 271 | md""" 272 | ### Reproducibility 273 | The package manager does some other neat stuff too. As you're probably aware, the good folks maintaining packages will release new versions over time. That's great, but it can cause issues with compatibility. 274 | 275 | Because of this, it can be useful if you've written down somewhere which versions of each package you were using - and if you're running someone else's code, you can avoid errors by using the same versions they used. 276 | 277 | In Pluto all of that happens automatically: your package environment is stored inside the notebook file. When someone else opens your notebook with Pluto, the exact same package environment will be used, and packages will work on their computer. 278 | """ 279 | 280 | # ╔═╡ d3cf365d-ef7e-4a48-a32d-b050e69e5075 281 | md""" 282 | !!! tip 283 | 284 | If you're used to doing your own package management and you don't want Pluto to take over, don't worry! When you use `Pkg.activate(...)` inside a notebook, [the package manager will be disabled](https://github.com/fonsp/Pluto.jl/wiki/%F0%9F%8E%81-Package-management#advanced-set-up-an-environment-with-pkgactivate). 285 | """ 286 | 287 | # ╔═╡ 58761686-b3c8-47f3-b05c-616f34ac71d9 288 | md""" 289 | For more information on this, [read about package management on the Pluto.jl wiki](https://github.com/fonsp/Pluto.jl/wiki/%F0%9F%8E%81-Package-management). 290 | """ 291 | 292 | # ╔═╡ 8bbe13ff-f643-4ed0-aacf-9bafaa7c59c0 293 | md""" 294 | ## Markdown cells 295 | 296 | Unlike Jupyter, Pluto doesn't have text cells or markdown cells. Every cell is just Julia code. However, you can write markdown expressions in Julia, and those will be nicely displayed by Pluto. Like this: 297 | """ 298 | 299 | # ╔═╡ 016f9e48-1672-481e-b642-d0c6bf67a5bc 300 | md""" 301 | This cell contains some **text** in *Markdown*! 302 | """ 303 | 304 | # ╔═╡ 669323ca-aac3-415c-bbfc-14525447ccd8 305 | md""" 306 | !!! tip 307 | 308 | Use `Ctrl + M` in a cell to wrap it in `md""\"` markers! 309 | """ 310 | 311 | # ╔═╡ e99b9c02-a31a-46d9-a5f1-9849c9d3cbe0 312 | md""" 313 | ## Notebook files 314 | 315 | ### Pluto notebooks are scripts 316 | 317 | A neat thing: Pluto notebooks are saved as `.jl` files: they're just Julia scripts! You can send them to Julia programmers that don't use Pluto, and they can run the script just like that. Or you can write your code in a notebook, and then run it on a larger dataset from the command line. 318 | 319 | And just in case you're wondering: Pluto notebook files will save your cells in the order they should be _run_, not the order in which they're displayed. So you can play with the order and still run the code as a script! 320 | 321 | This is quite different from `.ipynb` files, which can only be run with Jupyter. 322 | 323 | There are a few more notable differences in the files: 324 | 325 | ### Pluto notebooks include packages 326 | 327 | As we mentioned, Pluto comes with a built-in package manager, so the notebook file also includes info about package versions. 328 | 329 | ### Pluto notebooks don't include output 330 | 331 | You may already have noticed that the experience of opening a Pluto notebook is a bit different, because it doesn't come with pre-loaded output for each cell. 332 | 333 | This comes with pros and cons: it allows Pluto notebooks to maintain a simpler file, but makes it a bit harder to "preview" a notebook. 334 | 335 | If you want to send someone your notebook _with output_, a good way to do it is as an HTML export (on the top menu) - that file will show all the output you created, and also allow viewers to download the original notebook file. 336 | 337 | ### Version management 338 | 339 | If you work with Git, good news! Pluto notebook files are designed to work well with version management. 340 | 341 | Jupyter notebooks are notorious for creating huge *git diffs* (a git diff is an overview of changes in the file). Jupyter notebooks are easy to read, but their raw files are not. 342 | 343 | By contrast, the changes to a Pluto notebook are much easier to make sense of. Small changes to a notebook will result in small changes to the file. Nice! 344 | """ 345 | 346 | # ╔═╡ e1c813e5-a393-4364-8494-687b98811a0b 347 | md""" 348 | ## Other programming languages 349 | 350 | Jupyter was created to work with Julia, Python, and R (hence the name: JuPyteR), and can even be made compatible with other languages! 351 | 352 | Pluto, however, is only ever going to be Julia environment. The core of Pluto is built in Julia, and Pluto's reactivity works by analysing your code. Jupyter is built to be largely language-agnostic, but Pluto decidedly isn't. 353 | 354 | This comes with pros and cons: Pluto can do some cool stuff because it knows the language you're working in, but it doesn't have the flexibility that Jupyter does. 355 | """ 356 | 357 | # ╔═╡ 40ff93d6-1755-4258-9c15-3ae7be681d93 358 | md""" 359 | ## Wrapping up 360 | 361 | That's it! 362 | 363 | I encourage you to make your own notebooks and play around with Pluto yourself. You can also take a look at Pluto's featured notebooks (on the home page) which show you a bit more of what you can do with Pluto! 364 | """ 365 | 366 | # ╔═╡ c12c3f7d-f91b-4395-9323-52a582a79bc6 367 | greatness = greatness + 10 368 | 369 | # ╔═╡ 5dd0949a-82d1-4b27-8318-9b42065d0957 370 | greatness = greatness * 2 371 | 372 | # ╔═╡ aff0754c-8e3a-4cbc-9697-0797e5d32fc2 373 | greatness = 0 374 | 375 | # ╔═╡ 00000000-0000-0000-0000-000000000001 376 | PLUTO_PROJECT_TOML_CONTENTS = """ 377 | [deps] 378 | PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" 379 | 380 | [compat] 381 | PlutoUI = "~0.7.62" 382 | """ 383 | 384 | # ╔═╡ 00000000-0000-0000-0000-000000000002 385 | PLUTO_MANIFEST_TOML_CONTENTS = """ 386 | # This file is machine-generated - editing it directly is not advised 387 | 388 | [[AbstractPlutoDingetjes]] 389 | deps = ["Pkg"] 390 | git-tree-sha1 = "6e1d2a35f2f90a4bc7c2ed98079b2ba09c35b83a" 391 | uuid = "6e696c72-6542-2067-7265-42206c756150" 392 | version = "1.3.2" 393 | 394 | [[ArgTools]] 395 | uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" 396 | version = "1.1.2" 397 | 398 | [[Artifacts]] 399 | uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" 400 | version = "1.11.0" 401 | 402 | [[Base64]] 403 | uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" 404 | version = "1.11.0" 405 | 406 | [[ColorTypes]] 407 | deps = ["FixedPointNumbers", "Random"] 408 | git-tree-sha1 = "b10d0b65641d57b8b4d5e234446582de5047050d" 409 | uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" 410 | version = "0.11.5" 411 | 412 | [[CompilerSupportLibraries_jll]] 413 | deps = ["Artifacts", "Libdl"] 414 | uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" 415 | version = "1.1.1+0" 416 | 417 | [[Dates]] 418 | deps = ["Printf"] 419 | uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" 420 | version = "1.11.0" 421 | 422 | [[Downloads]] 423 | deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] 424 | uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" 425 | version = "1.6.0" 426 | 427 | [[FileWatching]] 428 | uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" 429 | version = "1.11.0" 430 | 431 | [[FixedPointNumbers]] 432 | deps = ["Statistics"] 433 | git-tree-sha1 = "05882d6995ae5c12bb5f36dd2ed3f61c98cbb172" 434 | uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" 435 | version = "0.8.5" 436 | 437 | [[Hyperscript]] 438 | deps = ["Test"] 439 | git-tree-sha1 = "179267cfa5e712760cd43dcae385d7ea90cc25a4" 440 | uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91" 441 | version = "0.0.5" 442 | 443 | [[HypertextLiteral]] 444 | deps = ["Tricks"] 445 | git-tree-sha1 = "7134810b1afce04bbc1045ca1985fbe81ce17653" 446 | uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" 447 | version = "0.9.5" 448 | 449 | [[IOCapture]] 450 | deps = ["Logging", "Random"] 451 | git-tree-sha1 = "b6d6bfdd7ce25b0f9b2f6b3dd56b2673a66c8770" 452 | uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" 453 | version = "0.2.5" 454 | 455 | [[InteractiveUtils]] 456 | deps = ["Markdown"] 457 | uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" 458 | version = "1.11.0" 459 | 460 | [[JSON]] 461 | deps = ["Dates", "Mmap", "Parsers", "Unicode"] 462 | git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" 463 | uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" 464 | version = "0.21.4" 465 | 466 | [[LibCURL]] 467 | deps = ["LibCURL_jll", "MozillaCACerts_jll"] 468 | uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" 469 | version = "0.6.4" 470 | 471 | [[LibCURL_jll]] 472 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] 473 | uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" 474 | version = "8.6.0+0" 475 | 476 | [[LibGit2]] 477 | deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] 478 | uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" 479 | version = "1.11.0" 480 | 481 | [[LibGit2_jll]] 482 | deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] 483 | uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" 484 | version = "1.7.2+0" 485 | 486 | [[LibSSH2_jll]] 487 | deps = ["Artifacts", "Libdl", "MbedTLS_jll"] 488 | uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" 489 | version = "1.11.0+1" 490 | 491 | [[Libdl]] 492 | uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" 493 | version = "1.11.0" 494 | 495 | [[LinearAlgebra]] 496 | deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] 497 | uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 498 | version = "1.11.0" 499 | 500 | [[Logging]] 501 | uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" 502 | version = "1.11.0" 503 | 504 | [[MIMEs]] 505 | git-tree-sha1 = "c64d943587f7187e751162b3b84445bbbd79f691" 506 | uuid = "6c6e2e6c-3030-632d-7369-2d6c69616d65" 507 | version = "1.1.0" 508 | 509 | [[Markdown]] 510 | deps = ["Base64"] 511 | uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" 512 | version = "1.11.0" 513 | 514 | [[MbedTLS_jll]] 515 | deps = ["Artifacts", "Libdl"] 516 | uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" 517 | version = "2.28.6+0" 518 | 519 | [[Mmap]] 520 | uuid = "a63ad114-7e13-5084-954f-fe012c677804" 521 | version = "1.11.0" 522 | 523 | [[MozillaCACerts_jll]] 524 | uuid = "14a3606d-f60d-562e-9121-12d972cd8159" 525 | version = "2023.12.12" 526 | 527 | [[NetworkOptions]] 528 | uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" 529 | version = "1.2.0" 530 | 531 | [[OpenBLAS_jll]] 532 | deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] 533 | uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" 534 | version = "0.3.27+1" 535 | 536 | [[Parsers]] 537 | deps = ["Dates", "PrecompileTools", "UUIDs"] 538 | git-tree-sha1 = "7d2f8f21da5db6a806faf7b9b292296da42b2810" 539 | uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" 540 | version = "2.8.3" 541 | 542 | [[Pkg]] 543 | deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] 544 | uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" 545 | version = "1.11.0" 546 | 547 | [Pkg.extensions] 548 | REPLExt = "REPL" 549 | 550 | [Pkg.weakdeps] 551 | REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" 552 | 553 | [[PlutoUI]] 554 | deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "FixedPointNumbers", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "MIMEs", "Markdown", "Random", "Reexport", "URIs", "UUIDs"] 555 | git-tree-sha1 = "d3de2694b52a01ce61a036f18ea9c0f61c4a9230" 556 | uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8" 557 | version = "0.7.62" 558 | 559 | [[PrecompileTools]] 560 | deps = ["Preferences"] 561 | git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" 562 | uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" 563 | version = "1.2.1" 564 | 565 | [[Preferences]] 566 | deps = ["TOML"] 567 | git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" 568 | uuid = "21216c6a-2e73-6563-6e65-726566657250" 569 | version = "1.4.3" 570 | 571 | [[Printf]] 572 | deps = ["Unicode"] 573 | uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" 574 | version = "1.11.0" 575 | 576 | [[Random]] 577 | deps = ["SHA"] 578 | uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 579 | version = "1.11.0" 580 | 581 | [[Reexport]] 582 | git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" 583 | uuid = "189a3867-3050-52da-a836-e630ba90ab69" 584 | version = "1.2.2" 585 | 586 | [[SHA]] 587 | uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" 588 | version = "0.7.0" 589 | 590 | [[Serialization]] 591 | uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" 592 | version = "1.11.0" 593 | 594 | [[Statistics]] 595 | deps = ["LinearAlgebra"] 596 | git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0" 597 | uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" 598 | version = "1.11.1" 599 | 600 | [Statistics.extensions] 601 | SparseArraysExt = ["SparseArrays"] 602 | 603 | [Statistics.weakdeps] 604 | SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" 605 | 606 | [[TOML]] 607 | deps = ["Dates"] 608 | uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" 609 | version = "1.0.3" 610 | 611 | [[Tar]] 612 | deps = ["ArgTools", "SHA"] 613 | uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" 614 | version = "1.10.0" 615 | 616 | [[Test]] 617 | deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] 618 | uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" 619 | version = "1.11.0" 620 | 621 | [[Tricks]] 622 | git-tree-sha1 = "6cae795a5a9313bbb4f60683f7263318fc7d1505" 623 | uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" 624 | version = "0.1.10" 625 | 626 | [[URIs]] 627 | git-tree-sha1 = "cbbebadbcc76c5ca1cc4b4f3b0614b3e603b5000" 628 | uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" 629 | version = "1.5.2" 630 | 631 | [[UUIDs]] 632 | deps = ["Random", "SHA"] 633 | uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" 634 | version = "1.11.0" 635 | 636 | [[Unicode]] 637 | uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" 638 | version = "1.11.0" 639 | 640 | [[Zlib_jll]] 641 | deps = ["Libdl"] 642 | uuid = "83775a58-1f1d-513f-b197-d71354ab007a" 643 | version = "1.2.13+1" 644 | 645 | [[libblastrampoline_jll]] 646 | deps = ["Artifacts", "Libdl"] 647 | uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" 648 | version = "5.11.0+0" 649 | 650 | [[nghttp2_jll]] 651 | deps = ["Artifacts", "Libdl"] 652 | uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" 653 | version = "1.59.0+0" 654 | 655 | [[p7zip_jll]] 656 | deps = ["Artifacts", "Libdl"] 657 | uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" 658 | version = "17.4.0+2" 659 | """ 660 | 661 | # ╔═╡ Cell order: 662 | # ╟─cdbcc440-858c-11ee-25d2-dd9d69531eef 663 | # ╟─a423fc4f-6000-4451-bc03-4035c9847753 664 | # ╠═b25c812b-7ec2-4e17-aa1b-e1a1407d29fb 665 | # ╠═8e1faf5f-7b60-4b57-9902-e9d2531f0961 666 | # ╟─03d3ade3-056a-4f16-9b31-d259879082c9 667 | # ╟─1512a488-3d77-4161-9fd0-0ade53e75c34 668 | # ╟─3ed1ed94-8741-48a0-9d23-bb78499eec91 669 | # ╟─773ac617-4e5d-46b9-92ff-b0d9a23e42f1 670 | # ╠═6ba28587-3612-45bb-a5fa-5e1ce8fa3aa6 671 | # ╠═f4d990a8-274a-4098-b4f9-ce1d39ec41a6 672 | # ╟─74a6102a-e09d-4ebb-9ef8-2511b0f46f58 673 | # ╠═807b1586-8b3e-4cb1-9a9d-8ca66a28ec3e 674 | # ╠═3bca136c-115f-4dd1-ac4d-d14c23c538ce 675 | # ╟─2b91d104-921a-4d66-ac1f-a940cdb2d14c 676 | # ╟─3103e636-3f0a-4e16-94f7-3da1a573ec3d 677 | # ╟─0948181e-b26c-421b-83b5-c9dceb71e804 678 | # ╟─9c3cfd5e-b89c-4df2-9982-d581e9fc3730 679 | # ╠═f6e66043-6773-470a-9a07-17283c878d79 680 | # ╟─2a84a64a-b819-4246-8f77-99679691da61 681 | # ╠═3323e930-31be-4b0b-8cf2-71a07a017758 682 | # ╠═c702dde3-6cb4-4444-ab1d-f1db95e6776a 683 | # ╟─b04a791f-7eb9-40eb-9cab-ff38fbc6cca6 684 | # ╠═def86a18-7106-490d-a1f0-c3e48b42b8f6 685 | # ╟─ec2bcfd5-bd38-4801-ac38-2339bc782147 686 | # ╟─1086228a-e28d-45c7-9153-c79378239e54 687 | # ╟─447f49ce-1738-4987-a976-094174971ccb 688 | # ╠═aff0754c-8e3a-4cbc-9697-0797e5d32fc2 689 | # ╠═c12c3f7d-f91b-4395-9323-52a582a79bc6 690 | # ╠═5dd0949a-82d1-4b27-8318-9b42065d0957 691 | # ╟─c4ece2cd-31f4-4c91-a59b-e520de13dedd 692 | # ╟─5200e802-8080-4394-aa85-e2604c7279c8 693 | # ╠═94991d24-6aad-4361-a8e5-5e2c1f15c53c 694 | # ╟─244ca1ba-c2dc-4713-9dd0-57ed0d19ba70 695 | # ╟─4df1d31c-db13-49a1-963b-337550cd2bda 696 | # ╟─a7ea9146-86f6-4d2a-85a3-950f2e7bc102 697 | # ╠═db1ef6d1-7921-4035-8705-a0820048b785 698 | # ╟─d8b4d774-258d-4ef8-9bd9-586d19c785d2 699 | # ╠═4e75b797-dbba-4d2e-843e-4abb0f8de22c 700 | # ╟─4720cedc-502b-4c66-9c4a-98622c87cb04 701 | # ╟─74ff3d85-a6f4-4ae4-8502-18cf7a180ac5 702 | # ╟─d3cf365d-ef7e-4a48-a32d-b050e69e5075 703 | # ╟─58761686-b3c8-47f3-b05c-616f34ac71d9 704 | # ╟─8bbe13ff-f643-4ed0-aacf-9bafaa7c59c0 705 | # ╠═016f9e48-1672-481e-b642-d0c6bf67a5bc 706 | # ╟─669323ca-aac3-415c-bbfc-14525447ccd8 707 | # ╟─e99b9c02-a31a-46d9-a5f1-9849c9d3cbe0 708 | # ╟─e1c813e5-a393-4364-8494-687b98811a0b 709 | # ╟─40ff93d6-1755-4258-9c15-3ae7be681d93 710 | # ╟─00000000-0000-0000-0000-000000000001 711 | # ╟─00000000-0000-0000-0000-000000000002 712 | --------------------------------------------------------------------------------