<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Paul Cochrane 🇪🇺</title>
    <description>The latest articles on DEV Community by Paul Cochrane 🇪🇺 (@peateasea).</description>
    <link>https://dev.to/peateasea</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F476547%2Fd8e90745-f369-497b-84c4-650ce4d8a8ed.jpeg</url>
      <title>DEV Community: Paul Cochrane 🇪🇺</title>
      <link>https://dev.to/peateasea</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/peateasea"/>
    <language>en</language>
    <item>
      <title>Computational physics with Python: tool setup</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Wed, 22 Apr 2026 22:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/computational-physics-with-python-tool-setup-2fi0</link>
      <guid>https://dev.to/peateasea/computational-physics-with-python-tool-setup-2fi0</guid>
      <description>&lt;p&gt;Imagine you want to learn computational physics and Python as an advanced high-school student or undergraduate. Where to start? Assuming no prior programming experience, a quick introduction to programming concepts won’t go amiss. To get to that point, though, you’ll need to prepare some tools first.&lt;/p&gt;

&lt;p&gt;In this post, I describe how to install Python and Visual Studio Code, two tools we need before we can start programming and learning computational physics. I then describe how to configure VS Code to use Python, finishing up by writing a toy Python program and running it within VS Code.&lt;/p&gt;

&lt;p&gt;A high school student that I tutor asked me a while ago if one can learn physics by programming in Python. I answered: “Of course!” Since then, I’ve had all kinds of ideas about how to introduce computational physics and numerical methods to advanced high-school or early-level university students.&lt;/p&gt;

&lt;p&gt;This is the first post in a (long-term) series focusing on numerical methods and computational physics. The intent is to collect enough topics and examples to create a &lt;a href="https://peateasea.de/courses/#learning-computational-physics-with-python" rel="noopener noreferrer"&gt;course in computational physics using Python&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A rough plan
&lt;/h2&gt;

&lt;p&gt;My rough plan is to discuss concepts already taught at school, for which we know the analytical solution. This way, we focus on learning the numerical methods, secure in the knowledge that we have a firm understanding of the mathematics and physical concepts.&lt;/p&gt;

&lt;p&gt;Then we implement the numerical solution in Python and compare it with the analytical one to see how well we did. This reduces cognitive load: we’re not introducing new physics and maths concepts. The only things that are new to us are programming and the relevant numerical methods.&lt;/p&gt;

&lt;p&gt;One long-term goal is to build sufficient understanding of the numerical methods so that we can move out of our comfort zone and learn to solve physical problems where an analytical solution is either unknown or difficult to calculate.&lt;/p&gt;

&lt;p&gt;Before we can really get going, we need to set up our working environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;To run Python programs, we need a working Python development environment. And to create Python programs, we need software in which we can write code. Thus, we need to do some boring administrative work before we can start doing interesting physics and programming stuff.&lt;/p&gt;

&lt;p&gt;This post will focus on getting a Python environment up and running within Visual Studio Code. The following article will introduce some basic programming concepts and show a simple example of using the NumPy and Matplotlib libraries. This foundation will enable us to focus on computational physics topics later.&lt;/p&gt;

&lt;p&gt;The installation guide described here assumes a Windows environment. I made this decision because I assume that most students either use Windows or have access to a Windows computer.&lt;/p&gt;

&lt;p&gt;Some students will have macOS. Unfortunately, I don’t have access to a macOS system. Hence, I can’t describe the installation process in that environment.&lt;/p&gt;

&lt;p&gt;Other students likely use Linux. From personal experience, Linux users are often in the minority. So, even though I would like to describe the process from a Linux perspective, I chose Windows because it is relevant to most students.&lt;sup id="fnref:long-time-unix-user"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;We now focus on installing Python and the Visual Studio Code &lt;a href="https://en.wikipedia.org/wiki/Integrated_development_environment" rel="noopener noreferrer"&gt;integrated development environment&lt;/a&gt; (known simply as VS Code). As you will see below, there’s a lot of setup required before we can get to the fun stuff and start programming. Fortunately, we only have to do this setup once, so it’s worth taking our time to do it properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Python
&lt;/h2&gt;

&lt;p&gt;According to the &lt;a href="https://code.visualstudio.com/docs/python/python-tutorial" rel="noopener noreferrer"&gt;Visual Studio Code tutorial on installing Python&lt;/a&gt;, it’s recommended to install Python first, so we’ll start there. This ensures that Python is available for VS Code to find when we install it later.&lt;/p&gt;

&lt;p&gt;There is also good &lt;a href="https://code.visualstudio.com/docs" rel="noopener noreferrer"&gt;documentation on the VS Code website&lt;/a&gt; for writing and running Python programs. You can find more information under the “Python” link on that site.&lt;/p&gt;

&lt;p&gt;Before installing Python, we have to download it. The best place to get it for Windows is from the Python website. Using a browser, navigate to the &lt;a href="https://www.python.org/downloads/" rel="noopener noreferrer"&gt;Python downloads page&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn67eg9giq2venp9iy0kj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn67eg9giq2venp9iy0kj.png" alt="Python downloads page" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now click on the “Download Python” button to download the most recent version of Python (note that the version number you see will be different to that shown in the screenshot above).&lt;sup id="fnref:python-for-windows-downloads-page"&gt;2&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;After the download has completed, open your &lt;code&gt;Downloads&lt;/code&gt; folder and search for the installer application. It’ll be called something like &lt;code&gt;python-3.15.5-amd64.exe&lt;/code&gt; (where 3.15.5 is the version number and is likely different in your case). You should see an icon which looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7008sczapswc6eh5dq96.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7008sczapswc6eh5dq96.png" alt="Python on Windows installer icon" width="107" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Double-click on the installer icon. You should then see the Python for Windows installer startup dialog box:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy33doz0bwr25o25bi0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy33doz0bwr25o25bi0g.png" alt="Python on Windows installer startup dialog" width="654" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This window has two unchecked options at the bottom. One mentions using admin privileges when installing Python (which we don’t need), and the other mentions adding &lt;code&gt;python.exe&lt;/code&gt; to your &lt;code&gt;PATH&lt;/code&gt;. Your &lt;code&gt;PATH&lt;/code&gt; tells your computer where to look when it wants to find the program to run Python. It’s therefore a good idea to check this option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkm2tk9xyi14q5h064zn5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkm2tk9xyi14q5h064zn5.png" alt="Python on Windows installer with Add python.exe to PATH checkbox checked" width="654" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we’re ready to install Python. Click on the “Install Now” option in the middle of the window. This will install Python and any supporting software it needs.&lt;/p&gt;

&lt;p&gt;Once the installation has completed, you’ll see the “Setup was successful” dialog box appear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq78szsfu1z5auekkcg31.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq78szsfu1z5auekkcg31.png" alt="Python on Windows installer setup successful dialog box" width="654" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the “Close” button to continue.&lt;/p&gt;

&lt;p&gt;Now that Python is installed, we’re ready to install Visual Studio Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Visual Studio Code
&lt;/h2&gt;

&lt;p&gt;One thing to note first: Visual Studio Code is &lt;em&gt;not&lt;/em&gt; Visual Studio; they’re different things. Yes, Visual Studio is also an IDE.&lt;sup id="fnref:ide"&gt;3&lt;/sup&gt; Yes, it’s a product from the same company. Yes, this is confusing. Sorry about that.&lt;/p&gt;

&lt;p&gt;Go to the &lt;a href="https://code.visualstudio.com/Download" rel="noopener noreferrer"&gt;Visual Studio Code download page&lt;/a&gt; and choose an installer appropriate for your operating system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnayegrj5ph998ro8lb1o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnayegrj5ph998ro8lb1o.png" alt="VS Code downloads page" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because we’re using Windows, click on the “Windows” button to download the installer application. This will download a file called &lt;code&gt;VSCodeUserSetup-x64-1.101.2.exe&lt;/code&gt; (the &lt;code&gt;1.101.2&lt;/code&gt; part is the version number; it’ll be different for you).&lt;/p&gt;

&lt;p&gt;Open your &lt;code&gt;Downloads&lt;/code&gt; folder and double-click on the &lt;code&gt;.exe&lt;/code&gt; file’s icon:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fih3wh58bsfs9zlgotfkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fih3wh58bsfs9zlgotfkw.png" alt="VS Code installer icon" width="107" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will start the VS Code installer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvy9yq7y9za7kolcrjvk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvy9yq7y9za7kolcrjvk.png" alt="VS Code license agreement dialog box" width="596" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To continue, we have to click on “I accept the agreement”. This way, the “Next” button becomes active.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj8jni0ev7pz0w7xrgcu5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj8jni0ev7pz0w7xrgcu5.png" alt="VS Code license agreement dialog box with license accepted" width="596" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the “Next” button. You’ll see a window asking you to choose a destination location.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexfjn1iimqcqru5qgb68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexfjn1iimqcqru5qgb68.png" alt="VS Code installer with select destination location dialog" width="596" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The default option should be good enough, so click on “Next” in this window. A dialog box will appear, asking you if you want a Start Menu folder entry for Visual Studio Code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepmfyrepvo9mbef1uigk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepmfyrepvo9mbef1uigk.png" alt="VS Code installer start menu folder dialog" width="596" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is handy to have, so click on “Next” to continue.&lt;/p&gt;

&lt;p&gt;The following dialog box asks which additional tasks the installer should perform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0fsu24awykgtt239fhu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0fsu24awykgtt239fhu.png" alt="VS Code installer additional tasks dialog" width="596" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One option you might want to select, which isn’t one of the default options, is to add a desktop icon. If you want that, go for it, and click on the “Create a desktop icon” checkbox. In this case, I chose not to do this and simply clicked on “Next”.&lt;/p&gt;

&lt;p&gt;You’re now presented with an overview of what will be installed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh2gnd4ey34215rzxfbp7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh2gnd4ey34215rzxfbp7.png" alt="VS Code installer ready to install dialog" width="596" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on “Install” to install Visual Studio Code. The installation will now start.&lt;/p&gt;

&lt;p&gt;You should see that the installation completed successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftn3flhakwd1lolr71vlt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftn3flhakwd1lolr71vlt.png" alt="VS Code installer finish installation dialog" width="596" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The dialog box has a checkbox to ask if you want to launch Visual Studio Code. This is a good idea, so click on “Finish” to complete the installation and start the IDE.&lt;sup id="fnref:ide:1"&gt;3&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The VS Code start page will then appear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukyzjw1mg67o7emybox5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukyzjw1mg67o7emybox5.png" alt="VS Code start page" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You could take the walkthrough setup of VS Code at this stage, if you want. We’ll skip that, though, and start installing the extensions we need to get Python up and running within VS Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing the Python VS Code extension
&lt;/h2&gt;

&lt;p&gt;The next task is to install the Python VS Code extension. This allows us to develop and run Python programs within the VS Code IDE.&lt;/p&gt;

&lt;p&gt;To see a list of available extensions, you could either click on the extensions icon from the toolbar on the left-hand side of the page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6olqp3uw6pfymsjv3gro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6olqp3uw6pfymsjv3gro.png" alt="VS Code extensions icon" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;or click on the settings icon (the cog symbol at the bottom left of the page) and select the Extensions menu option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxhiitbsru5ljjqvgsvi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foxhiitbsru5ljjqvgsvi.png" alt="VS Code extensions menu via settings icon" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Either way, you’ll see a list of extensions populated in the left-hand frame in VS Code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr32e7lv8maqxiuhgswub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr32e7lv8maqxiuhgswub.png" alt="VS Code extensions list" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fortunately for us, Python appears as one of the recommended extensions at the top of the list. If it weren’t, we could have searched for it in the search box above the list of extensions.&lt;/p&gt;

&lt;p&gt;To install the Python extension, click on its “Install” button. If you look carefully, you’ll see that VS Code also installs the Pylance and Python Debugger extensions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr12ucjlvpq1divvfuvgi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr12ucjlvpq1divvfuvgi.png" alt="VS Code installing the Python extension" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the Python extension has been installed, you’ll see a help page for getting started with Python development:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i7m820b56de129rstsh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i7m820b56de129rstsh.png" alt="VS Code showing Getting Started with Python Development steps" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we’re ready to set up a project, which will contain the computational physics topics we’re going to investigate as part of this course.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the project folder
&lt;/h2&gt;

&lt;p&gt;Our next goal is to write a simple Python program. Again, there’s some setup we have to do before we can do that. Such is life when starting at the very beginning. Don’t worry, we’ll soon have enough foundation that we won’t have to spend any time on setup.&lt;/p&gt;

&lt;p&gt;In software development, which is part of what we’re doing here, one often collects related files together into a &lt;em&gt;project&lt;/em&gt;. This is an organisational structure that keeps related things together; things that share a similar topic or theme. In theory, you could put all files from all projects into your user directory. And yes, I’ve seen people who work like that. However, you’ll find that over time, as you write more and more code, things get hard to find. Such chaos slows you down and makes your life harder. Hence, it’s a good idea to bundle code into projects and–as necessary–into subfolders to keep things organised.&lt;/p&gt;

&lt;p&gt;The top-level organisational unit we have is the overarching topic of computational physics. Thus, we’ll create a &lt;em&gt;project folder&lt;/em&gt; in VS Code for this topic. Subtopics live in their own folders within the main project folder. The main project folder will also contain the environment we need to run Python programs.&lt;/p&gt;

&lt;p&gt;There are two ways to create a project folder. We can either click on the “File” menu and choose the “Open Folder…” option, or we can click on the “Open Project Folder” button from the “Get Started with Python Development” page. For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9tjicpn5o2gnsls99m5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9tjicpn5o2gnsls99m5.png" alt="VS Code open folder menu" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ll choose the second option, because it’s a single click. Clicking on the “Open Project Folder” button in the middle of the page will open the “Open Folder” system dialog.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4a2ziztt0od2vs8uior3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4a2ziztt0od2vs8uior3.png" alt="VS Code open folder dialog" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The issue right now is that we don’t have a prior project folder we want to open: we’ve got to create a new one. To do this, click on the “New folder” button at the top left of the “Open Folder” dialog box.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favck8nudfo394dpnxxkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favck8nudfo394dpnxxkw.png" alt="VS Code new folder created" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This created a new folder in the current directory. You should see that the folder’s name (“New folder”) is highlighted and thus ready for us to rename. Let’s call this folder &lt;code&gt;ComputationalPhysics&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpt1dc52jzbaar21uwvat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpt1dc52jzbaar21uwvat.png" alt="VS Code rename folder to computational physics" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the “Select Folder” button at the bottom right to select it as our project folder for use in VS Code.&lt;/p&gt;

&lt;p&gt;VS Code will now open the project folder. But first, it will ask you if you trust the authors of the files in this folder. Since you yourself are the author, you can click on the “Yes, I trust the authors” button. Assuming, of course, that you trust yourself. 😉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxl9vecw4gck48tvxb3p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxl9vecw4gck48tvxb3p.png" alt="VS Code trust authors of project folder" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Python virtual environment
&lt;/h2&gt;

&lt;p&gt;Theoretically, we’re ready to create a simple Python program and start playing. However, later we want to install some external Python libraries (i.e. libraries that aren’t distributed as part of Python itself) so that we can define and plot data. Thus, we need to set up a &lt;a href="https://docs.python.org/3/library/venv.html" rel="noopener noreferrer"&gt;virtual environment&lt;/a&gt; which will contain these extra libraries.&lt;/p&gt;

&lt;p&gt;Setting up a virtual environment is a good idea when writing Python programs. It allows you to keep the extra libraries you install separate from any other Python software you might have, thus avoiding conflicts between libraries with different versions.&lt;/p&gt;

&lt;p&gt;Conflicts between different library versions can arise surprisingly easily. Hence, it’s useful to isolate software libraries within their own project context. Our computational physics project is one instance of such a context. Were we to install a library in a global context (i.e. where the library could be used across multiple projects), it’s possible for different projects to need different library versions.&lt;/p&gt;

&lt;p&gt;For instance, let’s say program &lt;code&gt;blah&lt;/code&gt; needs version 5.2 of a library called &lt;code&gt;buzz&lt;/code&gt;, but program &lt;code&gt;foo&lt;/code&gt; needs version 3.7 of that same library. It’s not possible to satisfy both requirements had we installed &lt;code&gt;buzz&lt;/code&gt; at a global level. But using a virtual environment allows us to keep things isolated. Thus, if programs &lt;code&gt;blah&lt;/code&gt; and &lt;code&gt;foo&lt;/code&gt; each use their own virtual environment, we can install the appropriate &lt;code&gt;buzz&lt;/code&gt; version for each program and avoid conflict.&lt;/p&gt;

&lt;p&gt;There are a few ways to set up a virtual environment in VS Code.&lt;/p&gt;

&lt;p&gt;One way to do this is to go to the “View” menu and select the “Command Palette…” option:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlifmq7xmzk873p7rrs3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlifmq7xmzk873p7rrs3.png" alt="VS Code view command palette" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will see a list of items in a drop-down menu at the top of the screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrn0hrbcclo3hj76qdu5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrn0hrbcclo3hj76qdu5.png" alt="VS Code command palette options list" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can either type “Python: Create Environment” into the box at the top:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frifr0m0djkqggmwqxqj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frifr0m0djkqggmwqxqj4.png" alt="VS Code Python create environment in command palette" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;or scroll down the (very) long list of options until you see the “Python: Create Environment…” option. Either way, click on this option now to create your Python environment.&lt;/p&gt;

&lt;p&gt;Another way to do this is to click in the box at the top middle of the screen containing a magnifying glass icon and the name of our project folder, &lt;code&gt;ComputationalPhysics&lt;/code&gt;. Clicking here will bring up a menu including the option “Show and Run Commands”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F34uc4n4ao4isgvel4q2n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F34uc4n4ao4isgvel4q2n.png" alt="VS Code search box options" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assuming that the “Get Started with Python Development” window is still available, click on the “Select or create a Python environment” option and then click on the “Create Environment” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfufhfrax2t1z85nq1s2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfufhfrax2t1z85nq1s2.png" alt="VS Code create Python environment from first steps" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;VS Code will ask us what type of environment we want to create.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffyriozo6c8qvogcm8ze6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffyriozo6c8qvogcm8ze6.png" alt="VS Code select virtual environment type" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since we aren’t using &lt;a href="https://anaconda.org/" rel="noopener noreferrer"&gt;Anaconda&lt;/a&gt;, we only want to use the standard Python &lt;a href="https://docs.python.org/3/library/venv.html" rel="noopener noreferrer"&gt;virtual environment&lt;/a&gt;, so click on the “Venv” option. This will create a folder within our project folder with the name &lt;code&gt;.venv&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;VS Code now asks us which Python installation we want to use in our virtual environment. If you’ve installed multiple versions of Python, you’ll see several options in the drop-down list that now appears. In our case, we’ve only installed the one Python version, so we only see one version appear:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovco4m6ib25l5zelvvkd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovco4m6ib25l5zelvvkd.png" alt="VS Code select Python installation" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Selecting the Python installation will create the Python environment. You’ll see an info box in the bottom right-hand part of the window telling you about this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay37h1evhxa1mv1nr498.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay37h1evhxa1mv1nr498.png" alt="VS Code creating virtual environment" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a new Python file
&lt;/h2&gt;

&lt;p&gt;To make sure that everything works as expected, let’s create a simple Python file to check. Usually, you create new files by going to the “File” menu and selecting the “New Text File” option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc7w70w2n8473e339iv8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc7w70w2n8473e339iv8w.png" alt="VS Code New Text file menu option" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, because we’re just getting started, we click on the “Create a Python file” step from the “Get Started with Python Development” window:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqr8h53662n3vj4x6klr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqr8h53662n3vj4x6klr.png" alt="VS Code Create Python File from first steps" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Doing so will open a Python file called &lt;code&gt;Untitled-1&lt;/code&gt; in a tab next to the “Welcome” tab containing the “Get Started with Python Development” stuff.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1j70sqgt2mjaafx0jp61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1j70sqgt2mjaafx0jp61.png" alt="VS Code new Python file next to Welcome tab" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that if you open a new file via the “File” menu, you’ll only see the new file in a tab and the “Welcome” tab will be hidden.&lt;/p&gt;

&lt;h2&gt;
  
  
  A personal statistics program
&lt;/h2&gt;

&lt;p&gt;We’re now going to create a small program which asks you some questions and prints back that information in a slightly different form. It’s not very interesting, but it allows us to see that the Python environment is working, and we can start some basic programming.&lt;/p&gt;

&lt;p&gt;Click in the tab named &lt;code&gt;Untitled-1&lt;/code&gt; and enter the following text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s your name? &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s your age (in years)? &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s your height (in m)? &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;! You are &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; years old and &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; m tall.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to save this file before you can run it. You save files by either selecting the “File” menu and then the “Save” option:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpeus6loqali0tsonrkl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpeus6loqali0tsonrkl.png" alt="VS Code Save menu option" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;or you could use the key combination &lt;code&gt;Ctrl+S&lt;/code&gt;. This means you press the control key (labelled &lt;code&gt;Ctrl&lt;/code&gt; on your keyboard) together with the &lt;code&gt;s&lt;/code&gt; key.&lt;/p&gt;

&lt;p&gt;Either way, you’ll see a dialog box to save the file as a certain name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F224h1r2ag3s1x81yrvr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F224h1r2ag3s1x81yrvr9.png" alt="VS Code Save As dialog box" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the “File name:” field at the bottom, where the text “Untitled-1” is highlighted, enter the name &lt;code&gt;print-personal-stats.py&lt;/code&gt;. Then click on the “Save” button in the bottom right-hand corner.&lt;/p&gt;

&lt;p&gt;Now we’re ready to run the file. At the top right of the VS Code tab with our Python code in it, there’s a small triangle which looks like the symbol for “Play”. If you hover your mouse over this triangle, you’ll see the text “Run Python File”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuffjdv0nb1gxyolca0ps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuffjdv0nb1gxyolca0ps.png" alt="VS Code Run Python File icon" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the triangle to run the file.&lt;/p&gt;

&lt;p&gt;You will see a new window appear in VS Code. This is your &lt;a href="https://en.wikipedia.org/wiki/Computer_terminal" rel="noopener noreferrer"&gt;terminal&lt;/a&gt; window where your program runs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fej3ilu2s6ocgjzg3on0f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fej3ilu2s6ocgjzg3on0f.png" alt="VS Code terminal window, stats program started" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll also notice that your program has started, and it’s already asking you a question. To enter text into the terminal, you have to click in its area at the bottom of your VS Code window to focus it. This will allow you to interact with your running program. A cursor (a small white rectangle) will appear where you can now start entering information.&lt;/p&gt;

&lt;p&gt;As an example, enter the following information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When asked for the name, enter: &lt;code&gt;Alice&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;When asked for the age, enter: &lt;code&gt;42&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;When asked for the height, enter: &lt;code&gt;1.57&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After typing each piece of information, press the “Enter” key to pass it to the program. You should see output like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dw60mvlv7q21aculoq4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dw60mvlv7q21aculoq4.png" alt="VS Code terminal window, stats program input and output" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You’ve run your first Python program in VS Code!&lt;/p&gt;

&lt;p&gt;We’ve fulfilled a large number of the first steps listed in the “Get Started with Python Development” welcome tab, and we’re able to continue with confidence. We can close this tab and free up some room in the VS Code window.&lt;/p&gt;

&lt;p&gt;Close the “Welcome” tab by clicking on the small “x” next to the word “Welcome”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6wpjocbab6012gpypboy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6wpjocbab6012gpypboy.png" alt="VS Code close Welcome tab" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That gave us a lot more room to see our code. Nice!&lt;/p&gt;

&lt;h2&gt;
  
  
  More next time
&lt;/h2&gt;

&lt;p&gt;That will do for this time. We’ve come quite far in getting everything we need up and running. &lt;a href="https://peateasea.de/learning-computational-physics-with-python-programming-basics/" rel="noopener noreferrer"&gt;Next time&lt;/a&gt;, we’ll discuss the Python code in detail, talking about programming concepts such as variables, assignment, and data types.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;As a long-time Unix and Linux user, this does break my heart a bit. However, I have to realise that Windows is the most common environment for students in the wild and adapt to that. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Note that you &lt;em&gt;could&lt;/em&gt; go to the Python for Windows downloads page. But it turns out to be easier to click on the “Download Python” button on the main downloads page. If you’re on Windows, it will detect that and will provide you with a direct link to download Python. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IDE stands for &lt;a href="https://en.wikipedia.org/wiki/Integrated_development_environment" rel="noopener noreferrer"&gt;Integrated Development Environment&lt;/a&gt;. This is a term for a very powerful code editor packed with lots of functionality that makes editing and running code very easy. You could use something simpler, such as &lt;a href="https://www.vim.org/" rel="noopener noreferrer"&gt;vim&lt;/a&gt; or&lt;a href="https://www.gnu.org/software/emacs/emacs.html" rel="noopener noreferrer"&gt;Emacs&lt;/a&gt;, to write Python code, and many people do. IDEs such as VS Code are very prevalent in software development circles. ↩ ↩&lt;sup&gt;2&lt;/sup&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>physics</category>
      <category>maths</category>
      <category>python</category>
    </item>
    <item>
      <title>I think the bots don’t like me anymore</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Wed, 15 Apr 2026 22:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/i-think-the-bots-dont-like-me-anymore-3l6c</link>
      <guid>https://dev.to/peateasea/i-think-the-bots-dont-like-me-anymore-3l6c</guid>
      <description>&lt;p&gt;After about five months of AI bots hungrily munching on my blog’s free training data, they seem to have abruptly stopped. It’s a good sign, but given they seem to be hammering most other sites on the web, it’s somewhat odd. Here, I have a quick look at the numbers to see what’s been happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rising views
&lt;/h2&gt;

&lt;p&gt;Although &lt;a href="https://dev.to/weaning-website-off-cookies/"&gt;I removed analytics collection from my blog years ago&lt;/a&gt;, Hetzner (where my blog is hosted) generates basic statistics from their web server logs,&lt;sup id="fnref:hetzner-awstats"&gt;1&lt;/sup&gt; and sometimes I have a nosey to see if anything interesting is happening. Stats derived from these web server logs have limited information content, which is how I like it. This way, I get rough information about site visits while not tracking anyone.&lt;/p&gt;

&lt;p&gt;Late last year, I noticed an upwards trend in the number of hits to my blog. I observed that there were many more hits than usual and that the number rose steadily over the following few months. At the end of the year, I wasn’t surprised to see names in the “Robots/Spiders” section from a well-known AI company. I thought to myself, “Oh ok, that’s just a horde of AI bots sucking data from my blog, much like they’re doing to everyone else”. In other words, “Move along. Nothing to see here. This is the new normal”. Not having the time to investigate further or take any mitigating measures, I carried on with my life.&lt;/p&gt;

&lt;h2&gt;
  
  
  A sudden drop
&lt;/h2&gt;

&lt;p&gt;That was the situation until late March, when the numbers returned to “normal” levels. For my tiny site, it’s quite the drop-off. You can see numbers begin their decline from the 19th until the 24th of March:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgjeetnhj0v1xzp5ejuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgjeetnhj0v1xzp5ejuy.png" alt="Hits per day statistics from March 2026" width="800" height="755"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I mean, say what? Don’t the bots like my yummy free training data anymore?&lt;/p&gt;

&lt;p&gt;To be honest, I don’t have an explanation for the behaviour, but I thought it’d be fun to dig into the numbers a little and see what’s happening. I’m wondering if the trend will continue into April and the rest of the year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Xmas lift-off
&lt;/h2&gt;

&lt;p&gt;Anyway, the story begins in earnest in December last year, when I happened to notice a jump in the number of visits to my blog. To some degree, that can be a flattering indicator: people like my articles! Yay!&lt;/p&gt;

&lt;p&gt;Look at the number of different visitors (“Unterschiedliche Besucher”) ramping up over the course of 2025:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqp5wdos03rted387kszc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqp5wdos03rted387kszc.png" alt="Monthly hits statistics over 2025" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, at the end of December,&lt;sup id="fnref:xmas-bot-break"&gt;2&lt;/sup&gt; the hits per day stats (“Anzahl der Besuche”) reached a high level&lt;sup id="fnref:high-is-relative"&gt;3&lt;/sup&gt; (~1,700 hits per day),&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qz4hv34kumehnvpc3ji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qz4hv34kumehnvpc3ji.png" alt="Hits per day statistics from December 2025" width="800" height="757"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;eventually touching the 3,000 hits per day mark later, in March 2026.&lt;/p&gt;

&lt;p&gt;Unfortunately, a quick look at other data from December 2025 showed lots of hits from bots:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymun7h1acw6u93ccv57c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymun7h1acw6u93ccv57c.png" alt="Robots statistics from December 2025" width="800" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That was somewhat deflating. Ok, my articles &lt;em&gt;aren’t&lt;/em&gt; being read by humans and &lt;em&gt;aren’t&lt;/em&gt; that useful to people. 😕 Instead, bots are gobbling them up and are (probably) dishing them up in a mangled form in someone’s search results. That’s quite the bummer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hitting the categories for no good reason
&lt;/h2&gt;

&lt;p&gt;Digging into the stats a little more, it turned out that the daily bot-snacking began in roughly October 2025. Yet, definitive evidence only turned up in the “Robots/Spiders” stats later.&lt;/p&gt;

&lt;p&gt;What gave their presence away? Well, the “categories” page was being downloaded so often that it appeared in the list of top 10 pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu5jr5mtef1na8czxtmo1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu5jr5mtef1na8czxtmo1.png" alt="Top 10 pages statistics from October 2025" width="800" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, the “categories” page is a pretty bloody boring page. It’s not something a human is going to look at much, and hence, this page shouldn’t appear in the top 10 list. I mean, it’s not often you want to know what categories some blogger uses on their page, right?&lt;/p&gt;

&lt;p&gt;From October 2025 onwards, the numbers start to become very weird, at least if one expects the traffic to be coming from humans. To get a feel for what I mean, consider that in September 2025, the “categories” page didn’t appear in the top 10. In October, it suddenly appeared at the fourth position in the top 10 pages with 499 hits. That was the first sign that something odd was happening. In November, it was 700 hits. Then, in the following months, 17,538, 34,798, and 32,631 hits respectively, reaching 39,997 hits in March 2026.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdq5h1mdpvppcx7o2gwf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdq5h1mdpvppcx7o2gwf.png" alt="Top 10 pages statistics from March 2026" width="800" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like, WTAF? Just why??? Why don’t they hit the other pages as well?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx4egnfsbfo2xd2wvtypi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx4egnfsbfo2xd2wvtypi.jpg" alt="Jackie Chan with hands on his head going WTF" width="494" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Maybe they are. But why hammer the &lt;em&gt;categories&lt;/em&gt; page?&lt;/p&gt;

&lt;p&gt;It’s difficult to know how many of the hits to the remaining pages are from actual human beings, if at all. After all, it’s nice to know if an article has been popular. This gives me an indication of the kinds of posts that are useful and/or interesting to people. If some topic resonates, then I can consider writing more along such lines in the future.&lt;/p&gt;

&lt;p&gt;The stats for the top 10 countries tell a similar story. For instance, the United States had ~8,000 hits and ~700 MB, respectively, in September 2025. These stats jump to ~24,500 hits and 5.6 GB in December, achieving ~50,000 hits and 12 GB in March 2026. That’s pretty nuts for such a small site, and it washes out any useful signal that might be in the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Direct AI bot evidence
&lt;/h2&gt;

&lt;p&gt;The first direct evidence of AI bots scraping the site appeared in the “Robots/Spiders” stats in November 2025, even if the site was already being regularly scraped before then.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwss8a1lxs3zon0xkpkz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwss8a1lxs3zon0xkpkz1.png" width="800" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s when the bot names &lt;code&gt;ChatGPT-User (OpenAI)&lt;/code&gt; and &lt;code&gt;OAI-SearchBot&lt;br&gt;
(OpenAI)&lt;/code&gt; appeared in the top 10 list. From January onwards, they were the top two, which was the same month that Google’s crawler got pushed off the top 10 list. I find it amazing that Google’s bot got shouldered out of the top 10. Did Google’s bots get more efficient and hence no longer need to access the site as often? No idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  More questions than answers
&lt;/h2&gt;

&lt;p&gt;Anyway, it seems the bots have now lost interest to a certain degree. Which is good, I guess. But it does leave me wondering why. Has someone realised that it’s not necessary to poll the site many tens of thousands of times a month when I only post weekly? I don’t reckon. Have they run out of money? Not likely.&lt;/p&gt;

&lt;p&gt;I’ve wondered if the drop off is due to some kind of measure implemented by Hetzner to protect small sites like mine. I couldn’t find anything in the Hetzner docs about such measures, so that reason seem improbable right now. It’s hard to know the actual cause for the drop in traffic and the sudden bot disinterest.&lt;/p&gt;

&lt;p&gt;I enjoy sharing what I know and things I’ve learned with others. Thus, I sometimes wonder if an increase in visits comes from more people finding the articles appealing. That would be great! After all, I write articles because some problem or topic was interesting to me, hence I’d like to think what I’ve written is also of interest or is useful to others. But with &lt;em&gt;so&lt;/em&gt; much “attention” coming from the AI bots, there’s no way to tell how many hits are coming from real human beings. The stats have (or, at least, had) become, for all practical purposes, worthless.&lt;/p&gt;

&lt;p&gt;Perhaps now that the bots have lost interest, the numbers will one day reflect actual human usage and hence actual value for people. I’ll have to wait a while to find out.&lt;/p&gt;

&lt;p&gt;I’m curious to see if the bots leave me alone long-term. That would be nice. Time will tell!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Hetzner uses &lt;a href="https://www.awstats.org/" rel="noopener noreferrer"&gt;AWStats&lt;/a&gt; and ReportMagic to generate traffic statistics from the Apache logs of simple static sites. In this article, I’ve focused only on the AWStats output. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Oddly enough, this happened on Boxing Day after very little activity on Christmas Eve and Christmas Day. Do AI bots take a break for Christmas? ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I say “high”, but to be honest, this is relative. 1,700 hits a day is nothing for many sites. But when 300-400 hits per day is the norm, this is quite the difference. ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>general</category>
    </item>
    <item>
      <title>Building LaTeX documents on GitHub</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Wed, 08 Apr 2026 22:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/building-latex-documents-on-github-525e</link>
      <guid>https://dev.to/peateasea/building-latex-documents-on-github-525e</guid>
      <description>&lt;p&gt;Do you have LaTeX projects on GitHub? Ever wondered how to get GitHub to build them automatically? Here’s how I do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A geeky workflow for LaTeX documents
&lt;/h2&gt;

&lt;p&gt;I’m a geek. More precisely, I’m a physicist. So I’m probably even geekier than your standard geek.&lt;/p&gt;

&lt;p&gt;Now, when physicists write documents, such as papers, letters, or slides for talks, they tend to use &lt;a href="https://www.latex-project.org/" rel="noopener noreferrer"&gt;LaTeX&lt;/a&gt;. I’m no exception. After all, the layout is automatic, the mathematics looks &lt;em&gt;great&lt;/em&gt;, and I get to write code to construct my documents. What’s there not to like?&lt;/p&gt;

&lt;p&gt;When creating the slides for &lt;a href="https://peateasea.de/talks/" rel="noopener noreferrer"&gt;my talks&lt;/a&gt;, I use the &lt;a href="https://ctan.org/pkg/beamer" rel="noopener noreferrer"&gt;&lt;code&gt;beamer&lt;/code&gt;&lt;/a&gt; class. It’s become the standard these days when writing talks in LaTeX.&lt;sup id="fnref:prosper-and-foiltex"&gt;1&lt;/sup&gt; Of course, because LaTeX is code, I put my work into Git and push it to an online Git service such as GitLab or GitHub. When using &lt;a href="https://dev.to/konstruktoid/konstruktoid-deleted-branch-renovatestep-security-harden-runner-2x-at-konstruktoidtymely-4g6h-temp-slug-892592"&gt;GitHub&lt;/a&gt;, I build the document using a &lt;a href="https://docs.github.com/en/actions" rel="noopener noreferrer"&gt;GitHub Actions workflow&lt;/a&gt;. This way, the document builds in a “pristine” environment, and helps me spot issues that might not be obvious when working only on my development system.&lt;/p&gt;

&lt;h2&gt;
  
  
  A version lag in Ubuntu’s TeXLive packages
&lt;/h2&gt;

&lt;p&gt;In one recent project, I was building the slides on GitHub by installing the standard Ubuntu &lt;a href="https://tug.org/texlive/" rel="noopener noreferrer"&gt;TeXLive&lt;/a&gt; LaTeX packages and then running &lt;code&gt;latexmk&lt;/code&gt;. The problem here is that the Ubuntu LaTeX packages aren’t as up to date as one might like them to be. On GitHub, using for instance the &lt;code&gt;ubuntu-22.04&lt;/code&gt; Docker image,&lt;sup id="fnref:ubuntu-latest"&gt;2&lt;/sup&gt; one has access to a TeXLive version from 2021. That’s somewhat … old. I needed a recent TeXLive distribution.&lt;/p&gt;

&lt;p&gt;But how best to get a recent TeXLive? Starting from a stock Ubuntu image and then installing TeXLive is a no-goer, as anyone who has installed a full TeXLive distribution will know. This process can potentially take hours only to download the individual TeXLive packages. That definitely won’t work in a GitHub-CI build: the process will time out before any document has been built. Also, getting feedback on broken builds would take forever, thus reducing the usefulness of building the project on GitHub.&lt;/p&gt;

&lt;p&gt;Another possibility would be to use either the small or medium TeXLive distribution, installing any missing packages as necessary. This would be a lot of work trying to find out which packages are missing. I’d have to update the CI config, wait for a build to run (which involves a long installation step, so it takes a while), see if the build fails, read the log output to find the missing package, add it to the CI config, and try everything again. Future package additions to the document would also make the build fail if I’m not vigilant in keeping the CI config up to date. Not an optimal situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  A LaTeX-specific GitHub action
&lt;/h2&gt;

&lt;p&gt;&lt;a href="///assets/images/surely-you-cant-be-serious.gif"&gt;Surely&lt;/a&gt; there’s a better way? Yes, there is. Introducing the &lt;a href="https://github.com/xu-cheng/latex-action" rel="noopener noreferrer"&gt;&lt;code&gt;latex-action&lt;/code&gt;&lt;/a&gt; GitHub action. It’s a&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[…] GitHub Action that compiles LaTeX documents to PDF using a complete TeXLive environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s just what we’re after!&lt;/p&gt;

&lt;p&gt;The action provides many TeXLive versions to choose from, from 2020 up to the latest version as of writing, 2025. You can also choose between Alpine or Debian Linux as the base image, giving you some flexibility about what other software you might want to install. There are other options available to handle paths, compilation settings, etc. Check out &lt;a href="https://github.com/xu-cheng/latex-action" rel="noopener noreferrer"&gt;the action’s documentation&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;Sounds great! Let’s begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  A worked example
&lt;/h2&gt;

&lt;p&gt;Using a simple example for illustration, I’ll first describe how to build a LaTeX document within a GitHub workflow using the stock Ubuntu images. Then I’ll show how to migrate to a workflow using the &lt;code&gt;latex-action&lt;/code&gt; action.&lt;/p&gt;

&lt;p&gt;We’ll construct a short beamer document that’s got a couple of slides in it with just enough complexity to make it a bit interesting. For those who are interested, the document introduces the basics of the &lt;a href="https://en.wikipedia.org/wiki/Discrete_Fourier_transform" rel="noopener noreferrer"&gt;discrete Fourier transform&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the document locally
&lt;/h3&gt;

&lt;p&gt;Imagine we have a local Git repository called &lt;code&gt;discrete-fourier-transform&lt;/code&gt; with a file containing the following LaTeX code:&lt;sup id="fnref:dorotea-avra"&gt;3&lt;/sup&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="na"&gt;[t,aspectratio=169]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;beamer&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usetheme&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;metropolis&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;\title&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Briefly introducing the discrete Fourier transform&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\author&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Dorotea Avra&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;\begin{document}&lt;/span&gt;

&lt;span class="k"&gt;\maketitle&lt;/span&gt;

&lt;span class="nt"&gt;\begin{frame}&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Background&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;\begin{itemize}&lt;/span&gt;
        &lt;span class="k"&gt;\item&lt;/span&gt; From Wikipedia:&lt;span class="k"&gt;\footnote&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\url&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;https://en.wikipedia.org/wiki/Discrete&lt;span class="p"&gt;_&lt;/span&gt;Fourier&lt;span class="p"&gt;_&lt;/span&gt;transform&lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="nt"&gt;\end{itemize}&lt;/span&gt;
    &lt;span class="nt"&gt;\begin{quotation}&lt;/span&gt;
        the discrete Fourier transform is a discrete version of the Fourier
        transform that converts a finite sequence of equally-spaced samples of a
        function to a same-length sequence of equally spaced samples of the
        discrete-time Fourier transform [&lt;span class="k"&gt;\ldots&lt;/span&gt;].
    &lt;span class="nt"&gt;\end{quotation}&lt;/span&gt;
&lt;span class="nt"&gt;\end{frame}&lt;/span&gt;

&lt;span class="nt"&gt;\begin{frame}&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Background&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;\begin{itemize}&lt;/span&gt;
        &lt;span class="k"&gt;\item&lt;/span&gt; If data sets contain periodic oscillations, one can analyse
            them with ``spectral methods'', a.k.a. ``Fourier transform
            methods''.
        &lt;span class="k"&gt;\item&lt;/span&gt; Sometimes it is easier or more useful to analyse and process
            data in the frequency domain than it is in the time domain.
        &lt;span class="k"&gt;\item&lt;/span&gt; The discrete Fourier transform is a numerical method to
            calculate the Fourier transform of a data set on a computer.
    &lt;span class="nt"&gt;\end{itemize}&lt;/span&gt;
&lt;span class="nt"&gt;\end{frame}&lt;/span&gt;

&lt;span class="nt"&gt;\begin{frame}&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Discrete Fourier transformation definition&lt;span class="p"&gt;}&lt;/span&gt;
    Consider a vector of &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;N&lt;/span&gt;&lt;span class="p"&gt;$&lt;/span&gt; evenly-spaced time series
    points,&lt;span class="k"&gt;\footnote&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Discussion based on Chapter 5.2 Spectral Analysis from
    &lt;span class="k"&gt;\emph&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Numerical Methods for Physics&lt;span class="p"&gt;}&lt;/span&gt; by Alejandro L.&lt;span class="k"&gt;\ &lt;/span&gt;Garcia, 1994.&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nt"&gt;\begin{equation}&lt;/span&gt;
        &lt;span class="k"&gt;\mathbf&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;y&lt;span class="p"&gt;}&lt;/span&gt; = [y&lt;span class="p"&gt;_&lt;/span&gt;1, y&lt;span class="p"&gt;_&lt;/span&gt;2, &lt;span class="k"&gt;\ldots&lt;/span&gt;, y&lt;span class="p"&gt;_&lt;/span&gt;N]
    &lt;span class="nt"&gt;\end{equation}&lt;/span&gt;

    The data are sampled every &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nv"&gt;\tau&lt;/span&gt;&lt;span class="p"&gt;$&lt;/span&gt; seconds, thus giving us a list of time
    points defined by:

    &lt;span class="nt"&gt;\begin{equation}&lt;/span&gt;
        t&lt;span class="p"&gt;_&lt;/span&gt;i = &lt;span class="k"&gt;\tau&lt;/span&gt; (i - 1)
    &lt;span class="nt"&gt;\end{equation}&lt;/span&gt;

    where &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;i&lt;/span&gt;&lt;span class="p"&gt;$&lt;/span&gt; is the 1-based index of the input vector.
&lt;span class="nt"&gt;\end{frame}&lt;/span&gt;

&lt;span class="nt"&gt;\begin{frame}&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Discrete Fourier transformation definition&lt;span class="p"&gt;}&lt;/span&gt;
    Given the vector of data points, &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nv"&gt;\mathbf&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;y&lt;/span&gt;&lt;span class="p"&gt;}$&lt;/span&gt;, we can define its discrete
    Fourier transform, &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nv"&gt;\mathbf&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;}$&lt;/span&gt;, as a vector:

    &lt;span class="nt"&gt;\begin{equation}&lt;/span&gt;
        Y&lt;span class="p"&gt;_{&lt;/span&gt;k+1&lt;span class="p"&gt;}&lt;/span&gt; = &lt;span class="k"&gt;\sum&lt;/span&gt;&lt;span class="p"&gt;_{&lt;/span&gt;j=0&lt;span class="p"&gt;}^{&lt;/span&gt;N-1&lt;span class="p"&gt;}&lt;/span&gt; y&lt;span class="p"&gt;_{&lt;/span&gt;j+1&lt;span class="p"&gt;}&lt;/span&gt; e&lt;span class="p"&gt;^{&lt;/span&gt;-2 &lt;span class="k"&gt;\pi&lt;/span&gt; i j k / N&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;\end{equation}&lt;/span&gt;

    where &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;i &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt; &lt;/span&gt;&lt;span class="nv"&gt;\sqrt&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}$&lt;/span&gt;. Note that &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;j&lt;/span&gt;&lt;span class="p"&gt;$&lt;/span&gt; and &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;k&lt;/span&gt;&lt;span class="p"&gt;$&lt;/span&gt; start at zero, whereas the
    vector uses a 1-based index.
&lt;span class="nt"&gt;\end{frame}&lt;/span&gt;

&lt;span class="nt"&gt;\begin{frame}&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Example&lt;span class="p"&gt;}&lt;/span&gt;
    Following the discrete Fourier transform discussion in
    Garcia,&lt;span class="k"&gt;\footnote&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Chapter 5.2 Spectral Analysis from &lt;span class="k"&gt;\emph&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Numerical Methods for
    Physics&lt;span class="p"&gt;}&lt;/span&gt; by Alejandro L.&lt;span class="k"&gt;\ &lt;/span&gt;Garcia, 1994.&lt;span class="p"&gt;}&lt;/span&gt; using a sampling interval of
    &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nv"&gt;\tau&lt;/span&gt;&lt;span class="nb"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;$&lt;/span&gt;, &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;N &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt; &lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;$&lt;/span&gt; data points, a signal frequency of &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;f&lt;/span&gt;&lt;span class="p"&gt;_&lt;/span&gt;&lt;span class="nb"&gt;s &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;$&lt;/span&gt;, and
    a phase of &lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nv"&gt;\phi&lt;/span&gt;&lt;span class="p"&gt;_&lt;/span&gt;&lt;span class="nb"&gt;s &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;$&lt;/span&gt; we obtain the following graph:

    &lt;span class="k"&gt;\centerline&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;\includegraphics&lt;/span&gt;&lt;span class="na"&gt;[width=0.5\textwidth]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;dft-sine-wave.png&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;\end{frame}&lt;/span&gt;

&lt;span class="nt"&gt;\end{document}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assuming that you have LaTeX installed on your local machine, and that the code is saved in a file called &lt;code&gt;discrete-fourier-transform.tex&lt;/code&gt;, you can build the document yourself by running &lt;code&gt;latexmk&lt;/code&gt; in the &lt;code&gt;discrete-fourier-transform&lt;/code&gt; directory. This will create a PDF file called &lt;code&gt;discrete-fourier-transform.pdf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the output I got for the title page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fin3fdm27xa5hb32qdbuk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fin3fdm27xa5hb32qdbuk.png" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That looks good. With this foundation in place, assume that we’ve also created a corresponding repository on GitHub and have pushed the code upstream. If you want to follow along at home, or simply don’t want to copy-and-paste the code from above, you can clone &lt;a href="https://github.com/paultcochrane/discrete-fourier-transform" rel="noopener noreferrer"&gt;the repository I created&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting GitHub to build the document for us
&lt;/h3&gt;

&lt;p&gt;With a GitHub repository on hand, we can get GitHub to build our slides for us. To do that, we need to create a YAML configuration file in the location that GitHub expects to find &lt;a href="https://en.wikipedia.org/wiki/Continuous_integration" rel="noopener noreferrer"&gt;continuous integration&lt;/a&gt; tasks, namely, &lt;code&gt;.gitlab/workflows&lt;/code&gt;. Let’s create the directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .github/workflows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using your favourite editor, create a file called &lt;code&gt;ci.yml&lt;/code&gt; within that directory, and fill it with these contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build slides in CI&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-22.04&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sudo apt install texlive-latex-recommended texlive-latex-extra texlive-luatex latexmk&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build slides&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latexmk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In GitHub parlance, this file is called a &lt;a href="https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax" rel="noopener noreferrer"&gt;&lt;em&gt;workflow&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We denote the workflow’s name by the value of the &lt;code&gt;name&lt;/code&gt; keyword given at the top level.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;on&lt;/code&gt; keyword specifies which events will trigger a workflow. In the case here, we’ve specified that the workflow should run on pushes to any branch or on any pull requests. It’s possible to make these settings more specific, but let’s keep things simple.&lt;/p&gt;

&lt;p&gt;Next up is the &lt;code&gt;jobs&lt;/code&gt; keyword, which defines the jobs to run within the workflow. There can be many jobs in a workflow, but in our case, we only need one.&lt;/p&gt;

&lt;p&gt;The keyword in the level under &lt;code&gt;jobs&lt;/code&gt; defines a block of job-related tasks as well as the job’s name. The single job we defined in the workflow above is called &lt;code&gt;build&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We’ve configured the &lt;code&gt;build&lt;/code&gt; job to run on a host using Ubuntu 22.04 as its base Docker image via the &lt;code&gt;runs-on&lt;/code&gt; keyword. You might wonder why I didn’t use the other available Ubuntu version (24.04), a.k.a. &lt;code&gt;ubuntu-latest&lt;/code&gt;. Well, I had repository lookup errors when trying to install the required LaTeX packages. Hence, I reverted to the older Ubuntu version where the installation worked as expected. Stability matters. Especially when presenting worked examples.&lt;/p&gt;

&lt;p&gt;The next keyword is called &lt;code&gt;steps&lt;/code&gt; and defines the individual steps that the job should run.&lt;/p&gt;

&lt;p&gt;The first step checks out our repository into our build host with the &lt;code&gt;actions/checkout@4&lt;/code&gt; GitHub action. The steps thereafter run shell commands via the &lt;code&gt;run&lt;/code&gt; keyword. You can also give each step a name, as we’ve done here, so that they are easier to find within the GitHub Actions tab.&lt;/p&gt;

&lt;p&gt;Workflows appear in the &lt;em&gt;Actions&lt;/em&gt; tab on the GitHub repository project page. I’m still a bit confused about how the naming works here. It seems that one combines actions into a workflow. However, the overarching term is GitHub Actions, under which one defines workflows. These then contain actions. It seems a bit circular to me, but I simply might not have understood the concept yet.&lt;/p&gt;

&lt;p&gt;Anyway, the subsequent steps in this job install the relevant Ubuntu TeXLive packages and build the slides with &lt;code&gt;latexmk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To get GitHub to follow these instructions and thus build the document, we need to add it to our repository and commit that change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git add .github/workflows/ci.yml
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git commit
&lt;span class="go"&gt;[main bc389e5] Build document using GitHub's CI system
 Date: Sun Feb 8 21:49:21 2026 +0100
 1 file changed, 17 insertions(+)
 create mode 100644 .github/workflows/ci.yml
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We push this change upstream to get GitHub to build our document.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git push
&lt;span class="go"&gt;Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 663 bytes | 331.00 KiB/s, done.
Total 5 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.com:paultcochrane/discrete-fourier-transform.git
&lt;/span&gt;&lt;span class="gp"&gt;   315cf5a..bc389e5 main -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Opening the Actions tab in our GitHub &lt;code&gt;discrete-fourier-transform&lt;/code&gt; project, we see a green tick next to the workflow run. This is a good sign: the workflow ran successfully. The workflow run’s title is the commit message’s subject.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99upwi76tsma5msk2q54.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99upwi76tsma5msk2q54.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking on the workflow run’s title, we’re taken to a page with further details:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frd0sh8xmcznphjxazalv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frd0sh8xmcznphjxazalv.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Within the grey box on this page, we see the name of the job we ran: &lt;code&gt;build&lt;/code&gt;. Clicking on the smaller white box for the job, we’re taken to the details for the job:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8mbepy8lqqv6prt5ef8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8mbepy8lqqv6prt5ef8.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we see the steps that the job took to build everything. If we click on the “Build slides” step, the section expands, and we see its build log. If you’re following along at home, you’ll see &lt;em&gt;lots&lt;/em&gt; of LaTeX build information. Scrolling to the end, you’ll see output like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9wdhtq3tw0s7wvfpvifz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9wdhtq3tw0s7wvfpvifz.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The important bits are at the end, in particular these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Output written on discrete-fourier-transform.pdf (6 pages, 143709 bytes).
Transcript written on discrete-fourier-transform.log.
Latexmk: Log file says output to 'discrete-fourier-transform.pdf'
Latexmk: Examining 'discrete-fourier-transform.log'
=== TeX engine is 'LuaHBTeX'
Latexmk: All targets (discrete-fourier-transform.pdf) are up-to-date
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where we find out that the document was written to a file called &lt;code&gt;discrete-fourier-transform.pdf&lt;/code&gt; and that all targets are up to date. Awesome!&lt;/p&gt;

&lt;h3&gt;
  
  
  Archiving artefacts from the build
&lt;/h3&gt;

&lt;p&gt;Ok, so the &lt;em&gt;build&lt;/em&gt; looks good, but does the &lt;em&gt;output&lt;/em&gt; of that build also look good? We can’t tell right now because we have no way of viewing it. GitHub built it, but deleted it as soon as the job finished.&lt;/p&gt;

&lt;p&gt;That’s … suboptimal. We want to check the output as well. How to do that? For this task, we want to archive the build artefacts, which we can do with the &lt;a href="https://github.com/actions/upload-artifact" rel="noopener noreferrer"&gt;&lt;code&gt;actions/upload-artifact@v4&lt;/code&gt; GitHub action&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To archive our GitHub-built PDF file, we append the following step to those defined in the &lt;code&gt;build&lt;/code&gt; job in our &lt;code&gt;ci.yml&lt;/code&gt; workflow file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Archive built PDF document&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dft-slides&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;discrete-fourier-transform.pdf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now commit this change and push it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git commit .github/workflows/ci.yml
&lt;span class="go"&gt;[main d5ec2be] Archive built PDF document as artefact
 Date: Mon Feb 9 14:04:58 2026 +0100
 1 file changed, 6 insertions(+)
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git push
&lt;span class="go"&gt;Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 585 bytes | 585.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To github.com:paultcochrane/discrete-fourier-transform.git
&lt;/span&gt;&lt;span class="gp"&gt;   bc389e5..d5ec2be main -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Revisiting the details page for the &lt;code&gt;build&lt;/code&gt; job:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6fx5icbbxjt8kw9apows.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6fx5icbbxjt8kw9apows.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we see a new step appear after “Build slides” called “Archive built PDF document”. Clicking on this step, we see its log output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm22mmec6mqz2yltpa0y4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm22mmec6mqz2yltpa0y4.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This part of the log output is interesting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Artifact dft-slides.zip successfully finalized. Artifact ID 5432273684
Artifact dft-slides has been successfully uploaded! Final size is 137788 bytes. Artifact ID is 5432273684
Artifact download URL: https://github.com/paultcochrane/discrete-fourier-transform/actions/runs/21826316227/artifacts/5432273684
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;because it shows that the build artefact (called &lt;code&gt;dft-slides.zip&lt;/code&gt;) was created successfully, and we see a link where we can download it.&lt;/p&gt;

&lt;p&gt;Of course, you could click on this link to download the archived artefacts. However, a simpler way to access build artefacts is to look at the overview page for a given workflow run. There, you’ll see a new section, called “Artifacts”:&lt;sup id="fnref:artifacts-and-artefacts"&gt;4&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs1yc75piemjypd85928i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs1yc75piemjypd85928i.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From here, you can click on the little download button on the right-hand side. This will download the &lt;code&gt;.zip&lt;/code&gt; file that the workflow run created.&lt;/p&gt;

&lt;p&gt;If you download that file now and open it, you’ll find the document that GitHub built:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1nyglfv4hm5yanu61ohl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1nyglfv4hm5yanu61ohl.png" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Now&lt;/em&gt; things are looking good!&lt;/p&gt;

&lt;h3&gt;
  
  
  Finding font failures
&lt;/h3&gt;

&lt;p&gt;Not very surprisingly, this result looks much the same as our earlier result. I say &lt;em&gt;much the same&lt;/em&gt; because the results are not identical. In particular, the fonts are different. It seems that some fonts have been replaced by default ones. A quick look at the “Build slides” log output reveals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;luaotfload | db : Reload initiated (formats: otf,ttf,ttc); reason: Font "Fira Sans Light" not found.
Package beamerthememetropolis Warning: Could not find Fira Sans fonts on
input line 95.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, the Fira Sans font that the &lt;code&gt;metropolis&lt;/code&gt; theme needs isn’t available. This is a secondary issue that we want to fix by using an up-to-date TeXLive distribution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrating to &lt;code&gt;latex-action&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Ok, we’ve got a document built on GitHub, and it’s almost producing the PDF output we expect. Now we need to get around the issue of using an outdated TeXLive distribution. Instead of using a version from 2021, we want to use a version from at least 2025.&lt;/p&gt;

&lt;p&gt;This is what we really came here for: to see the &lt;code&gt;latex-action&lt;/code&gt; action in action.&lt;/p&gt;

&lt;p&gt;To be honest, the change is very simple: remove the “Install dependencies” step and swap out the current “Build slides” step with this YAML code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build slides&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xu-cheng/latex-action@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;root_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;discrete-fourier-transform.tex&lt;/span&gt;
          &lt;span class="na"&gt;texlive_version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2025&lt;/span&gt;
          &lt;span class="na"&gt;latexmk_use_lualatex&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new step uses the same name as the step it replaced, but now we’re using a GitHub action via the &lt;code&gt;uses&lt;/code&gt; keyword instead of running &lt;code&gt;latexmk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We’re also being careful to specify a version. Theoretically, it should be possible to do without the &lt;code&gt;@v4&lt;/code&gt; suffix, but specifying an explicit version is good practice. This way, we ensure builds are more reproducible. Were we to leave out the version suffix, there could be future changes to &lt;code&gt;latex-action&lt;/code&gt; that break an otherwise functioning build. Of course, updating to a new version would be a good idea once it exists, but we need to check that it works as expected before committing to it.&lt;/p&gt;

&lt;p&gt;We configure options to the &lt;code&gt;latex-action&lt;/code&gt; GitHub action within the &lt;code&gt;with&lt;/code&gt; keyword block. The &lt;code&gt;root_file&lt;/code&gt; option specifies the main file that builds the entire document. The &lt;code&gt;texlive_version&lt;/code&gt; option specifies the TeXLive version we want to use, i.e. 2025. We also want to use LuaLaTeX when running the &lt;code&gt;latexmk&lt;/code&gt; command, so that we get the full power of a modern LaTeX engine. Hence, we set &lt;code&gt;latexmk_use_lualatex&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What’s the effect of this change? Well, instead of pulling in an Ubuntu Docker image and then installing the Ubuntu TeXLive packages, we now grab a Docker image with TeXLive pre-installed and use that as our build host. This gives us a complete TeXLive environment from the get-go.&lt;/p&gt;

&lt;p&gt;Let’s see how we get on. Doing our commit and push dance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git commit .github/workflows/ci.yml
&lt;span class="go"&gt;[main bbe6dba] Replace Ubuntu TeXLive with latex-action TeXLive
 Date: Mon Feb 9 14:55:41 2026 +0100
 1 file changed, 5 insertions(+), 4 deletions(-)
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git push
&lt;span class="go"&gt;Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 562 bytes | 562.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To github.com:paultcochrane/discrete-fourier-transform.git
&lt;/span&gt;&lt;span class="gp"&gt;   d5ec2be..bbe6dba main -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and letting GitHub do its thing, we find that everything builds successfully:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futoih52hfwpaadbe5a2w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futoih52hfwpaadbe5a2w.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s a good sign.&lt;/p&gt;

&lt;p&gt;If we now download our archived artefacts from the workflow overview page (note that the file size is also smaller):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxnpidj20a0qdf46zfne7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxnpidj20a0qdf46zfne7.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we see that the font issue has been corrected:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1x1hrsog709w19qj7brh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1x1hrsog709w19qj7brh.png" width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now we’re using an up-to-date TeXLive version! Yay! 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to from here?
&lt;/h2&gt;

&lt;p&gt;And that’s it really. Of course, there are more things you could do to extend and customise the build process.&lt;/p&gt;

&lt;p&gt;One thing you might like to try is to add the &lt;a href="https://github.com/softprops/action-gh-release" rel="noopener noreferrer"&gt;&lt;code&gt;action-gh-release&lt;/code&gt; GitHub action&lt;/a&gt;. This action automates creating releases according to Git tags. Your Git project will then host any PDF documents you deem worthy of a versioned release (and hence a Git tag) on the repository’s project page. If you want to upload draft releases, that’s also possible. This way, you can show users current development-grade releases of your LaTeX documents.&lt;/p&gt;

&lt;p&gt;The sky’s the limit! Have fun!&lt;/p&gt;

&lt;h2&gt;
  
  
  Addendum: metropolis and moloch woes
&lt;/h2&gt;

&lt;p&gt;One other incentive I had to use the &lt;code&gt;latex-action&lt;/code&gt; GitHub action was a desire to replace the &lt;a href="https://github.com/matze/mtheme" rel="noopener noreferrer"&gt;&lt;code&gt;metropolis&lt;/code&gt; beamer theme&lt;/a&gt; with &lt;a href="https://moloch.ink/" rel="noopener noreferrer"&gt;&lt;code&gt;moloch&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I like &lt;code&gt;metropolis&lt;/code&gt;. It’s clean and minimalistic, and looks rather stylish. Sadly, it’s now unmaintained, and the last &lt;a href="https://ctan.org/pkg/beamertheme-metropolis" rel="noopener noreferrer"&gt;release to CTAN&lt;/a&gt; was from 2017. It’s been replaced by its fork, a project called &lt;a href="https://moloch.ink/" rel="noopener noreferrer"&gt;&lt;code&gt;moloch&lt;/code&gt;&lt;/a&gt;. Its internals are cleaner, it fixes some bugs in the &lt;code&gt;metropolis&lt;/code&gt; theme, and it is less fragile to internal changes in beamer itself.&lt;/p&gt;

&lt;p&gt;Unfortunately, &lt;code&gt;moloch&lt;/code&gt; is only available in recent TeXLive versions (it was first released in 2024) and hence &lt;em&gt;isn’t&lt;/em&gt; available in the Ubuntu TeXLive packages on GitHub. Hence, my wish to migrate to a GitHub action providing an up-to-date TeXLive version.&lt;/p&gt;

&lt;p&gt;Implementing this change while maintaining the same look led down rather a deep rabbit hole. Regrettably, I wasn’t able to solve all the problems that appeared. Thus, I decided against introducing &lt;code&gt;moloch&lt;/code&gt; as an additional change in the main part of this article.&lt;/p&gt;

&lt;p&gt;One major blocking issue I had was with fonts. By default, &lt;code&gt;metropolis&lt;/code&gt; uses the Fira Sans font; &lt;code&gt;moloch&lt;/code&gt; doesn’t: it seems to use a mixture of the Computer Modern and Latin Modern fonts. Using Fira Sans with &lt;code&gt;moloch&lt;/code&gt; is simple enough: it’s a configuration option added in the document preamble. However, this also changed the font used for mathematics, and I couldn’t get that to look right. For instance, bold mathematics were shown with a serif font, whereas &lt;code&gt;metropolis&lt;/code&gt; used a sans-serif font without problems. Using either the Fira Math or &lt;code&gt;firamath-otf&lt;/code&gt; packages bundled with TeXLive didn’t help, because they currently only provide the regular typeface. The lighter typefaces aren’t yet bundled with TeXLive, thus I’m hoping a future TeXLive update might help this situation.&lt;/p&gt;

&lt;p&gt;Oh well. Ya can’t win every day! I’m going to stick to &lt;code&gt;metropolis&lt;/code&gt; for the time being. It still does the job well and works (for my purposes) with the current TeXLive version.&lt;/p&gt;

&lt;p&gt;Once I realised that this detail wasn’t necessary for what I wanted to introduce in the article, I decided to leave it out of the main text. I’m guessing no one missed it but me! 😄&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Does anyone remember the prosper or foiltex classes? Wow, it seems like aeons ago that I was using them. I think I’m showing my age… ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I’m aware that the &lt;code&gt;ubuntu-24.04&lt;/code&gt; a.k.a &lt;code&gt;ubuntu-latest&lt;/code&gt; Docker image is available. However, I got errors when fetching packages. Thus, for this article, and the sake of stability for anyone following along at home, I stuck with &lt;code&gt;ubuntu-22.04&lt;/code&gt;, where I knew that everything worked. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dorotea Avra is not the name of a real person. I generated it using a &lt;a href="https://www.behindthename.com/random/" rel="noopener noreferrer"&gt;random name generation site&lt;/a&gt;. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Note that American English spells this word as “artifact”. Since I grew up with a British English-derived variant of the English language, I spell it “artefact”. Just so you know. ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>latex</category>
      <category>github</category>
    </item>
    <item>
      <title>Finding a fisherman’s fastest path from shore to boat</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Wed, 01 Apr 2026 22:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/finding-a-fishermans-fastest-path-from-shore-to-boat-2ibi</link>
      <guid>https://dev.to/peateasea/finding-a-fishermans-fastest-path-from-shore-to-boat-2ibi</guid>
      <description>&lt;p&gt;When tutoring high-school students in maths and physics, I sometimes stumble across interesting problems.  In this scenario, a fisherman seeks to determine the fastest route from his location on the shore to his boat out in the water.  What I find interesting here is the change of perspective that makes solving the problem easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;Consider the figure below. A fisherman stands on the shore of a lake some distance from his boat out in the water.  The distance from the fisherman to the boat is 10 m; the distance from the edge of the shore to the boat is 6 m. Using &lt;a href="https://en.wikipedia.org/wiki/Fermat%27s_principle" rel="noopener noreferrer"&gt;Fermat's principle&lt;/a&gt;, determine the shortest time it will take the fisherman to reach the boat if the speed&lt;br&gt;
of the fisherman's movement along the shore is 3 m/s, and in the water is three times less.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmjj1wnn6vfa553hwg3hr.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmjj1wnn6vfa553hwg3hr.jpeg" alt="A fisherman stands on a lake shore.  A boat sits in the water some distance from him.  The diagonal distance is 10m; the distance from the boat to the shore is 6m." width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;There are several ways that the fisherman could reach the boat.  He could go directly to the boat through the water, travelling the shortest distance: 10 m.  Or he could move along the shore until the distance in the water is shortest (6 m), going through the water the rest of the way.  Neither of these options is optimal.  In one case, he doesn't make any use of the speed advantage along the shore.  In the other case, he moves too far along the shore and ends up travelling a much longer distance than necessary.  The best path lies between these two extremes, and that's what we have to find.&lt;/p&gt;
&lt;h3&gt;
  
  
  At the start, collect what we know
&lt;/h3&gt;

&lt;p&gt;Let's collect some information from the question and deduce what we can to solve the problem.  We're told that the fisherman's speed along the shore is 3 m/s.  Let's denote this speed by 

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vsv_s&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.  The speed in the water we denote by 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vwv_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.  We're told that the speed in the water is three times less than the speed along the shore, hence 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vwv_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is 1 m/s.  From the geometry of the situation, we can see that the paths in the water and the path along the shore make a scaled 3-4-5 right-angled triangle.  Doubling the side lengths of a 3-4-5 right-angled triangle gives a 6-8-10 right-angled triangle.&lt;sup id="fnref1"&gt;1&lt;/sup&gt; In other words, the path along the shore is 8 m, which is the only side length that we didn't yet know.&lt;/p&gt;

&lt;p&gt;Having deduced most of the information we can from the diagram and the question, the task is to find the best path from the fisherman's position on the shore to the boat.  Note that this is &lt;em&gt;not&lt;/em&gt; the shortest path.  It is, however, the path that takes the least &lt;em&gt;time&lt;/em&gt;, which is where Fermat's principle comes in.&lt;/p&gt;
&lt;h3&gt;
  
  
  Look at the problem from the beginning &lt;em&gt;and&lt;/em&gt; from the end
&lt;/h3&gt;

&lt;p&gt;The problem involves movement at a given velocity in one medium (along the shore) and then movement at a different velocity in a different medium (the water).  Changing our perspective, we can see that we're really looking at Snell's law in ray optics.&lt;/p&gt;

&lt;p&gt;Turning the problem on its head will hopefully make this clearer.  Consider the path a light ray would take from the boat to the fisherman's initial position.  Why look at the problem from this perspective?  It turns out that the time to travel along a given path is independent of direction: i.e. the path &lt;em&gt;from&lt;/em&gt; the boat is the same as the path &lt;em&gt;to&lt;/em&gt; the boat.  Changing our perspective to be &lt;em&gt;from&lt;/em&gt; the boat, we can see that a path from the boat to the shore at some angle, then continuing &lt;em&gt;along&lt;/em&gt; the shore to the fisherman,&lt;br&gt;
is the same situation as a light ray sent from the boat and then refracted at the water-shore boundary at the &lt;em&gt;critical angle&lt;/em&gt;.&lt;sup id="fnref2"&gt;2&lt;/sup&gt;  In other words, a calculation using &lt;a href="https://en.wikipedia.org/wiki/Snell%27s_law#Total_internal_reflection_and_critical_angle" rel="noopener noreferrer"&gt;Snell's law at the critical angle&lt;/a&gt; is equivalent to the fisherman moving along the shore and then travelling to the boat through the water.  This is the problem we're trying to solve, and now we have a way to do that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1i71ckgvtmrvmpjqygt6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1i71ckgvtmrvmpjqygt6.jpg" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Construct a solution using Snell's law
&lt;/h3&gt;

&lt;p&gt;Let's examine Snell's law from the perspective of a light ray travelling from the boat.  Consider the following diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwywbjhlv1bi226l7zcma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwywbjhlv1bi226l7zcma.png" width="749" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The blue region represents the water; the white region represents the lake shore.  We have a light ray travelling from the left-hand red point in the blue region towards the white region.  Its path makes an angle 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θw\theta_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 to the normal at the boundary between the two regions (i.e. a line perpendicular to the boundary between the two regions).  It is refracted at this boundary and travels along the boundary interface to the second red point on the right.  The ray travels at an angle 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θs\theta_s&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 to the normal.&lt;/p&gt;

&lt;p&gt;Using Snell's law, we have the following relationship:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;sin⁡θssin⁡θw=vsvw.
\frac{\sin \theta_s}{\sin \theta_w} = \frac{v_s}{v_w}.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;We know that 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vsv_s&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is 3 m/s, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vwv_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is 1 m/s, and that 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θs\theta_s&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;90∘90^\circ&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;9&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mbin mtight"&gt;∘&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (equivalently: 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;π/2\pi/2&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;π&lt;/span&gt;&lt;span class="mord"&gt;/2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 radians).  Since 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;sin⁡(π/2)=1\sin(\pi/2) = 1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;π&lt;/span&gt;&lt;span class="mord"&gt;/2&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, we can simplify the expression above to:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;1sin⁡θw=31.
\frac{1}{\sin \theta_w} = \frac{3}{1}.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Rearranging this equation to be in terms of 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;sin⁡θw\sin \theta_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, we have:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;sin⁡θw=13.
\sin \theta_w = \frac{1}{3}.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Taking the inverse sine, we have an expression for 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θw\theta_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θw=sin⁡−1(13).
\theta_w = \sin^{-1}\left( \frac{1}{3} \right).
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size3"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size3"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;This is the angle to the normal at the boundary that a light ray would take along the path of least time between the two red points.&lt;/p&gt;

&lt;p&gt;We can now work out the distance travelled both in the water and along the shore.  Once we have that information, we can use the velocities in each medium to work out the time taken along this path.  Hence, we can calculate the time along the fisherman's fastest path from his position on the shore to the boat.&lt;/p&gt;

&lt;p&gt;From geometry, we see that the angle between the vertical solid line and the ray in the blue region is equal to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θw\theta_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.  Thus, we can calculate the length 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dwd_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, which is the hypotenuse of the right-angled triangle with sides 6 m and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ds′d_{s'}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
:&lt;sup id="fnref3"&gt;3&lt;/sup&gt;&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dw=6cos⁡θw.
d_w = \frac{6}{\cos \theta_w}.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;6&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;From the diagram, we know that the length along the shore (i.e. along the boundary between the blue and white regions) is 8 m.  Thus, the distance the ray travels along the shore, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dsd_s&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, plus the remaining distance along the shore, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ds′d_{s'}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, is equal to 8 m.  This gives us the following relation:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ds+ds′=8.
d_s + d_{s'} = 8.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;8.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;We thus have an expression for 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dsd_s&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 in terms of 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ds′d_{s'}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ds=8−ds′.
d_s = 8 - d_{s'}.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;8&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Again, from geometry, we can work out what 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ds′d_{s'}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is in terms of 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θw\theta_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 by using the tangent and the adjacent side (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ds′d_{s'}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the opposite side of the triangle):&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ds′=6tan⁡θw.
d_{s'} = 6 \tan \theta_w.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;6&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;tan&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Now we know how far the distance along the shore is in terms of the angle 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θw\theta_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ds=8−6tan⁡θw.
d_s = 8 - 6 \tan \theta_w.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;8&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;6&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;tan&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;We're now left with the task of finding out how long it takes to travel each of the two components of the path, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dwd_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dsd_s&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.  Since the speed in each medium is constant, we can write the distances in terms of their velocities and times, i.e.:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dw=vwtw,
d_w = v_w t_w,
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ds=vsts,
d_s = v_s t_s,
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;where 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;twt_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;tst_s&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 are the times in the water and along the shore, respectively.  We can write these times in terms of distance and velocity like so:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;tw=dwvw,
t_w = \frac{d_w}{v_w},
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ts=dsvs.
t_s = \frac{d_s}{v_s}.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;The total time for the fastest path, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;tt&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, is the sum of these two&lt;br&gt;
quantities:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t=ts+tw,
t = t_s + t_w,
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=8−6tan⁡θwvs+6vwcos⁡θw,
= \frac{8 - 6 \tan \theta_w}{v_s} + \frac{6}{v_w \cos \theta_w},
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;8&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;6&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;tan&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;6&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=8−6tan⁡θw3+6cos⁡θw,
= \frac{8 - 6 \tan \theta_w}{3} + \frac{6}{\cos \theta_w},
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;8&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;6&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;tan&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;6&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;where I've substituted the values of the speed along the shore and the speed through the water into the final expression.&lt;/p&gt;

&lt;p&gt;We know that:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θw=sin⁡−1(13)≈0.3398.
\theta_w = \sin^{-1} \left( \frac{1}{3} \right) \approx 0.3398.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;&lt;span class="mop"&gt;sin&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size3"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size3"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;≈&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0.3398.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Substituting this value into the equation for 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;tt&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 above, we get:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t=ts+tw≈1.9595 s+6.3640 s≈8.3235 s.
t = t_s + t_w \approx 1.9595\ \text{s} + 6.3640\ \text{s} \approx 8.3235\ \text{s}.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;≈&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1.9595&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;6.3640&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;≈&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;8.3235&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;In other words, the fastest time for the fisherman to travel from his initial position to the boat is 8.3235 s.&lt;/p&gt;

&lt;h2&gt;
  
  
  Numerical calculations
&lt;/h2&gt;

&lt;p&gt;Below is the &lt;a href="https://www.sagemath.org/" rel="noopener noreferrer"&gt;SageMath&lt;/a&gt; code I used to calculate the numerical values of 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;tst_s&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;twt_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, and hence 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;tt&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 in the section above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;theta_w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;asin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;tan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta_w&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;3.&lt;/span&gt;
&lt;span class="n"&gt;tw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta_w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tw&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ts = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;; tw = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;; t = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The first line defines a variable called &lt;code&gt;theta_w&lt;/code&gt; containing the value of 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θw\theta_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 we calculated using Snell's law from earlier.  The next two lines define the variables &lt;code&gt;ts&lt;/code&gt; and &lt;code&gt;tw&lt;/code&gt;, which calculate the times along the shore and through the water, respectively.  The fourth line calculates the total time for the fastest path.  The final line of code prints the results nicely.&lt;/p&gt;

&lt;p&gt;Running this code gives the following output:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts = 1.9596; tw = 6.3640; t = 8.3235
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Note that the value for &lt;code&gt;ts&lt;/code&gt; shown here is rounded up to four decimal places, and is hence different from the value I mentioned in the text.  If you add the rounded &lt;code&gt;ts&lt;/code&gt; and &lt;code&gt;tw&lt;/code&gt; values together, you'll get a slightly different result from using the unrounded values.  This is why the value for &lt;code&gt;t&lt;/code&gt; &lt;em&gt;looks&lt;/em&gt; like it should be 8.3236 when the correct value is really 8.3235.&lt;/p&gt;
&lt;h2&gt;
  
  
  Extension
&lt;/h2&gt;

&lt;p&gt;Now, because I'm me, I can't simply solve something in one way and be done with it.  Thus, I decided to plot the total time for paths corresponding to different 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θw\theta_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 angles, ranging from 0 (the fisherman goes 8 m along the shore and then 6 m in the water) to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θmax=cos⁡−1(3/5)\theta_{\mathrm{max}} = \cos^{-1}(3/5)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathrm mtight"&gt;max&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;&lt;span class="mop"&gt;cos&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;3/5&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (the fisherman follows the most direct path: 10 m through the water).  I wanted to see this plot because it gives an intuitive feel for how the time is a minimum between the two extremes.&lt;/p&gt;

&lt;p&gt;I used &lt;a href="https://www.sagemath.org/" rel="noopener noreferrer"&gt;SageMath&lt;/a&gt;, an open source mathematics software system, to set up the variables and plot the graph.  SageMath uses a Python-based language, hence it's fairly easy to use.&lt;/p&gt;

&lt;p&gt;In the code below, I define a symbolic variable &lt;code&gt;theta_w&lt;/code&gt;, corresponding to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θw\theta_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 from above.  I then define the time along the shore, &lt;code&gt;ts&lt;/code&gt;, and the time in the water, &lt;code&gt;tw&lt;/code&gt;, in terms of &lt;code&gt;theta_w&lt;/code&gt;.  This allows me to write the total time, &lt;code&gt;t&lt;/code&gt;, which is then a function of &lt;code&gt;theta_w&lt;/code&gt;.  I also calculate the maximum value &lt;code&gt;theta_w&lt;/code&gt; can have given the problem's geometry, which I've called &lt;code&gt;theta_max&lt;/code&gt;.  This way, I know the maximum value of &lt;code&gt;theta_w&lt;/code&gt; to plot.  The &lt;code&gt;theta_max&lt;/code&gt; value corresponds to the direct path from the fisherman through the water to the boat.  The minimum value for &lt;code&gt;theta_w&lt;/code&gt; is zero, corresponding to a path perpendicular to the shore. Lastly, I plot &lt;code&gt;t&lt;/code&gt; as a function of &lt;code&gt;theta_w&lt;/code&gt; running from 0 up to &lt;code&gt;theta_max&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;theta_w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;theta_w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;tan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta_w&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;tw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta_w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tw&lt;/span&gt;
&lt;span class="n"&gt;theta_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;acos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta_w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;theta_max&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;axes_labels&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;theta_w$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$t$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here's what the plot looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0w7t7qf0227mu3n69dg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0w7t7qf0227mu3n69dg.png" width="599" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The graph shows the total path time for values of &lt;code&gt;theta_w&lt;/code&gt; ranging from zero up to &lt;code&gt;theta_max&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;theta_w&lt;/code&gt; is equal to zero, this is the same as travelling 8 m at 3 m/s and then 6 m at 1 m/s.  In other words:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;83 s+6 s≈8.667 s.
\frac{8}{3}\ \text{s} + 6\ \text{s} \approx 8.667\ \text{s}.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;8&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;6&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;≈&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;8.667&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;This is the value where the curve intersects the 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;yy&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
-axis, which we can see matches the plot above.&lt;/p&gt;

&lt;p&gt;At the largest angle, &lt;code&gt;theta_max&lt;/code&gt;, the time taken is 10 s because this is the time taken to move a distance of 10 m travelling at 1 m/s, i.e. the direct path from the fisherman to the boat.&lt;/p&gt;

&lt;p&gt;Reading the graph, we can approximate the shortest time to be at a &lt;code&gt;theta_w&lt;/code&gt; value of roughly 0.35, which is approximately 8.3 s.  These values correspond to those we got for 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;θw\theta_w&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;w&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;tt&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 in the solution section above.&lt;/p&gt;

&lt;p&gt;We've effectively verified the result we got in the previous section.  Yay!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;And that's it.  Hopefully, the explanation helped you understand the problem and its solution!&lt;/p&gt;

&lt;p&gt;It intrigues me how sometimes a maths or physics problem becomes more&lt;br&gt;
tractable just by looking at it from a different point of view.  If at first you find a problem difficult, try changing your perspective. 🙂&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;You can verify that this is still a right-angled triangle because 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;62+82=1026^2 + 8^2 = 10^2&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;6&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;8&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;This angle is the smallest angle that would keep a light ray within the given medium. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;The length 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;ds′d_{s'}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the remaining distance along the shore after the fisherman has travelled the distance 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dsd_s&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>physics</category>
    </item>
    <item>
      <title>German Perl/Raku Workshop 2026 (Berlin): a report</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Wed, 25 Mar 2026 23:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/german-perlraku-workshop-2026-berlin-a-report-1427</link>
      <guid>https://dev.to/peateasea/german-perlraku-workshop-2026-berlin-a-report-1427</guid>
      <description>&lt;p&gt;Last week, the &lt;a href="https://act.yapc.eu/gpw2026/" rel="noopener noreferrer"&gt;28th edition of the German Perl/Raku Workshop&lt;/a&gt; took place in Berlin. It was great to see some familiar faces (as well as some new ones!) to discuss computing, our favourite Swiss army chainsaw, and much more.&lt;/p&gt;

&lt;p&gt;This report contains rough notes of the talks that I attended.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting to Berlin
&lt;/h2&gt;

&lt;p&gt;Because I’m a bit crazy, and because I wanted to collect up-to-date and relevant data before my talk, I rode my bike from Hannover to Berlin. The trip was roughly 300 km long and took two days. The weather was pretty good, and I only had a nasty headwind for part of the first day. The second day went quite quickly, and once in Berlin, I decided to be a bit of a tourist for a little while and rode to the Brandenburg Gate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1hwh3utzgu1nxcrm569.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1hwh3utzgu1nxcrm569.png" alt="Bike with panniers in front of the Brandenburg Gate" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since there were several demonstrations in Berlin on that day, the Straße des 17. Juni (the road leading from the victory column to the Brandenburg Gate) was completely closed to traffic. This meant that people were walking and riding their bikes along what is usually three lanes of traffic in each direction. That was an opportunity I was glad to take! Like, when am I going to get that kind of opportunity again? Needless to say, I thoroughly enjoyed the freedom and space of riding along such a famous street.&lt;/p&gt;

&lt;p&gt;The next day (Sunday), I happened to meet Geoffrey and Theo as they were on their way to breakfast. I didn’t expect to stumble across anyone from the workshop so soon, and it was nice to have a chat and hear how they were and what they were up to. They went off to do touristy stuff, but I decided that, after two days on the bike, spending some time at a cafe with my laptop was the more relaxing option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-workshop meetup
&lt;/h2&gt;

&lt;p&gt;The pre-workshop event took place in a Bavarian-style pub a few blocks’ walk from the workshop venue. I found it amusing that we were in a Bavarian pub when we were in Berlin. However, there’s probably no such thing as a Berlin-style pub; it’s probably just a pub. The workshop took place in Munich last year, so in some sense the pre-workshop meetup venue made a connection to last year’s workshop. Given that we were the last people to leave (the staff had to be rather insistent to get us to pay and leave; they were very nice about it, though), I’d say that the conversation was at its usual excellent level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 1
&lt;/h2&gt;

&lt;p&gt;Last year’s workshop had a very relaxed schedule, and this year was no different. I far prefer this style to the stress of heaps of talks jammed in between 8 am and 6 pm. It’s much more laid-back and gives more time for discussions. One also has more time to process the information presented in the talks. Many thanks to the organisers for putting this together so well!&lt;/p&gt;

&lt;h3&gt;
  
  
  Max Maischein (Corion) - Using Coding Assistants with Perl
&lt;/h3&gt;

&lt;p&gt;Although Max doesn’t use much Perl or AI in his job, he’d looked into it anyway, basically because it’s the current hype and he wanted to see how and where coding assistants can be useful. A coding assistant is built from a coding harness and a large language model. A harness is then a command execution and loop environment. Currently, common harnesses include Claude, OpenCode and Codex, whereas the models that one can use with these harnesses include Claude AI (which costs currently ~20€/month), z.ai (72€/year) or Deepseek (which is self-hosted).&lt;/p&gt;

&lt;p&gt;There are yet others, such as OpenClaw, which act as both a harness and a model. The big deal here is that OpenClaw also has access to your email, bank account, messenger services and identity, thus it’s supposed to be able to help people organise their lives. However, the security and financial implications of letting a statistical inference engine say things for you and make transactions on your behalf, shall we say, are fraught with difficulties. Max mentioned the lethal trifecta: access to private data, ability to externally communicate, and exposure to untrusted content. It’s not a good idea to give automated services so much access, as things can go wrong in very bad ways. To avoid potential issues, Max mentioned some advice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Don’t YOLO outside of a container”&lt;/li&gt;
&lt;li&gt;When giving an agent commit access to a repository, let it work on a copy of the repo, not the main repository itself&lt;/li&gt;
&lt;li&gt;Don’t give the agent any credentials&lt;/li&gt;
&lt;li&gt;Run agents within a VM/container&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although there are issues with using agents wantonly, they can still be useful. One can use them to generate code, run that code, check the output (e.g. via tests), and work from lists. The quality depends upon the size of the task, the quality of the surrounding code and the quality of the prompt given to the agent.&lt;/p&gt;

&lt;p&gt;Max found that LLMs know Perl rather well, yet the style is from around Perl 5.12. They know about the need for &lt;code&gt;use strict; use warnings;&lt;/code&gt;, which took years to bang into the heads of humans and can cope with function signatures, possibly because these are common in other languages. The coding agents mimic pre-existing code well. If one has good prompts (there exist examples on, e.g. GitHub) that provide a walkthrough of good software development, then the agent is reminiscent of an enthusiastic junior developer.&lt;/p&gt;

&lt;p&gt;He then discussed some example projects for which he’d used coding agents and the pluses and minuses he’d discovered. Sometimes things were hard-coded when they shouldn’t have been. There was extra code added for testing, but it wasn’t used in the actual code. He found that he needed to provide the agent with good API examples, good implementation ideas, and general program structure to get acceptable output. It’s possible to give agents templates of the desired coding style so that the output matches the way one wants code to look.&lt;/p&gt;

&lt;p&gt;Max also discussed some of the social, economic and other consequences of using coding agents.&lt;/p&gt;

&lt;p&gt;From a social perspective, the threshold for implementing a tool is massively reduced; it’s now much easier to implement an idea. Due to the low quality of code output, they’re ok for throwaway debugging tools, but not so much for senior-dev level production code. There is also the issue of money flows and their concentration in a few select companies. The point was also made about “pulling the ladder up”, meaning that junior developers aren’t really involved in programming anymore because so much is handled by the coding agent. The level of structured thought required for programming is not really there; one describes feature lists instead. Also, one doesn’t get the opportunity to make errors and learn from them in the same way. Debugging code becomes more difficult since it’s easier to debug code one has written oneself, and the skill itself atrophies somewhat because junior devs are less likely to want to do this.&lt;/p&gt;

&lt;p&gt;One long-term economic consequence was based on the subscription model that most hosters use. They want the service to be useful enough to you that you spend lots of money on tokens, but not so much that you want to cancel your subscription. From what I understand, many of the companies aren’t even covering their costs from the subscription income, so it’s hard to see how this model will continue to work long-term.&lt;/p&gt;

&lt;p&gt;The talk was an informative and thought-provoking introduction to the workshop’s overall theme: Agentic Perl.&lt;/p&gt;

&lt;h3&gt;
  
  
  Abigail - Sharding a database, twice
&lt;/h3&gt;

&lt;p&gt;Abigail has recently retired after having spent most of his working life at Booking.com. One of the experiences he had of working there was of sharding the enormous database behind Booking’s site to solve performance and size problems.&lt;/p&gt;

&lt;p&gt;The talk wasn’t about how to shard a database–this has been described elsewhere–it gave more of the background information as to why one would want to shard a database and some of the technical challenges in doing this. A “shard” is a horizontal partition of data in a database. By sharding a database, one can reduce the disk, memory and network requirements for access to the database, especially if the database is exceedingly large.&lt;/p&gt;

&lt;p&gt;The database at booking.com stores hotel inventory and contains ~1000 tables spanning 14 years of data. There are roughly 10^11 rows, with 10^10 to 10^11 row reads per day and 10^9 to 10^10 row updates per day. The processing was split across many read-only slave instances, yet there was only a single master and in 2013, the disks were filling up, and there was a lot of replication delay. Any downtime causes millions of Euros in lost income.&lt;/p&gt;

&lt;p&gt;After much discussion, the booking people decided to shard the database, with the requirements that there be: no downtime, no big switch to the new system, it needed to be reversible, all data for a single hotel should be in the same shard, a shard could not influence others, it needed to be easy to reshard, and the code changes needed to be minimal.&lt;/p&gt;

&lt;p&gt;In the end, they decided to split the database into four parts. This required updates to over 100 Perl files. They included fallbacks so that code still using legacy interfaces would still work while the new code that understood the sharding also did its job properly. They moved the data in batches, initially starting small and proceeding to larger chunks of data as they gained confidence that everything was working properly. For instance, they moved a single hotel at a time, starting with test hotels, then new hotels, then small countries and large countries and later ran everything in parallel. Once everything was moved, they removed the legacy DB handling code. The whole process from the initial meeting to all data having been moved took about 6 months.&lt;/p&gt;

&lt;p&gt;In 2024, the database was hitting its limits again: disk space was running out, there were deadlocks and wait timeouts, as well as various I/O limits being hit. They decided to double the number of shards and used a similar process to what they used back in 2013. This time, there was a bug in the code, which caused duplicate data to appear in queries, which meant that the site showed twice the number of rooms available in hotels. Oops! Fortunately, the bug was only in one location, and they were able to fix the problem quickly, which in the end only took 30 seconds. Afterwards, they could clean up the duplicated data. This required every row in the database to be inspected twice and then for the tables to be rebuilt to reclaim space. This process took roughly 2 months to complete.&lt;/p&gt;

&lt;p&gt;In the end, everything worked out, and the site is still chugging along well. I was left wondering if it will be another ten years before Booking needs to shard its databases again…&lt;/p&gt;

&lt;h3&gt;
  
  
  Lars Dɪᴇᴄᴋᴏᴡ (daxim) - Der Datentyp und die Datenbank
&lt;/h3&gt;

&lt;p&gt;It turns out that it’s rather difficult to handle and store complex data types in an SQL database. It is, however, possible to get close, but it’s a lot of work. This talk explained some of the details of how to achieve that.&lt;/p&gt;

&lt;p&gt;One can combine the available types in SQL with Boolean AND and OR to create more complex types via the UNION keyword. It would be a lot easier to do such things if database creators added native support to the databases, but it seems that this won’t happen, as SQL isn’t intended as a general-purpose programming language (something which would have the ability to create complex types from more basic types).&lt;/p&gt;

&lt;p&gt;One example presented of representing a complex data type in a database was that of a payment type. This could be, e.g. cash, online or via credit card. The overall type is a payment, but then one can have more specific types and store these sensibly within the database. Lars showed how to do this, but it wasn’t simple, and one had to be careful about how one ordered the construction of the types and tables in SQL so that everything worked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flavio S. Glock - PerlOnJava: A Perl Distribution for the JVM Part 1
&lt;/h3&gt;

&lt;p&gt;This was one of the most impressive talks at the workshop. The sheer amount of work, spread over many projects and many years, in order for this to work, was mind-blowing. Put very simply, Flavio has managed to get the Perl compiler and runtime working within the JVM. This is not an interpreter wrapping a Perl binary; this is Perl code compiled to native JVM bytecode, hence it can be used alongside Java, Kotlin or Scala code. His system requires Java 21+ and targets Perl 5.42+. This first talk was a high-level overview of the PerlOnJava project and some of its results.&lt;/p&gt;

&lt;p&gt;Using the JVM makes sense in many ways because the JVM has 30 years of optimisations, meaning that its JIT ability is now very good. Also, there are 500k+ libraries that one now has access to. The JVM is also container-aware and has support for Docker/Kubernetes. And Perl can run alongside other languages which already run on the JVM, of which there are now many.&lt;/p&gt;

&lt;p&gt;He’s managed to get Perl scripts to run unchanged on the JVM. It’s also possible to embed Perl in Java applications. The PerlOnJava application is a single jar file and has no external dependencies. It’s possible to run programs via &lt;code&gt;java -jar ...&lt;/code&gt; or via a wrapper &lt;code&gt;./jperl script.pl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The PerlOnJava project is derived from many earlier attempts to get Perl to run on Java and is most directly derived from the perlito project. There are 200,000 tests in the test suite and 400 Java files. Everything is JIT-optimised.&lt;/p&gt;

&lt;p&gt;It’s possible to run pure Perl CPAN modules as-is, and there are XS modules which can use the Java equivalents. The standard Perl test suites also work as-is in this environment. Because of the large amount of optimisation in the JVM, some code runs 5x faster than a pure Perl environment. However, for string operations, Perl is 2x faster than PerlOnJava. Flavio was able to compile and run &lt;code&gt;Image::ExifTool&lt;/code&gt;, which is a very large distribution. This is so large that it was too big for the JVM’s 64KB method size limit, yet he managed to get this to work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flavio S. Glock - PerlOnJava: A Perl Distribution for the JVM Part 2
&lt;/h3&gt;

&lt;p&gt;The second part of this talk was the technical deep dive into PerlOnJava.&lt;/p&gt;

&lt;p&gt;Unicode was a problem because Java handles this differently from how Perl does it, but this now works as expected.&lt;/p&gt;

&lt;p&gt;Flavio needed to handle Perl’s special blocks, such as &lt;code&gt;BEGIN&lt;/code&gt;, &lt;code&gt;END&lt;/code&gt;, &lt;code&gt;INIT&lt;/code&gt;, and &lt;code&gt;CHECK&lt;/code&gt;, mapping them to equivalents in the JVM world.&lt;/p&gt;

&lt;p&gt;It’s sometimes possible for large Perl subs to exceed the JVM’s 64KB method size limit. The way to solve this was to have PerlOnJava fall back to an internal VM for oversized methods. The second backend was also necessary due to CPU cache pressure: sparse JVM bytecode overflows the instruction caches, hence one needs to fall back to another backend. Also, things like &lt;code&gt;eval STRING&lt;/code&gt; need to be handled in the internal VM because using &lt;code&gt;eval&lt;/code&gt; like this doesn’t meet the JVM’s security measures, and if one had left it as-is, then the JVM would be running the same code each time, making things much slower. The second backend helps with getting this kind of code to run with better performance.&lt;/p&gt;

&lt;p&gt;Flavio also handled scalars, arrays, hashes, subs/methods, and globs specially so that they translate nicely to their JVM equivalents. He described LOTS of detail about how to get Perl to work within the JVM, and there was a lot of stuff to cover to get Perl code to run as-is within the JVM. One comment he made summed this up nicely: “Perl was never designed for the JVM - but careful engineering makes it work”.&lt;/p&gt;

&lt;p&gt;There were some limitations, because not everything maps 100% from Perl to the JVM: &lt;code&gt;fork&lt;/code&gt; isn’t available on the JVM, and there didn’t seem to be a solution to that just yet. Also, &lt;code&gt;DESTROY&lt;/code&gt; can’t work because of the nondeterministic nature of the JVM’s garbage collection.&lt;/p&gt;

&lt;p&gt;Nevertheless, this was impressive work! Wow!&lt;/p&gt;

&lt;h3&gt;
  
  
  Lars Dɪᴇᴄᴋᴏᴡ (daxim) - Aus dem Nähkästchen
&lt;/h3&gt;

&lt;p&gt;In this talk, Lars showed technical things that help him personally and at work.&lt;/p&gt;

&lt;p&gt;For instance, he shares his dotfiles in a repo on GitHub.&lt;/p&gt;

&lt;p&gt;There are some tools available to get better diffs in &lt;code&gt;git&lt;/code&gt; than the defaults. E.g. &lt;code&gt;delta&lt;/code&gt;, &lt;code&gt;difft&lt;/code&gt; and the &lt;code&gt;--color-words&lt;/code&gt; option to the standard &lt;code&gt;diff&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Some tools were replacements for existing and common Unix tools, which also enhance the standard behaviour. For example: &lt;code&gt;eza&lt;/code&gt; is a replacement for &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;zoxide&lt;/code&gt; is a replacement for &lt;code&gt;cd&lt;/code&gt;, and &lt;code&gt;xh&lt;/code&gt; is a replacement for &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;He also mentioned &lt;code&gt;mise&lt;/code&gt;, which is a version manager for programming languages and tools. Instead of using perlbrew, rustup, and so on, one only needs the single tool.&lt;/p&gt;

&lt;p&gt;Handy to know!&lt;/p&gt;

&lt;h3&gt;
  
  
  Thomas Klausner (domm) - Using class
&lt;/h3&gt;

&lt;p&gt;In this talk, domm introduced us to the &lt;code&gt;class&lt;/code&gt; keyword that has been available since Perl 5.38. Perl also has the &lt;code&gt;field&lt;/code&gt; and &lt;code&gt;method&lt;/code&gt; keywords, which make it possible to write modern OOP code in core Perl. &lt;code&gt;field&lt;/code&gt; is like &lt;code&gt;has&lt;/code&gt; in &lt;code&gt;Moose&lt;/code&gt;. The &lt;code&gt;Object::Pad&lt;/code&gt; project is being used as a test bed for new OOP features in core Perl, and slowly, the stable features from that distribution are making their way into the core language. Paul Evans has been doing a huge amount of work to get this going.&lt;/p&gt;

&lt;p&gt;domm showed how he used the new Perl OOP features to handle conversion from one bibliographic format to another (MAB2 -&amp;gt; MARC21).&lt;/p&gt;

&lt;p&gt;MAB2 (Maschinelle Austauschformat für Bibliotheken) is from 1973, and MARC21 is originally from the 1960s and was updated in 1999 and is now XML-based.&lt;/p&gt;

&lt;p&gt;domm wrote a set of classes to handle conversion from one format to the other.&lt;/p&gt;

&lt;p&gt;Some notes about Perl’s new OOP features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;:reader&lt;/code&gt; keyword automatically creates an accessor from a field.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;:param&lt;/code&gt; keyword allows the field to be set at instantiation.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;ADJUST&lt;/code&gt; keyword allows code to be called during object construction.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;method&lt;/code&gt; uses function signatures directly; automatically provides &lt;code&gt;$self&lt;/code&gt;, thus it’s no longer necessary to do &lt;code&gt;my $self = shift;&lt;/code&gt; anymore.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was nice to see the new OOP features being used in a real-world project rather than the standard &lt;code&gt;Point&lt;/code&gt; class or something similar. Real-world code tends to bump up against the sharp edges of reality more, and hence, one can better see if the new features are applicable in other less-than-pure situations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lee Johnson - I Bought A Scanner (No, Really This Time)
&lt;/h3&gt;

&lt;p&gt;In a previous talk, Lee had discussed a scanner that he’d been thinking of buying, but it turned out to be waaaay too expensive and much too outdated to use. Its quality was second-to-none, though, hence why he’d considered the purchase in the first place. This would have been one way for him to get scans of photos from his various multi-year photographic projects that would have good quality. This new talk described the scanner he ended up getting.&lt;/p&gt;

&lt;p&gt;One thing I didn’t know is that the new security scanners at airports destroy photographic film. I guess there just aren’t that many people going through airports with old-fashioned film anymore. This makes things rather difficult for people who travel with old-style cameras, and hence Lee travels with a film-based camera much less frequently now.&lt;/p&gt;

&lt;p&gt;The scanner he’d originally considered, which would allow him to scan large prints in good quality, required proprietary software, was last updated in 2012 and required a 32-bit architecture to run. Thus, he needed an old Mac running a very old version of MacOSX for things to work at all. Thus, the system can’t ever be updated, and it’s difficult to know if the hardware and software will continue working in the future. Also, the connector used FireWire, which was dodgy, breaking down and having connection issues, so that made things even harder. The scanner itself was EOL, and the physical ports were dying.&lt;/p&gt;

&lt;p&gt;One alternative that he considered was to use a high-resolution camera to take digital photos of the film. This did seem a bit odd because one is taking a photo of a photo just so that one can get a digital rendition of the original. I can totally see the point, though, as in essence that’s what a scanner is doing, albeit in much better quality. One issue with using a digital camera is keeping the film flat, because even a small amount of curvature in the film creates a large change in the scan.&lt;/p&gt;

&lt;p&gt;The scanner he found and bought was cheaper than the previous scanner he was looking at, and is basically an older model of what he’d been looking at. One positive aspect was that it used SCSI, which is more robust than FireWire. Although using a digital camera to scan film can come close to the quality of what the scanner created, it wasn’t good enough. The scanner scanned the images well within specifications (Lee used a special reference to check).&lt;/p&gt;

&lt;p&gt;The main downside is that the scanner only works with a MacG4, and it won’t last forever. Effectively, the scanner will stop working due to the “upgrade treadmill”, which Lee then discussed in depth. He mentioned many instances and issues with trying to keep old hardware and software running just to use what is, in reality, still good equipment. He mentioned that the upgrade treadmill seems to be getting faster or is becoming steeper; some people at work are effectively employed to just keep updating dependencies for the main software systems. This seems like a crazy situation to be in; however, I’ve experienced it myself at previous jobs. Keeping up with the updates of dependencies, or swapping out dependencies if they go EOL and one has to find a replacement, took up a lot of time from what could have been spent on actual software development.&lt;/p&gt;

&lt;p&gt;Lee has now been able to get high-quality scans of many of the photos from his various projects, so that part of the story had a happy end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 2
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Richard Jelinek (TheWhip) - Perl mit AI
&lt;/h3&gt;

&lt;p&gt;This talk was split into two parts: the first part described the trials and tribulations he’d faced in installing and setting up controlling and monitoring systems in houses for friends and family. The second part presented his implementation of a JIT-ed and parallel Perl.&lt;/p&gt;

&lt;p&gt;When constructing the various houses, he wanted to use a Perl-based solution for the controlling and monitoring system. However, one system, &lt;code&gt;MisterHouse&lt;/code&gt;, was dead, and another, &lt;code&gt;FHEM&lt;/code&gt;, was difficult to use. In the end, he wrote his own and, to a certain degree, created his own hardware for the monitoring solution. A lot of this was guided by AI to get all of the various parameters within the desired specifications and to get the code written.&lt;/p&gt;

&lt;p&gt;Richard had wished for a Perl that ran in parallel for a long time and mentioned his wish-list for such functionality. He then implemented a system of his own with the help of AI and showed a demonstration of using his parallel and JIT-ed Perl to render the Mandelbrot set.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alexander Thurow (Alex) - Thoughts on (Modern?) Software Development - Beobachtungen von einer 21-jährigen Reise
&lt;/h3&gt;

&lt;p&gt;Alex shared lots of advice and anecdotes from many years of programming and helping teams do software development. He’s now a freelancer doing software development, mentoring, communication, and software development culture; the slides from his talk are available on &lt;a href="https://onmoderndev.de" rel="noopener noreferrer"&gt;https://onmoderndev.de&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;He discussed diverse “soft” topics in software development and the interactions between people when doing software development. He noted that continual learning is the key to mastery in every field. It’s difficult to deal with differing requirements in projects, e.g. quality versus time/budget, maintainability versus time-to-market, etc. He mentioned that communication is one of the most difficult things we can do as humans. And because code is communication, it’s important to realise that if you think that code is completely stupid, then it’s a sign that one doesn’t know what the pressures were that created the code. In other words, context is very important when reading old code from someone else.&lt;/p&gt;

&lt;p&gt;He also mentioned that in IT, we seem to work in cycles; topics, themes, frameworks, and ideas keep repeating. Thus, if one is aware of the basic patterns, then one can adapt to the latest trends and frameworks.&lt;/p&gt;

&lt;p&gt;He also discussed several challenges at the micro and macro-level of software development and their effect, e.g. at a societal level.&lt;/p&gt;

&lt;p&gt;He recommended many books, talks, and blog posts, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Book: “The mythical man-month” by Fred Brooks&lt;/li&gt;
&lt;li&gt;Book: “Pragmatic thinking and learning: refactor your wetware” by Andy Hunt&lt;/li&gt;
&lt;li&gt;Talk: &lt;a href="https://prezi.com/p/7ifumnpcggku/fantastic-biases-and-where-to-find-them-in-software-development/" rel="noopener noreferrer"&gt;Fantastic biases and where to find them in software development&lt;/a&gt; (Michael Kutz and João Proença)&lt;/li&gt;
&lt;li&gt;Blog series about refactoring: &lt;a href="https://www.digdeeproots.com/articles/on/naming-process/" rel="noopener noreferrer"&gt;https://www.digdeeproots.com/articles/on/naming-process/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Lars Dɪᴇᴄᴋᴏᴡ (daxim) - Hierarchien in SQL
&lt;/h3&gt;

&lt;p&gt;Lars showed how to describe graph-like hierarchies in SQL. It wasn’t 100% clear to me where the impetus came to do this, but it was impressive that it’s possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sören Laird Sörries - Digitale Souveränität und Made in Europe
&lt;/h3&gt;

&lt;p&gt;These days, we rely more and more on digital services and many of the big players that we rely on most are based in the US. This is sort of like having a single point of failure in a software system. Thus, there is a movement to migrate one’s online services to equivalent ones in the EU. It seems that it’s possible to migrate to “100% made in Europe” for software services; however, it seems practically impossible in the case of hardware. One other reason for such a movement is to reduce the fallout from enshittification coming from large tech companies.&lt;/p&gt;

&lt;p&gt;Sören then discussed various categories of services and mentioned providers that one could use in the EU. Services include: Payments, Cloud, Email, Chat, Office suites, Maps/Navigation, Search, Social media, Music, Video conferencing, and Translation. It turns out that there is a wealth of available services in the EU to choose from that have the same functionality as the large tech companies. The alternatives often seem to be based in Germany, France, the Netherlands or Scandinavia.&lt;/p&gt;

&lt;h3&gt;
  
  
  Salve J. Nilsen (sjn) - What might a CPAN Steward organization look like?
&lt;/h3&gt;

&lt;p&gt;The EU’s Cyber Resilience Act has far-reaching consequences for manufacturers and their products. Basically, that means that any product bearing the CE label requires the manufacturer to be liable for the security of their products, including any open source components in the dependency tree. The documentation has to be up to date and correct, and the metadata has to be complete and not misleading. They also need to be able to respond to risk assessments and maintain compliance.&lt;/p&gt;

&lt;p&gt;Some products can have tens of thousands of dependencies, most of which are open source, and hence manufacturers have to show that they have done due diligence in ensuring their products and the software that their products depend on are secure and standards-compliant. This is a huge task, hence Salve has come up with the idea of a community-owned non-profit steward cooperative. The idea being that projects can come under this umbrella, and manufacturers can pay for a kind of time-limited certificate showing compliance for the Perl-based software that they’re using. This takes a lot of the work off the shoulders of manufacturers to show that their software is compliant and could potentially funnel a lot of money into the open source Perl community, which could then be used to give maintainers a living wage, fund conferences and meetups such as the Perl Toolchain Summit. The steward is there to support projects and try to sustain them over time.&lt;/p&gt;

&lt;p&gt;It’s definitely an interesting idea and would be great if something like that could work. If one considers the amount of money some companies make from software that they can use for free, then funnelling even a small part of their profits back to the open source maintainers would be awesome.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 3
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Harald Jörg (haj) - Talking to PipeWire
&lt;/h3&gt;

&lt;p&gt;Following on from &lt;a href="https://act.yapc.eu/gpw2025/talk/7938" rel="noopener noreferrer"&gt;Harald’s talk from last year’s workshop&lt;/a&gt; &lt;a href="https://haraldjoerg.github.io/sfs/" rel="noopener noreferrer"&gt;(Sound from Scratch)&lt;/a&gt; in which he generated sound directly from Perl, he wanted to detect things such as when a microphone is plugged in or when a sound was played by an external program. For this task, he used &lt;a href="https://www.pipewire.org/" rel="noopener noreferrer"&gt;PipeWire&lt;/a&gt;, which&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;provides a low-latency, graph-based processing engine on top of audio and video devices that can be used to support the use cases currently handled by both PulseAudio and JACK.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course, he wanted to be able to use PipeWire from Perl, hence he needed to interact with the C-based library somehow. He tried out the API tutorial, then &lt;code&gt;Inline::C&lt;/code&gt;, then &lt;code&gt;h2xs&lt;/code&gt;, but found that it wasn’t very easy and eventually landed on &lt;code&gt;FFI:Platypus&lt;/code&gt; as the method which worked best in order for Perl to communicate with PipeWire.&lt;/p&gt;

&lt;p&gt;Because XS isn’t so easy to use, and because Dave Mitchell wants to rewrite the XS tutorial, Harald wanted to wait until Dave has finished with the tutorial before trying out XS again.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;FFI::Platypus&lt;/code&gt;, one can build C interfaces without XS. It’s possible to use this module to make a connection to PipeWire, but some C code was necessary to get everything to go properly. Harald found that some functions were defined as &lt;code&gt;static&lt;/code&gt;, which meant that FFI couldn’t find them automatically. It turns out that there’s a workaround for this issue, which lets everything work. Thus, one can make static functions and macros available to Perl via self-written wrappers. However, if there are lots of structs, then there is a lot of manual translation of C declarations necessary in order for everything to work, and it turns out that there are several constructs in PipeWire which can’t be mapped to &lt;code&gt;FFI::Platypus&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To work around these issues, Harald used &lt;code&gt;Convert::Binary::C&lt;/code&gt;, which operates on C header files and sources (ironically, not on binaries). &lt;code&gt;CBC&lt;/code&gt; gave insight into the C constructs, which then helped create Perl classes equivalent to the C structs and might also help with creating XS typemaps.&lt;/p&gt;

&lt;p&gt;He ran into a bug when trying to play sound with threaded Perl, which caused a segfault. It turns out that the issue doesn’t arise when using non-threaded Perl. Since most Linux distributions provide a threaded Perl, it’s necessary to build Perl yourself (which itself builds a non-threaded Perl by default) to work around the problem.&lt;/p&gt;

&lt;p&gt;Harald managed to get a lot of what he wanted to achieve to work, but he won’t be able to get much further with his initial goals. To get as far as he did, it was necessary to use a current, stable Linux version, a non-threaded Perl and a recent GCC version to get everything to compile. The &lt;code&gt;CBC&lt;/code&gt; config is rather fragile and difficult to get just right.&lt;/p&gt;

&lt;p&gt;He found that &lt;code&gt;FFI::Platypus&lt;/code&gt; was easy to learn, and it works with libraries from various languages. However, it needs declarations for every function call and every data type, which is a lot of work. It didn’t work out of the box with the libraries he tried so far, yet there are workarounds, but they are tedious. He also found &lt;code&gt;Convert::Binary::C&lt;/code&gt; to be a good companion to &lt;code&gt;FFI::Platypus&lt;/code&gt; or XS, but it was not a replacement. &lt;code&gt;CBC&lt;/code&gt; allows introspection and code generation, which one can then use with &lt;code&gt;FFI&lt;/code&gt; or XS wrappers. Unfortunately, it doesn’t support GCC extensions, which some libraries use extensively. Also, its configuration can be tedious and brittle.&lt;/p&gt;

&lt;p&gt;I liked Harald’s overview of what’s possible with XS and &lt;code&gt;FFI::Platypus&lt;/code&gt; for getting Perl to work with libraries from other projects. I have only really played with XS, and it’s interesting to see what other options are available and what the plus and minus points of each are.&lt;/p&gt;

&lt;h3&gt;
  
  
  Herbert Breunung (lichtkind) - Raku Grammars
&lt;/h3&gt;

&lt;p&gt;Herbert started his talk by explaining a bit of the background of the Raku language, its community and ecosystem. Then he spent some time showing examples of Perl and Raku code and contrasting the differences in behaviour. This was presented as a kind of quiz to see how well-known things from Perl work in Raku. Then he started to introduce grammars in Raku and showed that it’s very easy to generate a parser for a given grammar definition. Unfortunately, due to time constraints, he wasn’t able to finish discussing all the things he’d planned to discuss.&lt;/p&gt;

&lt;h3&gt;
  
  
  Raja Renga Bashyam - Perl’s T20 to Test Match Moments of Fibenis: Adaptive system evolving on Natural Lang. Principles
&lt;/h3&gt;

&lt;p&gt;Raja travelled all the way from India to give a talk at the workshop. I found that very impressive! The workshop has become much more international, with participants coming from England, the Netherlands, Austria, Switzerland, the US, as well as, of course, Germany. But wow, to have a visitor from so far away made an impression.&lt;/p&gt;

&lt;p&gt;Raja works at the company Webstars Codegram Informatics, which creates the &lt;a href="https://fibenis.org/" rel="noopener noreferrer"&gt;Fibenis tool&lt;/a&gt;. His talk contrasted various aspects of Perl with the game of cricket. As someone originally from a Commonwealth country, I could completely relate to the idea. Interestingly enough, I left the Commonwealth before the T20 variant of the game became popular; I’m much more familiar with the 1-day and test match (5-day) cricket variants.&lt;/p&gt;

&lt;p&gt;One can compare some roles in cricket with roles that Perl takes. For instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bowling: the delivery maps to shell and automation&lt;/li&gt;
&lt;li&gt;Batting: the score maps to text and regex&lt;/li&gt;
&lt;li&gt;Fielding: the defence maps DB abstraction&lt;/li&gt;
&lt;li&gt;Keeping: the catch maps to debug and pre-compiling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, some players in cricket can perform many roles. These are called “allrounders”, and Raja presented the case that Perl is an allrounder.&lt;/p&gt;

&lt;p&gt;In cricket, there are three main variations on the game: T20, which is fast-paced and lasts only three hours; one-day matches, which have 50 overs for each side, and take roughly one day to play (actually about 7 hours); lastly, there are test matches, which take 5 days of roughly 7-8 hours each to play. When comparing cricket to Perl, we can make the association that T20 is like one-liners: short and fast. Then one-day matches are like mini tools and utilities. And finally, test matches are like large-scale applications. Thus, Perl is an all-format all-rounder, i.e. can play any game variation and can fulfil many roles.&lt;/p&gt;

&lt;p&gt;Raja then spent the rest of the talk describing how his company uses ideas and patterns from Perl to create flexible web-based applications for their customer’s needs. Interestingly enough, the example code that he showed was in PHP. I asked him about this afterwards, and he said that yes, some of the code had moved to PHP, but the basic ideas that had been taken from Perl were still there. He also mentioned that his company plans to open-source its software in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Paul Cochrane (ptc) - Getting FIT in Perl
&lt;/h3&gt;

&lt;p&gt;Next came my talk, where I described the &lt;code&gt;Geo::FIT&lt;/code&gt; module, which one can use to parse Garmin FIT files. I discussed examples of what data is available in such files and what one could (potentially) do with that data. There were a couple of questions at the end of the talk, so I get the feeling that it went down ok. One thing that probably didn’t come across in the demo at the end of the talk was that the file I analysed and displayed data from was taken on one of the stages of my trip from Hannover to Berlin. The bike trip was thus in a way a requirement for the talk so that I had fresh data to play with.&lt;/p&gt;

&lt;p&gt;The slides of my talk are available on my &lt;a href="https://peateasea.de/talks/" rel="noopener noreferrer"&gt;talks page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Julien Fiegehenn (simbabque) - Turning humans into SysAdmins (without having to be one first)
&lt;/h3&gt;

&lt;p&gt;Many of Julien’s recent talks have been about how to turn young developers into Perl programmers (or software developers in general). Because he’s been through the German apprenticeship system and now lives and works in the UK, he’s made a modified version of that system for his company so that it works within the British context.&lt;/p&gt;

&lt;p&gt;This time, Julien was presented with a difficult problem: how to create a similar career development and progression program for sysadmins? This is especially challenging as a trainer if one isn’t a sysadmin oneself. Since none of the sysadmins at work had the time or desire to train newcomers, it fell on him as a trainer to come up with a solution. His strategy involved a mix of human and AI information to come up with such a training program. He interviewed the sysadmins at work to find out what their day-to-day work involved. Then he fed the transcripts of the interviews as well as the structure of the German software developer apprenticeship program into Google Gemini to iteratively create teaching materials for new sysadmins. With lots of iteration and plenty of review by actual humans (that was an important part of the process), he was able to create teaching materials, sysadmin guidelines, as well as a clear training progression path for new sysadmins. It was necessary to go through everything page by page and chapter by chapter to really understand everything, not only at a high level. In the end, he wrote most of it himself, yet the AI was useful in getting the initial structure and content in place. The documents were then taken to the sysadmin team and discussed with them so that they could give feedback and improve everything. In the end, it seemed like the project was a success, so hopefully, Julien will be turning humans into sysadmins in the near future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thomas Klausner (domm) - Deploying Perl apps using Podman, make &amp;amp; gitlab
&lt;/h3&gt;

&lt;p&gt;domm had given talks in the past about deploying Perl apps using Docker, GitLab and Kubernetes, as well as using Podman and Ansible for Perl app deployment. This talk was another variation on this theme.&lt;/p&gt;

&lt;p&gt;Building and deploying applications takes place in the CI pipelines within GitLab. He’d developed this particular pattern in the context of his company, Validad, where he has lots of Perl backends running in containers. Using Podman simplifies deployment because it’s much like Docker, and one can use &lt;code&gt;podman-compose&lt;/code&gt;, which is like &lt;code&gt;docker-compose&lt;/code&gt; to build and run container-based applications. Also, since all his backends are small and run in one stage on one node, there’s no need for fancy autoscaling, hence one can avoid, e.g. Kubernetes. He uses &lt;code&gt;systemd&lt;/code&gt; to start and stop services, uses &lt;code&gt;gopass&lt;/code&gt; for secrets management, and most of the processes are coordinated via &lt;code&gt;Makefile&lt;/code&gt;s, which call Ansible playbooks to do the actual deployment.&lt;/p&gt;

&lt;p&gt;Using containers simplifies application development, and he gave some advice on how to use containers well, e.g.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One should use multi-stage builds to reduce image size.&lt;/li&gt;
&lt;li&gt;There should be one service per container.&lt;/li&gt;
&lt;li&gt;There’s no need for &lt;code&gt;local::lib&lt;/code&gt; or &lt;code&gt;perlbrew&lt;/code&gt; inside a container.&lt;/li&gt;
&lt;li&gt;One can use well-known paths within containers instead of setting them dynamically in a configuration file.&lt;/li&gt;
&lt;li&gt;One can use volume mounts to get files from a node to the container and then share these between containers.&lt;/li&gt;
&lt;li&gt;One should pass the environment config to the container via environment vars, or as an &lt;code&gt;env&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found his presentation of Podman interesting because I’ve only ever used Docker myself, and finding out about this alternative was good information to learn. Podman calls itself “the best free and open source container tools”. Some of the advantages of Podman are that it can run rootless, doesn’t need a daemon (which Docker does), and one can run a container as a given user (Docker usually runs the container as &lt;code&gt;root&lt;/code&gt;, which can be a security issue). The &lt;code&gt;docker-compose&lt;/code&gt; equivalent isn’t as good as what’s available in Docker, and it uses a &lt;code&gt;Containerfile&lt;/code&gt; instead of a &lt;code&gt;Dockerfile&lt;/code&gt;, but it sounds to be much the same as what’s in Docker. Podman can create a pod, which is a collection of containers, all sharing a network.&lt;/p&gt;

&lt;p&gt;As mentioned above, domm uses &lt;code&gt;systemd&lt;/code&gt; to run user-specific services and finds that it works well together with Podman.&lt;/p&gt;

&lt;p&gt;Application deployment is triggered with a special &lt;code&gt;git&lt;/code&gt; tag with a specific deployment name. Thus, not each push gets built, tested, and its container deployed. This saves on resources, and the devs have direct control of when an application is deployed. Deployment is then handled by special &lt;code&gt;make&lt;/code&gt; targets.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Makefile&lt;/code&gt;s, there’s a lot of intelligence built into the make targets to create the relevant deployment tags and push new code. One can use, e.g. &lt;code&gt;make release stage=beta&lt;/code&gt; to deploy an application to the staging environment (the testing environment is called &lt;code&gt;alpha&lt;/code&gt;, however, prod is still called &lt;code&gt;production&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Lots of work has also gone into configuring GitLab-CI so that it works the way he wants. He makes use of child pipelines for various subtasks and avoids putting all steps within a CI pipeline; all steps are wrapped behind appropriate make targets, thus running things in CI is often as simple as running &lt;code&gt;make&lt;/code&gt;. With the setup used here, he’s also able to run the deployment locally by using the same &lt;code&gt;make&lt;/code&gt; commands and hence without needing GitLab-CI. This turns out to be very handy for testing deployment process changes.&lt;/p&gt;

&lt;p&gt;One thing about this whole setup is that I’ve created similar processes at my previous job and in other projects, so it’s interesting to see familiar patterns appear in someone else’s workflow. As they say: great minds think alike!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting home
&lt;/h2&gt;

&lt;p&gt;And with that, the conference was over. I went back to the hotel and did a lot of packing, unfortunately, not being able to squash everything back into my bags as compactly as I did on the way here. I had good fortune in that it didn’t rain on the way home!&lt;/p&gt;

&lt;p&gt;That evening, a few of us met up at an Italian restaurant, which was very helpful for me, because I needed to carbo-load for the following two days. After a yummy meal, and more interesting discussions with familiar faces, I headed back to the hotel to try to get some sleep before setting off early the next morning.&lt;/p&gt;

&lt;p&gt;The following two days went well; there wasn’t much wind, and on the second day, it came a little bit from behind me, which was nice. After many muesli bars and packets of nuts and raisins, I arrived home safely. Next year, I also plan to ride my bike to the workshop, but it won’t be as far as this year.&lt;/p&gt;

&lt;p&gt;Many thanks to the organisers, sponsors and participants for a fun workshop!&lt;/p&gt;

&lt;h2&gt;
  
  
  GPW2027
&lt;/h2&gt;

&lt;p&gt;Talking about next year’s workshop, Julien and I put ourselves forward to organise the workshop in Hannover in 2027. We’d been throwing the idea around for about the last 9 months and decided to take the plunge.&lt;/p&gt;

&lt;p&gt;See you next year in Hannover!&lt;/p&gt;

</description>
      <category>perl</category>
      <category>raku</category>
      <category>conferences</category>
    </item>
    <item>
      <title>Avoiding empty strings in non-nullable Django string-based model fields</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Wed, 11 Mar 2026 23:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/avoiding-empty-strings-in-non-nullable-django-string-based-model-fields-31bh</link>
      <guid>https://dev.to/peateasea/avoiding-empty-strings-in-non-nullable-django-string-based-model-fields-31bh</guid>
      <description>&lt;p&gt;Trying to save a null value to a non-nullable field in Django will raise an &lt;code&gt;IntegrityError&lt;/code&gt;, right? Well, not always. It turns out that Django saves string-based model fields as the empty string into the database instead. Usually, this is ok. For those times that it isn’t, you’ll need to add a constraint. Here, I explain how the situation arises and how to avoid it, if you want to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stumbling over unexpected (to me) behaviour
&lt;/h2&gt;

&lt;p&gt;Last year, while working on a web application for a client,&lt;sup id="fnref:hire-me"&gt;1&lt;/sup&gt; I stumbled over a small detail in &lt;a href="https://www.djangoproject.com/" rel="noopener noreferrer"&gt;Django&lt;/a&gt; that I’d not been aware of. The detail was that Django saves &lt;a href="https://forum.djangoproject.com/t/get-or-create-and-create-with-unspecified-non-nullable-fields/33755" rel="noopener noreferrer"&gt;non-nullable string-based model fields into the database as the empty string&lt;/a&gt;. I expected that trying to save a non-nullable field (i.e. one where &lt;code&gt;null=False&lt;/code&gt;) would raise an &lt;code&gt;IntegrityError&lt;/code&gt;, protecting me from doing anything silly. After all, that’s how most of the model fields behave. Unfortunately, not for string-based fields. So, the issue–if it is one for you–won’t manifest itself until you’re debugging some unexpected behaviour or happen to notice that a test passes when you expect it not to.&lt;/p&gt;

&lt;p&gt;To be clear: in most cases, this is not a problem. This, I think, at least partly, is why &lt;a href="https://docs.djangoproject.com/en/5.2/ref/models/fields/#django.db.models.Field.null" rel="noopener noreferrer"&gt;this is the expected behaviour&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let me explain. When you build a standard &lt;a href="https://en.wikipedia.org/wiki/Multitier_architecture" rel="noopener noreferrer"&gt;three-tier web application&lt;/a&gt; in Django, your form and Django’s default model field settings will protect you when users enter empty values into fields that shouldn’t be empty. The subtlety arises when you have code that saves data by manipulating model objects. Say you’re importing pre-existing data from CSV files; you’re not going to enter everything through an HTML form. You’ll write Python code to automate the process. But if the input data is missing a required string-based field, then you’ll pass &lt;code&gt;None&lt;/code&gt; (unwittingly or otherwise) as that field’s value. Django will convert the &lt;code&gt;None&lt;/code&gt; value into an empty string and save &lt;em&gt;that&lt;/em&gt; value to the database. It does this even though every other kind of model field in Django would raise an &lt;code&gt;IntegrityError&lt;/code&gt; in the same situation. This is what surprised me.&lt;/p&gt;

&lt;p&gt;Fortunately, I wasn’t the first person to spot this issue. &lt;a href="https://forum.djangoproject.com/u/cliff688/summary" rel="noopener noreferrer"&gt;Clifford Gama&lt;/a&gt; noticed this, &lt;a href="https://forum.djangoproject.com/t/get-or-create-and-create-with-unspecified-non-nullable-fields/33755" rel="noopener noreferrer"&gt;mentioned the issue in the Django forum&lt;/a&gt;, and submitted a &lt;a href="https://code.djangoproject.com/ticket/35671" rel="noopener noreferrer"&gt;pull request to the Django documentation&lt;/a&gt; (now merged) to clarify the situation. Yay Open Source Software development! He also &lt;a href="https://forum.djangoproject.com/t/get-or-create-and-create-with-unspecified-non-nullable-fields/33755/8" rel="noopener noreferrer"&gt;described how to make Django enforce a non-null constraint on string-based fields&lt;/a&gt;, should you want to ensure their data integrity.&lt;/p&gt;

&lt;p&gt;Since this subtlety in behaviour tripped me up, I thought I’d show how it can appear and present the solution that Clifford described.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with wibbly wobbly widgets
&lt;/h2&gt;

&lt;p&gt;Imagine a Django application called “Wibbly wobbly widgets”.&lt;sup id="fnref:dunno"&gt;2&lt;/sup&gt; If we make a model with a string-based field, we can observe its default behaviour. Later, we can constrain that behaviour to avoid saving null data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building a basic backend application
&lt;/h3&gt;

&lt;p&gt;Putting the project setup on overdrive, you can imagine doing something like this to get up and running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;create base directory&lt;span class="p"&gt;;&lt;/span&gt; would also be Git repo base
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;poetry new wibbly-wobbly-widgets
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;wibbly-wobbly-widgets/
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;add dependencies
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;poetry add django@^4 &lt;span class="c"&gt;# install Django; implicity creates .venv&lt;/span&gt;
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;poetry add pytest-django@^3 &lt;span class="c"&gt;# a pytest that plays with Django&lt;/span&gt;
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pytest needs six as a dependency, but didn&lt;span class="s1"&gt;'t install it ... weird
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;poetry add six
&lt;/span&gt;&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;activate the environment
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;create the Django project&lt;span class="p"&gt;;&lt;/span&gt; config &lt;span class="nb"&gt;dir &lt;/span&gt;contains settings.py
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;django-admin startproject config wibbly_wobbly_widgets
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;change into the project directory
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;wibbly_wobbly_widgets
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;create the Django app
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python manage.py startapp wwwidgets
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;run initial migrations
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the basic project and app structure in place, we can add a model to &lt;code&gt;models.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WobblyWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;wobble_factor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FloatField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can name our wobbly widgets and specify how much they wobble. Because we’ve not specified a default value, the &lt;code&gt;name&lt;/code&gt; field should be required. If we don’t specify the &lt;code&gt;wobble_factor&lt;/code&gt;, then they get a default value.&lt;/p&gt;

&lt;p&gt;We can test the model’s behaviour by putting these tests into &lt;code&gt;tests.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.test&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;wwwidgets.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;WobblyWidget&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestWobblyWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_saving_widget_sets_all_fields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;bungo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WobblyWidget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bungo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;wobble_factor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bungo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bungo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bungo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wobble_factor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_saving_widget_without_wobble_sets_default_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;bungo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WobblyWidget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bungo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bungo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wobble_factor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensuring that we’ve added the app to the &lt;code&gt;INSTALLED_APPS&lt;/code&gt; configuration in &lt;code&gt;config/settings.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.admin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sessions&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.staticfiles&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wwwidgets&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we can make our migrations and run them to wire up the first stage of the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python ./manage.py makemigrations
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python ./manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the tests, we see that the basic setup works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config.settings pytest wwwidgets/tests.py
&lt;span class="go"&gt;================================ test session starts ================================
platform linux -- Python 3.9.2, pytest-8.4.2, pluggy-1.6.0
django: settings: config.settings (from env)
rootdir: /home/cochrane/tmp/wibbly-wobbly-widgets
configfile: pyproject.toml
plugins: django-3.10.0
collected 2 items

wwwidgets/tests.py .. [100%]

================================= 2 passed in 0.41s =================================
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All green!&lt;sup id="fnref:imagine-all-green"&gt;3&lt;/sup&gt; Yay!&lt;/p&gt;

&lt;h3&gt;
  
  
  Tacking on a frontend
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;But&lt;/em&gt; we don’t really have a full Django app yet. This is only the backend; we need a frontend as well. Time to add a view and a form.&lt;/p&gt;

&lt;p&gt;Add this code to &lt;code&gt;views.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.views.generic.edit&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CreateView&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;WobblyWidget&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NewWobblyWidgetView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WobblyWidget&lt;/span&gt;
    &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; __all__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this view, Django can make a form for us to create new wobbly widgets. In this case, we’ve told Django to use all fields in the form. We’ll call the view from &lt;code&gt;urls.py&lt;/code&gt; in a moment.&lt;/p&gt;

&lt;p&gt;Now create a &lt;code&gt;templates&lt;/code&gt; directory within the Django project directory (i.e. where &lt;code&gt;manage.py&lt;/code&gt; lives):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;templates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and create a template file therein called &lt;code&gt;wobbly_widget_create_form.html&lt;/code&gt;. Fill this file with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en-NZ"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;New Wobbly Widget&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Create a new Wobbly Widget&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      {% csrf_token %}
      {{ form.as_p }}
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"save-button"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Save"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is just enough HTML and Django template code to make a basic web form where we can enter data into the fields that the &lt;code&gt;NewWobblyWidgetView&lt;/code&gt; creates for us automatically.&lt;/p&gt;

&lt;p&gt;For Django to find this template, we need to add the &lt;code&gt;templates&lt;/code&gt; path to the &lt;code&gt;DIRS&lt;/code&gt; option of the &lt;code&gt;TEMPLATES&lt;/code&gt; configuration in &lt;code&gt;settings.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;TEMPLATES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;BACKEND&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.template.backends.django.DjangoTemplates&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DIRS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;templates&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;APP_DIRS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OPTIONS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;context_processors&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.template.context_processors.debug&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.template.context_processors.request&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth.context_processors.auth&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages.context_processors.messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re not quite there yet. The last step is to wire up the view with its URL path and its associated template in &lt;code&gt;urls.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;wwwidgets.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NewWobblyWidgetView&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;admin/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;NewWobblyWidgetView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;template_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wobbly_widget_create_form.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that done, we can start the local development HTTP server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python manage.py runserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and feast our eyes on our creation by opening &lt;code&gt;http://localhost:8000&lt;/code&gt; in a browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fylwoib7h0hkrmyfu3b74.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fylwoib7h0hkrmyfu3b74.png" alt="HTML form to create a Wobbly Widget" width="522" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="///assets/images/frankenstein-its-alive.jpg"&gt;It’s alive!&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Saving empty form fields is a no-no
&lt;/h3&gt;

&lt;p&gt;With a complete, albeit toy, application running, we can try saving the form data without entering a value into the &lt;code&gt;Name&lt;/code&gt; field. Django will tell you &lt;a href="///assets/images/im-sorry-dave-im-afraid-i-cant-do-that.gif"&gt;you can’t do that&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpeateasea.de%2Fassets%2Fimages%2Fnew-wobbly-widget-form-field-required.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpeateasea.de%2Fassets%2Fimages%2Fnew-wobbly-widget-form-field-required.png" alt="HTML form to create a Wobbly Widget requiring name field to be filled&amp;lt;br&amp;gt;
out" width="521" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! That’s the behaviour we want. After all, the default settings for Django model fields are &lt;code&gt;null=False&lt;/code&gt; and &lt;code&gt;blank=False&lt;/code&gt;. In other words, these two lines of code are equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# implicit
&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# explicit
&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;HOWEVER…&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  That’s me in the corner. That’s me with my ORM, losing my integrity
&lt;/h3&gt;

&lt;p&gt;Let’s extend the tests to check that saving a &lt;code&gt;WobblyWidget&lt;/code&gt; without setting the &lt;code&gt;name&lt;/code&gt; field raises an &lt;code&gt;IntegrityError&lt;/code&gt;, i.e., that saving null data to the database is disallowed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_saving_widget_without_input_barfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntegrityError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;WobblyWidget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the tests, you’ll see that this test fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config.settings pytest wwwidgets/tests.py
&lt;span class="go"&gt;================================ test session starts ================================
platform linux -- Python 3.9.2, pytest-8.4.2, pluggy-1.6.0
django: settings: config.settings (from env)
rootdir: /home/cochrane/tmp/wibbly-wobbly-widgets
configfile: pyproject.toml
plugins: django-3.10.0
collected 3 items

wwwidgets/tests.py .F. [100%]

===================================== FAILURES ======================================
______________TestWobblyWidget.test_saving_widget_without_input_barfs______________

&lt;/span&gt;&lt;span class="gp"&gt;self = &amp;lt;wibbly_wobbly_widgets.wwwidgets.tests.TestWobblyWidget testMethod=test_saving_widget_without_input_barfs&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;
    def test_saving_widget_without_input_barfs(self):
        with self.assertRaises(IntegrityError):
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;WobblyWidget.objects.create&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="go"&gt;E AssertionError: IntegrityError not raised

wwwidgets/tests.py:26: AssertionError
============================== short test summary info ==============================
FAILED wwwidgets/tests.py::TestWobblyWidget::test_saving_widget_without_input_barfs - AssertionError: IntegrityError not raised
============================ 1 failed, 2 passed in 0.52s ============================
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hang on, what? That should barf, shouldn’t it? After all, we set (either implicitly or explicitly) &lt;code&gt;null=False&lt;/code&gt; on the model field. Aye, there’s the rub: &lt;a href="https://docs.djangoproject.com/en/5.2/ref/models/fields/#django.db.models.Field.null" rel="noopener noreferrer"&gt;this is actually expected behaviour&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Avoid using null on string-based fields such as &lt;code&gt;CharField&lt;/code&gt; and &lt;code&gt;TextField&lt;/code&gt;. The Django convention is to use an empty string, not &lt;code&gt;NULL&lt;/code&gt;, as the “no data” state for string-based fields. If a string-based field has &lt;code&gt;null=False&lt;/code&gt;, empty strings can still be saved for “no data”. If a string-based field has &lt;code&gt;null=True&lt;/code&gt;, that means it has two possible values for “no data”: &lt;code&gt;NULL&lt;/code&gt;, and the empty string. In most cases, it’s redundant to have two possible values for “no data”. One exception is when a &lt;code&gt;CharField&lt;/code&gt; has both &lt;code&gt;unique=True&lt;/code&gt; and &lt;code&gt;blank=True&lt;/code&gt; set. In this situation, &lt;code&gt;null=True&lt;/code&gt; is required to avoid unique constraint violations when saving multiple objects with blank values.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the important part of that quote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Django convention is to use an empty string, not &lt;code&gt;NULL&lt;/code&gt;, as the “no data” state for string-based fields. If a string-based field has &lt;code&gt;null=False&lt;/code&gt;, empty strings can still be saved for “no data”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Time for me to update my mental model of how Django’s model fields work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diving deep into Django’s database dealings
&lt;/h3&gt;

&lt;p&gt;Let’s have a look at this in detail.&lt;sup id="fnref:i-love-details"&gt;4&lt;/sup&gt; We’ll use a combination of the &lt;code&gt;sqlite3&lt;/code&gt; command line and the Django interactive shell.&lt;/p&gt;

&lt;p&gt;Opening the database and having a quick look inside, we see the available tables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sqlite3 db.sqlite3
&lt;span class="go"&gt;SQLite version 3.34.1 2021-01-20 14:10:07
Enter ".help" for usage hints.
&lt;/span&gt;&lt;span class="gp"&gt;sqlite&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.tables
&lt;span class="go"&gt;auth_group django_admin_log
auth_group_permissions django_content_type
auth_permission django_migrations
auth_user django_session
auth_user_groups wwwidgets_wobblywidget
auth_user_user_permissions
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking in the &lt;code&gt;wwwidgets_wobblywidget&lt;/code&gt; table, we see that it’s initially empty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;sqlite&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select &lt;/span&gt;count&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; from wwwidgets_wobblywidget &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="go"&gt;0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, so good. This is what we expect since we’ve not added any objects to the database yet.&lt;/p&gt;

&lt;p&gt;In a separate terminal session, start the Django interactive shell, import the &lt;code&gt;WobblyWidget&lt;/code&gt; class, and create an object with all attributes set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./manage.py shell
&lt;span class="go"&gt;Python 3.9.2 (default, Jan 25 2026, 13:37:52)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; from wwwidgets.models import WobblyWidget
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; WobblyWidget.objects.create&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Tobermory"&lt;/span&gt;, &lt;span class="nv"&gt;wobble_factor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7.9&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;lt;WobblyWidget: WobblyWidget object (1)&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checking the database table in &lt;code&gt;sqlite&lt;/code&gt; directly (i.e. not through the Django ORM), we see a new row in the table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;sqlite&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select &lt;/span&gt;count&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; from wwwidgets_wobblywidget &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="go"&gt;1
&lt;/span&gt;&lt;span class="gp"&gt;sqlite&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; from wwwidgets_wobblywidget &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="go"&gt;1|7.9|Tobermory
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what we expect: we have one object, and it has its &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;wobble_factor&lt;/code&gt; fields set. All good.&lt;/p&gt;

&lt;p&gt;Now return to the Django shell. Create an object without a name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; WobblyWidget.objects.create&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="gp"&gt;&amp;lt;WobblyWidget: WobblyWidget object (2)&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;… which feels weird, because my gut feeling says that “shouldn’t” work. But anyway.&lt;/p&gt;

&lt;p&gt;What does the database say?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;sqlite&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; from wwwidgets_wobblywidget &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="go"&gt;1|7.9|Tobermory
2|1.0|
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, there’s a second entry there. The &lt;code&gt;wobble_factor&lt;/code&gt; field has the default value of &lt;code&gt;1.0&lt;/code&gt;, as it should. And there’s “nothing” in the name field. But what’s really in that field? Let’s put quotes around the value to see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;sqlite&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'"%s"'&lt;/span&gt;, name&lt;span class="o"&gt;)&lt;/span&gt; from wwwidgets_wobblywidget where &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="go"&gt;""
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yup, that’s definitely the empty string.&lt;/p&gt;

&lt;p&gt;What did this achieve? Well, we verified the documented behaviour. This is a Good Thing™. It also helps reinforce our new mental model of how this actually works.&lt;/p&gt;

&lt;p&gt;Note that for other model fields, setting the attribute to &lt;code&gt;None&lt;/code&gt; will raise an &lt;code&gt;IntegrityError&lt;/code&gt; as per normal.&lt;/p&gt;

&lt;p&gt;For example, we can try setting &lt;code&gt;wobble_factor=None&lt;/code&gt; when creating a &lt;code&gt;WobblyWidget&lt;/code&gt; object within the Django shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; WobblyWidget.objects.create&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;wobble_factor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;None&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;Traceback (most recent call last):
  File "/home/cochrane/tmp/wibbly-wobbly-widgets/.venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/home/cochrane/tmp/wibbly-wobbly-widgets/.venv/lib/python3.9/site-packages/django/db/backends/sqlite3/base.py", line 328, in execute
    return super().execute(query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: wwwidgets_wobblywidget.wobble_factor
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and this fails with an &lt;code&gt;IntegrityError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is also good. It’s also the expected, documented behaviour.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sticking shackles on strings
&lt;/h3&gt;

&lt;p&gt;But Paul, what if we &lt;em&gt;want&lt;/em&gt; to raise an &lt;code&gt;IntegrityError&lt;/code&gt; when saving &lt;code&gt;None&lt;/code&gt; to non-nullable string-based fields? Django gives us the flexibility to do this. &lt;a href="https://forum.djangoproject.com/t/get-or-create-and-create-with-unspecified-non-nullable-fields/33755/8" rel="noopener noreferrer"&gt;And Clifford described exactly how&lt;/a&gt;: we need to add a constraint to the model.&lt;/p&gt;

&lt;p&gt;Opening up &lt;code&gt;models.py&lt;/code&gt; again, we add a &lt;code&gt;Meta&lt;/code&gt; class inside the &lt;code&gt;WobblyWidget&lt;/code&gt; class, and define the non-null constraint there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;constraints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CheckConstraint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=~&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Q&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name_field_non_empty&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The argument to the &lt;code&gt;CheckConstraint&lt;/code&gt;’s &lt;code&gt;check&lt;/code&gt; option, &lt;code&gt;~models.Q(name="")&lt;/code&gt;, means: “check that the &lt;code&gt;name&lt;/code&gt; field is not the empty string”. The &lt;code&gt;~&lt;/code&gt; character is the Boolean &lt;code&gt;NOT&lt;/code&gt; operator, which is the negation of the &lt;code&gt;Q&lt;/code&gt; object’s query. Django shows the value of the &lt;code&gt;name&lt;/code&gt; option in error messages when the constraint is violated. Using a descriptive name for the constraint can save much pain when debugging an error in the future.&lt;/p&gt;

&lt;p&gt;With that in place, we need to remove our erroneous database table entry before we can migrate this change. Delete the entry within &lt;code&gt;sqlite&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;sqlite&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;delete from wwwidgets_wobblywidget where &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is it gone?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;sqlite&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; from wwwidgets_wobblywidget &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="go"&gt;1|7.9|Tobermory
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yup. All good.&lt;/p&gt;

&lt;p&gt;(Note: if you don’t remove this entry, then running the database migration that adds the constraint will fail.)&lt;/p&gt;

&lt;p&gt;Making the migration and running it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python ./manage.py makemigrations
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python ./manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;means that when we run the tests again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config.settings pytest wwwidgets/tests.py
&lt;span class="go"&gt;================================ test session starts ================================
platform linux -- Python 3.9.2, pytest-8.4.2, pluggy-1.6.0
django: settings: config.settings (from env)
rootdir: /home/cochrane/tmp/wibbly-wobbly-widgets
configfile: pyproject.toml
plugins: django-3.10.0
collected 3 items

wwwidgets/tests.py ... [100%]

================================= 3 passed in 0.39s =================================
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;… they pass! 🎉&lt;/p&gt;

&lt;p&gt;Returning to the Django shell, we’ll see that adding a &lt;code&gt;WobblyWidget&lt;/code&gt; without a name now fails as desired:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; WobblyWidget.objects.create&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="go"&gt;Traceback (most recent call last):
  File "/home/cochrane/tmp/wibbly-wobbly-widgets/.venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/home/cochrane/tmp/wibbly-wobbly-widgets/.venv/lib/python3.9/site-packages/django/db/backends/sqlite3/base.py", line 328, in execute
    return super().execute(query, params)
sqlite3.IntegrityError: CHECK constraint failed: name_field_non_empty
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the way: passing the empty string to the &lt;code&gt;name&lt;/code&gt; field will do the same thing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; WobblyWidget.objects.create&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;Traceback (most recent call last):
  File "/home/cochrane/tmp/wibbly-wobbly-widgets/.venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/home/cochrane/tmp/wibbly-wobbly-widgets/.venv/lib/python3.9/site-packages/django/db/backends/sqlite3/base.py", line 328, in execute
    return super().execute(query, params)
sqlite3.IntegrityError: CHECK constraint failed: name_field_non_empty
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can even add a test for this case, to really nail down the specified behaviour:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_saving_widget_barfs_when_name_is_empty_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IntegrityError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;WobblyWidget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the tests again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config.settings pytest wwwidgets/tests.py
&lt;span class="go"&gt;================================ test session starts ================================
platform linux -- Python 3.9.2, pytest-8.4.2, pluggy-1.6.0
django: settings: config.settings (from env)
rootdir: /home/cochrane/tmp/wibbly-wobbly-widgets
configfile: pyproject.toml
plugins: django-3.10.0
collected 4 items

wwwidgets/tests.py .... [100%]

================================= 4 passed in 0.41s =================================
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we see them all pass!&lt;/p&gt;

&lt;p&gt;Nice! I love it when a test suite comes together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;So what did we learn?&lt;/p&gt;

&lt;p&gt;First up: string-based fields in Django can accept &lt;code&gt;None&lt;/code&gt; values and will save these as the empty string into the database. This is expected and documented behaviour, and something to keep in mind.&lt;/p&gt;

&lt;p&gt;Next, we learned that we can override this behaviour if we want to.&lt;/p&gt;

&lt;p&gt;Lastly, the Open Source Software model worked very well. Someone spotted the issue, wrote up a workaround, and extended the docs to clarify things so that others aren’t tripped up in the future. Many thanks to Clifford Gama for his contributions!&lt;/p&gt;

&lt;h2&gt;
  
  
  Addendum: Remember to use &lt;code&gt;pytest-django&lt;/code&gt;, not plain &lt;code&gt;pytest&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Note: if you’ve installed &lt;code&gt;pytest&lt;/code&gt;, and have set everything up as per normal for a Django project, but get an error when running the tests that apps aren’t loaded yet, i.e.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;E django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then make sure that you’ve installed &lt;code&gt;pytest-django&lt;/code&gt;. Installing &lt;code&gt;pytest&lt;/code&gt; alone isn’t enough.&lt;/p&gt;

&lt;p&gt;One symptom of this situation is that running the tests with the standard Django test runner &lt;em&gt;works&lt;/em&gt;, but using &lt;code&gt;pytest&lt;/code&gt; &lt;em&gt;doesn’t&lt;/em&gt;. In other words, running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python manage.py &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;works as you would expect, but&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ DJANGO_SETTINGS_MODULE=config.settings pytest &amp;lt;path-to&amp;gt;/tests.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;fails with the error noted above.&lt;/p&gt;

&lt;p&gt;So, if you see the Django test runner working, but &lt;code&gt;pytest&lt;/code&gt; tells you the apps aren’t yet loaded, make sure you’ve installed &lt;code&gt;pytest-django&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Do you need a software developer who is persistent, flexible, and thorough? One who integrates well with existing teams, has broad experience, and thrives on legacy systems? If so, give me a yell! I’m available for freelance Python/Perl backend development and maintenance work. Contact me at &lt;a href="mailto:paul@peateasea.de"&gt;paul@peateasea.de&lt;/a&gt; and let’s discuss how I can help solve your business’s hairiest problems. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I &lt;em&gt;really&lt;/em&gt; don’t know where I got that idea from. I must have been half asleep or something. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’ll have to imagine the last couple of lines being green in the terminal output. This is the colour that &lt;code&gt;pytest&lt;/code&gt; uses for passing tests. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I love details. That’s where you end up learning &lt;em&gt;why&lt;/em&gt; something is the way it is. ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>django</category>
      <category>python</category>
    </item>
    <item>
      <title>StreetComplete: Pokémon Go for map geeks</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Wed, 04 Mar 2026 23:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/streetcomplete-pokemon-go-for-map-geeks-3go8</link>
      <guid>https://dev.to/peateasea/streetcomplete-pokemon-go-for-map-geeks-3go8</guid>
      <description>&lt;p&gt;A few years ago, while recuperating from our at that time “favourite” dreaded lurgy,&lt;sup id="fnref:yes-covid"&gt;1&lt;/sup&gt; I stumbled across StreetComplete, an Android app to update OpenStreetMap data in a fun and easy way. It’s reminiscent of games such as Pokémon Go. But instead of tracking down Pikachu, you update the world’s largest open mapping system, thus contributing to the wider community.&lt;/p&gt;

&lt;p&gt;This story is about how I discovered StreetComplete and my impressions of the app and its potential. Give it a go! I’m sure you’ll enjoy it. 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Nudged into active recovery
&lt;/h2&gt;

&lt;p&gt;Most of January 2023 was pretty much screwed for me because of Covid. While recovering, I did a lot of reading and in the process stumbled across a blog post by &lt;a href="https://shkspr.mobi/blog/" rel="noopener noreferrer"&gt;Terence Eden&lt;/a&gt;, in which he became &lt;a href="https://shkspr.mobi/blog/2023/01/how-i-became-the-1-mapper-in-new-zealand/" rel="noopener noreferrer"&gt;“the #1 mapper in New Zealand”&lt;/a&gt;. As a New Zealander myself (and as a geek), this piqued my interest. He achieved this feat by being the most active user in New Zealand within a seven-day period.&lt;sup id="fnref:while-on-holiday"&gt;2&lt;/sup&gt; To do this, he used &lt;a href="https://streetcomplete.app/" rel="noopener noreferrer"&gt;StreetComplete&lt;/a&gt;, an app which gamifies the process of updating &lt;a href="https://www.openstreetmap.org/about" rel="noopener noreferrer"&gt;OpenStreetMap&lt;/a&gt; metadata.&lt;/p&gt;

&lt;p&gt;After having read Terence Eden’s post, I thought that sounded interesting. It also gave me the impetus to get outside and moving again. I was definitely in need of some fresh air! It turned out to be a lot of fun and rather addictive. I highly recommend it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Like Pokémon Go, but more useful
&lt;/h2&gt;

&lt;p&gt;You use the app like how you play &lt;a href="https://en.wikipedia.org/wiki/Pok%C3%A9mon_Go" rel="noopener noreferrer"&gt;Pokémon Go&lt;/a&gt;: by walking around outside &lt;em&gt;in the real world&lt;/em&gt; (😱) and solving quests. The StreetComplete website sums this up well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This app finds missing map data in your vicinity and displays it on a map as quests. Solve each quest by visiting the location on-site and answering a simple question to update the map.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Community contributions
&lt;/h2&gt;

&lt;p&gt;Playing StreetComplete is great because you make a direct contribution to your local community. The quests you solve update OpenStreetMap, which contains a wealth of metadata about our physical environment. And it’s completely open. Sure, Google Maps shows me where the roads are, what the name of a business is and what that business’s opening hours are. But OpenStreetMap is so much more. For instance, OpenStreetMap contains data about pedestrian crossings that use audible tones or have tactile paving, allowing visually impaired people to navigate their surroundings. &lt;a href="https://www.walkersguide.org/en/" rel="noopener noreferrer"&gt;Apps have been built on this data&lt;/a&gt; so that &lt;a href="https://www.blindsquare.com/" rel="noopener noreferrer"&gt;people with visual impairments can navigate their city more safely and easily&lt;/a&gt;. How cool is that?&lt;/p&gt;

&lt;h2&gt;
  
  
  Inclusive applications
&lt;/h2&gt;

&lt;p&gt;What I find most appealing about OpenStreetMap is that it is &lt;em&gt;inclusive&lt;/em&gt;. It’s not only for data or geography geeks to have fun, nor is it only for people who want to drive their cars down to the shops. All members of a community can benefit. Importantly, through applications built on OpenStreetMap data, people with physical, visual, or mobility impairments can be more independent.&lt;/p&gt;

&lt;p&gt;Think of someone in a wheelchair, an elderly person using a walker to get around, or even a parent pushing a large pram. Each person needs to cross the street easily. And if you know where the street crossings are best, you can save energy and effort. That’s why OpenStreetMap contains detailed data about the properties of street crossings. And with StreetComplete, you help keep this information up to date. Are the crossings on the same level as the street? Or is there a slight bump to get from the street onto the footpath? Such information forms, for instance, the basis for &lt;a href="https://news.wheelmap.org/en/" rel="noopener noreferrer"&gt;navigation apps&lt;/a&gt; &lt;a href="https://route4u.org/" rel="noopener noreferrer"&gt;for people in wheelchairs&lt;/a&gt;. Now you can plan your route to the shops without having to stress about finding a good place to cross the road.&lt;/p&gt;

&lt;p&gt;These are the kinds of applications that benefit &lt;em&gt;everyone&lt;/em&gt; in a community, not only able-bodied people sitting in cars. That’s brilliant! And OpenStreetMap data is freely available; you’re not being tracked for the “new oil” that is your personal data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making map updates fun
&lt;/h2&gt;

&lt;p&gt;To be honest, I can’t rave about StreetComplete enough. The developers have managed to gamify the (potentially very dry) process of updating the world’s largest open mapping system and make it a hell of a lot of fun.&lt;/p&gt;

&lt;p&gt;There’s a low barrier to entry to use the app. Simply download from &lt;a href="https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete" rel="noopener noreferrer"&gt;Google Play&lt;/a&gt; or &lt;a href="https://f-droid.org/packages/de.westnordost.streetcomplete/" rel="noopener noreferrer"&gt;F-Droid&lt;/a&gt; and off you go. Currently, StreetComplete is only available on Android. However, there is &lt;a href="https://github.com/streetcomplete/StreetComplete/issues/5421" rel="noopener noreferrer"&gt;a plan to create an iOS version&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s intuitive and easy to use. When you start the app, it’s clear what quests there are to solve, and they’re often rather simple questions. For instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What kind of surface does this pathway have?&lt;/li&gt;
&lt;li&gt;Does this set of steps have a handrail?&lt;/li&gt;
&lt;li&gt;Does this bike stand have a roof (i.e. is it protected from the rain)?&lt;/li&gt;
&lt;li&gt;Does this bench have a backrest?&lt;/li&gt;
&lt;li&gt;Are the postal collection times still up to date?&lt;/li&gt;
&lt;li&gt;Does this bus stop have a seat?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are almost two hundred such questions in total, including standard questions about business opening hours, road names, and house numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://youtu.be/VqomZQMZQCQ" rel="noopener noreferrer"&gt;Maybe we &lt;em&gt;do&lt;/em&gt; need badges?&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;StreetComplete can be quite addictive. You get badges for achieving various milestones, which is cool and gives a bit of a dopamine kick. Also, you get the feedback that you’ve made a small, positive contribution to society.&lt;/p&gt;

&lt;p&gt;There are many badges one can receive. To give an idea of the kinds of achievements available, I’ve listed below some of the badges I collected back when I first started playing StreetComplete.&lt;sup id="fnref:german-language-setting"&gt;3&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Here’s the badge I received after having solved 60 building-related quests:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy31ni6n8ny12cl83cf0l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy31ni6n8ny12cl83cf0l.png" width="460" height="596"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This one is after solving 150 quests that help cyclists:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7iswxi2ejtp23zltjahw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7iswxi2ejtp23zltjahw.png" width="460" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and for solving quests that help people in spaces in nature:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzd19zk4pe16oye557vz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzd19zk4pe16oye557vz1.png" width="460" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then there’s the badge for solving 100 quests that help wheelchair users to find their way around:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2mk2lb8qbfckynwgkwp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2mk2lb8qbfckynwgkwp.png" width="460" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;… and the one I got after solving 60 quests relevant to visually impaired people:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgic98bhaz1gatakyig51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgic98bhaz1gatakyig51.png" width="460" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a city, there are several badges one can get, especially since cities are criss-crossed with streets:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7s9gei47htupcow30w7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7s9gei47htupcow30w7.png" width="460" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and thus there are some quests relevant to pedestrians:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5aiuxwdjbuqo3wog1ng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5aiuxwdjbuqo3wog1ng.png" width="460" height="636"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;or to citizens in general:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl38s8b7ge5jl2hkr6zp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl38s8b7ge5jl2hkr6zp8.png" width="460" height="691"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you continue long enough, you also get general badges, such as the “surveyor” badge. This achievement also unlocked the &lt;a href="https://satellitestud.io/osm-haiku/app/" rel="noopener noreferrer"&gt;OpenStreetMap Haiku app&lt;/a&gt; for me, as shown in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fez41id6sxbxlijtzxzeo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fez41id6sxbxlijtzxzeo.png" width="460" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, there are many ways you can contribute valuable information to OpenStreetMap by playing StreetComplete.&lt;/p&gt;

&lt;p&gt;As shown above, some of the badges unlock links to various OpenStreetMap applications. Many are serious. For instance, &lt;a href="https://cyclosm.org/" rel="noopener noreferrer"&gt;a map for cyclists&lt;/a&gt;, &lt;a href="https://wheelmap.org/" rel="noopener noreferrer"&gt;a map to find barrier-free access to buildings and places&lt;/a&gt;, or &lt;a href="https://indoorequal.org/" rel="noopener noreferrer"&gt;an app which shows maps for the interior of shopping centres and train stations, etc.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yet, some are also fun, such as &lt;a href="https://satellitestud.io/osm-haiku/app/" rel="noopener noreferrer"&gt;the app that uses OpenStreetMap data to generate a haiku&lt;/a&gt;. Using this “unlock” mechanism highlighted to me just how many applications have been built around the massive amount of information stored in OpenStreetMap. There seems to be this flourishing community of volunteers imagining and creating clever ways to use map data to make other people’s lives easier. That’s &lt;em&gt;way&lt;/em&gt; cool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Positive benefits of open data
&lt;/h2&gt;

&lt;p&gt;There are many positive side effects of playing StreetComplete beyond simply having fun. It’s a great way to discover a city you are visiting or even the city you’ve lived in for years. When I’m on holiday somewhere, I’ll play a bit of StreetComplete, and before long, I’m more aware of what’s where and hence navigating without an app becomes easier. I’ll know that there’s a bakery down that street, that the supermarket is up that way, and there’s a thousand-year-old tree up on the hill over there. I end up spotting details I’d have likely overlooked otherwise. Things like the funky little model car shop tucked away on a side street, the proliferation of hairdressers in one small area of a city, or water fountains disguised as sculptures. It’s fascinating.&lt;/p&gt;

&lt;p&gt;I’ve also started to get an appreciation of the barriers existing in daily life that, at first glance, aren’t obvious. Things like a path separated from a road by a high curb. This means that wheelchair users have to travel an extra distance just to cross the road. Or the lack of acoustic signals or tactile paving at pedestrian crossings that help visually impaired people. You often find tactile paving at train stations and bus stops, but it’s still amazing how little there sometimes is. Even whether a public transport stop has seating is good information to have. This is especially true for people who can’t stand for long when waiting, say, for a bus.&lt;/p&gt;

&lt;p&gt;A city or regional council wanting to improve infrastructure and make the physical environment more barrier-free and inclusive, need only look up the information in OpenStreetMap to find where more effort is needed. Local and regional councils are usually cash-strapped, so it’s a boon for them if they can use crowdsourced, open data.&lt;/p&gt;

&lt;p&gt;Similarly, having well-updated data about the surface and width of bike paths and footpaths can give local authorities the information they need to improve and interconnect such infrastructure. The potential benefits of well-used open data are enormous.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip: avoid automatic uploads
&lt;/h2&gt;

&lt;p&gt;There’s one tip I’ll give for anyone starting out with StreetComplete: it’s a good idea to turn off automatic synchronisation of solved quests. This option is on by default, and there will be times when you want to undo a recent change because it wasn’t correct. If automatic synchronisation is on, then you’ll have to fix the change later within OpenStreetMap itself. Thus, it can be a lot more work to correct a well-intentioned mistake. Since it’s easy to upload completed quests manually, it makes sense to switch off automatic uploads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go lose yourself in your surroundings!
&lt;/h2&gt;

&lt;p&gt;So what are you waiting for? Get the app and go and get lost! 😉 It’s heaps of fun!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Yes, I mean Covid. Yes, I’m being ironic about it being “favourite”. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Terence Eden isn’t a Kiwi; he’s from England and achieved his high score while on holiday in NZ. A year later, I was also on holiday there and briefly achieved the number one spot for the seven-day window. It wasn’t that hard; there don’t seem to be that many people in NZ playing StreetComplete. In Germany, however, if you want to get a number one spot, it’s a full-time job! ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Note that I use German on my phone, hence the language shown in the badge text. ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>general</category>
    </item>
    <item>
      <title>Forwarding a Vagrant-based Jekyll dev server to its host</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Wed, 25 Feb 2026 23:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/forwarding-a-vagrant-based-jekyll-dev-server-to-its-host-1pel</link>
      <guid>https://dev.to/peateasea/forwarding-a-vagrant-based-jekyll-dev-server-to-its-host-1pel</guid>
      <description>&lt;p&gt;Forwarding port 80 or 22 from Vagrant virtual machines to their host system is fairly simple. Piping non-privileged ports outside the VM–from, say, a development HTTP server–requires not much extra work. Yet, it’s not always obvious how to do this. In this post, I explain how a Jekyll development HTTP server running within a Vagrant VM can allow connections from its host and why the configuration works.&lt;/p&gt;

&lt;p&gt;I was recently testing how to set up and build a Jekyll-based static site by running everything in a Vagrant VM. Since this was a test, I didn’t want to set up nginx, Apache, or reverse proxies; I only needed to connect to the development HTTP server. By default, Jekyll’s built-in HTTP server listens on port 4000. Thus, to connect to that port from a browser running on the VM’s host system, I only needed to forward port 4000 in my Vagrant config, right? Well, that’s part of the story, yes, but it’s not the full story.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building background knowledge
&lt;/h2&gt;

&lt;p&gt;Let’s build up some knowledge before wiring everything together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Find the port number
&lt;/h3&gt;

&lt;p&gt;After setting up a Jekyll site, one of the first things you want to do is verify that it works. Thus, you want to start the dev HTTP server and point your browser at &lt;code&gt;http://127.0.0.1:4000/&lt;/code&gt;. This is something that running &lt;code&gt;jekyll serve&lt;/code&gt; tells you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;jekyll serve
Configuration file: /home/cochrane/hello-jekyll/_config.yml
            Source: /home/cochrane/hello-jekyll
       Destination: /home/cochrane/hello-jekyll/_site
 Incremental build: disabled. Enable with &lt;span class="nt"&gt;--incremental&lt;/span&gt;
      Generating...
       Jekyll Feed: Generating feed &lt;span class="k"&gt;for &lt;/span&gt;posts
                    &lt;span class="k"&gt;done in &lt;/span&gt;1.392 seconds.
 Auto-regeneration: enabled &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s1"&gt;'/home/cochrane/hello-jekyll'&lt;/span&gt;
    Server address: http://127.0.0.1:4000/
  Server running... press ctrl-c to stop.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s the first bit of knowledge to collect: the server runs on port 4000.&lt;/p&gt;

&lt;h3&gt;
  
  
  Forward the port to the host
&lt;/h3&gt;

&lt;p&gt;The thing is, this server is running on &lt;code&gt;localhost&lt;/code&gt; &lt;em&gt;within the virtual machine&lt;/em&gt;. Trying to connect to this address from the VM’s host won’t work. This is because the connection would access &lt;code&gt;localhost&lt;/code&gt; &lt;em&gt;on the host&lt;/em&gt;, which is different. We solve this problem by forwarding the port from the guest system to the host system.&lt;/p&gt;

&lt;p&gt;Forwarding ports in Vagrant is simple enough: add the &lt;code&gt;forwarded_port&lt;/code&gt; identifier to the VM’s &lt;code&gt;network&lt;/code&gt; settings. The canonical example, &lt;a href="https://developer.hashicorp.com/vagrant/docs/networking/forwarded_ports#defining-a-forwarded-port" rel="noopener noreferrer"&gt;e.g. from the Vagrant docs&lt;/a&gt;, forwards port 80 from the guest to port 8080 on the host. In other words, you set something like this in the relevant part of your &lt;code&gt;Vagrantfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;network&lt;/span&gt; &lt;span class="s2"&gt;"forwarded_port"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;guest: &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;host: &lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s the next bit of knowledge: add the &lt;code&gt;forwarded_port&lt;/code&gt; option to the &lt;code&gt;network&lt;/code&gt; setting in the &lt;code&gt;Vagrantfile&lt;/code&gt;, and point the guest port to an unprivileged port number&lt;sup id="fnref:unpriv-port-number"&gt;1&lt;/sup&gt; on the host.&lt;/p&gt;

&lt;p&gt;How do we set this up for our Jekyll example? We need to pipe port 4000 to another number. Let’s use 4400 here so that it doesn’t clash with a separate Jekyll service which might be running on port 4000 on the host. Thus, we add this line to our &lt;code&gt;Vagrantfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;network&lt;/span&gt; &lt;span class="s2"&gt;"forwarded_port"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;guest: &lt;/span&gt;&lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;host: &lt;/span&gt;&lt;span class="mi"&gt;4400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="s2"&gt;"jekyll"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that I’ve added an ID to the configuration so that it’s more obvious to a human what service should run on this port.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learning to listen
&lt;/h3&gt;

&lt;p&gt;So far, so good. Starting (or restarting) the Vagrant VM and running &lt;code&gt;jekyll serve&lt;/code&gt; within it, we should be able to see the site in a browser at &lt;code&gt;http://localhost:4400&lt;/code&gt;, i.e. on the port we opened up on the host.&lt;/p&gt;

&lt;p&gt;But you’ll find that this won’t work. A browser will tell you that the connection was reset. Using &lt;code&gt;curl&lt;/code&gt; from the host system gives similar output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; http://localhost:4400/
&lt;span class="k"&gt;*&lt;/span&gt; Trying 127.0.0.1:4400...
&lt;span class="k"&gt;*&lt;/span&gt; Connected to localhost &lt;span class="o"&gt;(&lt;/span&gt;127.0.0.1&lt;span class="o"&gt;)&lt;/span&gt; port 4400 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c"&gt;#0)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; GET / HTTP/1.1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Host: localhost:4400
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; User-Agent: curl/7.88.1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Accept: &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt; Recv failure: Connection reset by peer
&lt;span class="k"&gt;*&lt;/span&gt; Closing connection 0
curl: &lt;span class="o"&gt;(&lt;/span&gt;56&lt;span class="o"&gt;)&lt;/span&gt; Recv failure: Connection reset by peer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What’s going wrong?&lt;/p&gt;

&lt;p&gt;To work that out, we need to do some debugging. Let’s check that the port is being forwarded correctly. Having a look for it on the host with &lt;code&gt;netstat&lt;/code&gt; reveals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;netstat &lt;span class="nt"&gt;-tulpen&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;4400
&lt;span class="o"&gt;(&lt;/span&gt;Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.&lt;span class="o"&gt;)&lt;/span&gt;
tcp 0 0 0.0.0.0:4400 0.0.0.0:&lt;span class="k"&gt;*&lt;/span&gt; LISTEN 1000 7916524 -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, the port’s there, and it &lt;em&gt;looks&lt;/em&gt; like we should be able to access it.&lt;/p&gt;

&lt;p&gt;Checking the ports inside the guest hints at the problem’s cause:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;netstat &lt;span class="nt"&gt;-tulpen&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.&lt;span class="o"&gt;)&lt;/span&gt;
Active Internet connections &lt;span class="o"&gt;(&lt;/span&gt;only servers&lt;span class="o"&gt;)&lt;/span&gt;
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 127.0.0.1:4000 0.0.0.0:&lt;span class="k"&gt;*&lt;/span&gt; LISTEN 1001 16842 -
tcp 0 0 0.0.0.0:22 0.0.0.0:&lt;span class="k"&gt;*&lt;/span&gt; LISTEN 0 1985 -
tcp6 0 0 :::22 :::&lt;span class="k"&gt;*&lt;/span&gt; LISTEN 0 1987 -
&amp;lt;snip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how port 22 has been configured, and that it is different to port 4000’s configuration. Namely, the local address is &lt;code&gt;0.0.0.0&lt;/code&gt; for port 22, but it’s set to &lt;code&gt;127.0.0.1&lt;/code&gt; for port 4000. Does that cause the connection reset failure? Put very simply, yes.&lt;/p&gt;

&lt;p&gt;The local addresses shown here are the addresses that the operating system will allow connections on. There’s also a subtlety that’s not obvious: &lt;code&gt;0.0.0.0&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; an IP address. This is a shorthand, telling the operating system to listen for connections on &lt;em&gt;any&lt;/em&gt; IPv4 address with the given port number. Thus, while we see the virtual machine listening for connections on port 22 from any address, it’s only listening for connections to port 4000 on &lt;code&gt;127.0.0.1&lt;/code&gt;. This is a specific address, and it’s not the one the host is trying to connect to via the forwarded port.&lt;/p&gt;

&lt;p&gt;Furthermore, &lt;code&gt;127.0.0.1&lt;/code&gt; is a &lt;em&gt;loopback address&lt;/em&gt;.&lt;sup id="fnref:loopback-ipv4-ipv6"&gt;2&lt;/sup&gt; This is completely internal,&lt;sup id="fnref:internal-to-vm"&gt;3&lt;/sup&gt; and hence there is no outside network connection. No traffic to this address will leave the computer. So, a service listening on &lt;code&gt;127.0.0.1&lt;/code&gt; will only answer to connection requests from the computer running the service. No wonder we couldn’t access it from the host! There was never the possibility of being able to connect to it from the outside. That’s why the connection was reset when accessing &lt;code&gt;http://127.0.0.1:4000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;How do we fix this problem? The solution is to bind the HTTP server to &lt;code&gt;0.0.0.0&lt;/code&gt;, thus making it listen for connections from any address.&lt;/p&gt;

&lt;p&gt;That’s the last bit of knowledge we need: bind the service to &lt;code&gt;0.0.0.0&lt;/code&gt;.&lt;sup id="fnref:any-address-ipv6"&gt;4&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;There are more subtleties to this topic. For a lot more detail and excellent explanations, have a look at the article &lt;a href="https://thelinuxcode.com/127001-vs-0000-what-they-mean-when-to-use-each-and-how-to-debug-binding-bugs/" rel="noopener noreferrer"&gt;127.0.0.1 vs 0.0.0.0: What They Mean, When to Use Each, and How to Debug Binding Bugs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Host binding
&lt;/h2&gt;

&lt;p&gt;So, how do we get Jekyll to bind to &lt;code&gt;0.0.0.0&lt;/code&gt;? The answer is to pass the bind address to &lt;code&gt;jekyll serve&lt;/code&gt; via the &lt;code&gt;--host&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;jekyll serve &lt;span class="nt"&gt;--host&lt;/span&gt; 0.0.0.0
Configuration file: /home/cochrane/hello-jekyll/_config.yml
            Source: /home/cochrane/hello-jekyll
       Destination: /home/cochrane/hello-jekyll/_site
 Incremental build: disabled. Enable with &lt;span class="nt"&gt;--incremental&lt;/span&gt;
      Generating...
       Jekyll Feed: Generating feed &lt;span class="k"&gt;for &lt;/span&gt;posts
                    &lt;span class="k"&gt;done in &lt;/span&gt;1.46 seconds.
 Auto-regeneration: enabled &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s1"&gt;'/home/cochrane/hello-jekyll'&lt;/span&gt;
    Server address: http://0.0.0.0:4000/
  Server running... press ctrl-c to stop.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the log message &lt;code&gt;Server address: http://0.0.0.0:4000/&lt;/code&gt; shown above is, technically, incorrect. This &lt;em&gt;is not an address&lt;/em&gt;, hence you should not point your browser at it. It &lt;em&gt;might&lt;/em&gt; work, but don’t count on it.&lt;/p&gt;

&lt;p&gt;With the service bound to &lt;code&gt;0.0.0.0&lt;/code&gt;, you’ll now find that the service is listening on all addresses on port 4000 within the VM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;netstat &lt;span class="nt"&gt;-tulpen&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.&lt;span class="o"&gt;)&lt;/span&gt;
Active Internet connections &lt;span class="o"&gt;(&lt;/span&gt;only servers&lt;span class="o"&gt;)&lt;/span&gt;
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 0.0.0.0:4000 0.0.0.0:&lt;span class="k"&gt;*&lt;/span&gt; LISTEN 1001 15737 -

&amp;lt;snip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and that a connection via the forwarded port to this service is now possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; http://127.0.0.1:4400
&lt;span class="k"&gt;*&lt;/span&gt; Trying 127.0.0.1:4400...
&lt;span class="k"&gt;*&lt;/span&gt; Connected to 127.0.0.1 &lt;span class="o"&gt;(&lt;/span&gt;127.0.0.1&lt;span class="o"&gt;)&lt;/span&gt; port 4400 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c"&gt;#0)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; GET / HTTP/1.1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Host: 127.0.0.1:4400
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; User-Agent: curl/7.88.1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Accept: &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&amp;lt; HTTP/1.1 200 OK
&amp;lt; Etag: 4065fa-1295-69849bfa
&amp;lt; Content-Type: text/html&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;utf-8
&amp;lt; Content-Length: 4757
&amp;lt; Last-Modified: Thu, 05 Feb 2026 13:32:42 GMT
&amp;lt; Cache-Control: private, max-age&lt;span class="o"&gt;=&lt;/span&gt;0, proxy-revalidate, no-store, no-cache, must-revalidate
&amp;lt; Server: WEBrick/1.9.2 &lt;span class="o"&gt;(&lt;/span&gt;Ruby/3.4.8/2025-12-17&lt;span class="o"&gt;)&lt;/span&gt;
&amp;lt; Date: Thu, 05 Feb 2026 13:36:56 GMT
&amp;lt; Connection: Keep-Alive

&amp;lt;snip lots of HTML&amp;gt;

&lt;span class="k"&gt;*&lt;/span&gt; Connection &lt;span class="c"&gt;#0 to host 127.0.0.1 left intact&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, pointing a browser on the host at the address &lt;code&gt;http://localhost:4400&lt;/code&gt; will display the development Jekyll site that we wanted to see. Great!&lt;/p&gt;

&lt;h2&gt;
  
  
  A general situation
&lt;/h2&gt;

&lt;p&gt;Note that this is not specific to Jekyll, nor to Vagrant. Other virtualisation technologies and HTTP servers providing a service on &lt;code&gt;localhost&lt;/code&gt; by default behave this way. For instance, it could be that you’re trying to connect to a development Django web server running inside a Docker container. Again, the dev HTTP server must be bound to &lt;code&gt;0.0.0.0&lt;/code&gt; so that the host system can connect to any forwarded ports.&lt;/p&gt;

&lt;h2&gt;
  
  
  Another thing learned!
&lt;/h2&gt;

&lt;p&gt;I hope this helps someone confronted with such a situation in the future! For me, it was nice to learn the differences between &lt;code&gt;127.0.0.1&lt;/code&gt;, &lt;code&gt;localhost&lt;/code&gt; and &lt;code&gt;0.0.0.0&lt;/code&gt;: my previous conceptual model dumped them all into the same pot, which was incorrect. Now I understand their meaning better, and how and where to use them.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What I mean by an unprivileged port number is one whose use or configuration does not require superuser privileges. These are sometimes also called unrestricted ports or &lt;a href="https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Registered_ports" rel="noopener noreferrer"&gt;registered ports&lt;/a&gt;. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Note that the address &lt;code&gt;127.0.0.1&lt;/code&gt; is the loopback address on IPv4. On IPv6, the loopback address is &lt;code&gt;::1&lt;/code&gt;. The name &lt;code&gt;localhost&lt;/code&gt; could be both. For instance, if you try to connect to &lt;code&gt;http://localhost&lt;/code&gt; in a browser, it will likely try &lt;code&gt;::1&lt;/code&gt; first before possibly falling back to &lt;code&gt;127.0.0.1&lt;/code&gt;. This is not behaviour one can rely on. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In this case, to the VM. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The IPv6 equivalent of this shorthand is &lt;code&gt;::&lt;/code&gt;. ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>linux</category>
      <category>vagrant</category>
      <category>jekyll</category>
    </item>
    <item>
      <title>Changing a hostname in Debian seems harder than necessary</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Wed, 18 Feb 2026 23:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/changing-a-hostname-in-debian-seems-harder-than-necessary-2bdo</link>
      <guid>https://dev.to/peateasea/changing-a-hostname-in-debian-seems-harder-than-necessary-2bdo</guid>
      <description>&lt;p&gt;Changing a host’s name in Debian&lt;sup id="fnref:probably-in-general"&gt;1&lt;/sup&gt; is a two-step process, and there doesn’t appear to be a more direct method. This seems odd to me, somehow. Because I stumbled upon this issue and a confusing error while relying solely on &lt;code&gt;sudo&lt;/code&gt;, I thought I’d write up how I worked around it.&lt;/p&gt;

&lt;p&gt;It feels like I missed something obvious here. I mean, changing the hostname should be a one-liner, right? Perhaps someone knows of a better solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  System setup stumbling-block
&lt;/h2&gt;

&lt;p&gt;Ok, so here’s the situation: I wanted to create a new Vagrant VM and run some basic provisioning steps. Since the use case wasn’t very involved, I didn’t want to use something like Ansible: a simple set of bash commands was sufficient.&lt;/p&gt;

&lt;p&gt;One step changes the hostname from the default to something more descriptive. Sounds simple, right? Technically, it &lt;em&gt;is&lt;/em&gt; simple. The thing is, two steps are required, which I found strange. And if you’re using &lt;code&gt;sudo&lt;/code&gt;, you’ll likely be surprised by a name resolution error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo: unable to resolve host &amp;lt;new-hostname&amp;gt;: Temporary failure in name resolution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What gives?&lt;/p&gt;

&lt;p&gt;The name resolution failure appears because the new hostname doesn’t match the entry in &lt;code&gt;/etc/hosts&lt;/code&gt;. Thus, any &lt;code&gt;sudo&lt;/code&gt; call thereafter is unable to find the host it’s running on. The hostname lookup within &lt;code&gt;sudo&lt;/code&gt; times out, and we get the name resolution failure message I mentioned above.&lt;/p&gt;

&lt;p&gt;I must admit, this tripped me up. I don’t remember having had this stumbling block previously. I ended up wondering how I’d done this before. Wasn’t this a single command in the past? And what’s with name resolution being needed as part of &lt;code&gt;sudo&lt;/code&gt;?&lt;sup id="fnref:sudo-host-lookup-reason"&gt;2&lt;/sup&gt; Once upon a time, I’d have opened a &lt;code&gt;root&lt;/code&gt; session and hence wouldn’t have run into this problem, but those days are long over. I now almost exclusively use &lt;code&gt;sudo&lt;/code&gt; for admin tasks.&lt;/p&gt;

&lt;p&gt;More recently, I use Ansible when provisioning new hosts, and hence haven’t spotted this issue.&lt;sup id="fnref:ansible-hostname-etc-hosts"&gt;3&lt;/sup&gt; At least, not for a while. Maybe I’ve just forgotten? Dunno.&lt;/p&gt;

&lt;p&gt;Anyhow, back to the story. The problem manifests itself if you run these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# either use the "old" way to set a hostname&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo hostname&lt;/span&gt; &amp;lt;new-hostname&amp;gt;
&lt;span class="c"&gt;# ... or use the new-fangled, strangely repetitive way to set a hostname&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;hostnamectl set-hostname &amp;lt;new-hostname&amp;gt;
&lt;span class="c"&gt;# now open /etc/hosts to fix hostname entry in there&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/hosts
&lt;span class="c"&gt;# ... wait until the name resolution times out ...&lt;/span&gt;
&lt;span class="c"&gt;# get the name resolution error message&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt;: unable to resolve host &amp;lt;new-hostname&amp;gt;: Temporary failure &lt;span class="k"&gt;in &lt;/span&gt;name resolution
&lt;span class="c"&gt;# now vim will open /etc/hosts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All online resources I looked at–such as &lt;a href="https://www.cyberciti.biz/faq/how-to-change-hostname-on-debian-10-linux/" rel="noopener noreferrer"&gt;nixCraft&lt;/a&gt;, which is usually a good source of info–recommend this two-step process. And to do it within a &lt;code&gt;root&lt;/code&gt; session.&lt;/p&gt;

&lt;p&gt;But what if you &lt;em&gt;don’t&lt;/em&gt; want to do that as &lt;code&gt;root&lt;/code&gt; directly? What if you want to script this and are restricted to using &lt;code&gt;sudo&lt;/code&gt;? That’s the issue I was trying to solve, and here’s my solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wonky workflow workaround
&lt;/h2&gt;

&lt;p&gt;The approach first adds the new hostname to &lt;code&gt;/etc/hosts&lt;/code&gt;. That way, the name is able to be resolved after changing the hostname. Then I change the hostname in the usual way. Afterwards, I delete the old &lt;code&gt;/etc/hosts&lt;/code&gt; entry to remove unnecessary cruft.&lt;/p&gt;

&lt;p&gt;Putting this all together as a shell script in a &lt;code&gt;Vagrantfile&lt;/code&gt; provisioning step, we get (by way of example):&lt;sup id="fnref:maybe-privileged-true"&gt;4&lt;/sup&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;    &lt;span class="n"&gt;bookworm_new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provision&lt;/span&gt; &lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;privileged: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;inline: &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;SHELL&lt;/span&gt;&lt;span class="sh"&gt;
      sudo DEBIAN_FRONTEND=noninteractive apt update
      sudo DEBIAN_FRONTEND=noninteractive apt -y upgrade
      sudo DEBIAN_FRONTEND=noninteractive apt install -y vim
      # add new hostname to /etc/hosts; keep old one for now
      # avoids `sudo: unable to resolve host &amp;lt;hostname&amp;gt;: Temporary failure in name resolution`
      # errors when running `sudo` after changing the hostname
      sudo sed -i 's/bookworm/bookworm bookworm-new/g' /etc/hosts
      sudo hostnamectl set-hostname bookworm-new
      # remove the old hostname
      sudo sed -i 's/bookworm //g' /etc/hosts
&lt;/span&gt;&lt;span class="no"&gt;    SHELL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The provisioning commands appear in a &lt;a href="https://en.wikipedia.org/wiki/Here_document" rel="noopener noreferrer"&gt;here doc&lt;/a&gt; called &lt;code&gt;SHELL&lt;/code&gt;.&lt;sup id="fnref:extract-script-file"&gt;5&lt;/sup&gt; The first few lines are standard update commands I use when setting up a new VM. I find it’s a good idea to ensure everything’s up to date before proceeding, even if the base image is recent. You’ll note that I install &lt;code&gt;vim&lt;/code&gt; as well. Basically, my muscle memory won’t think of another editor, and this saves friction for me when modifying config files or viewing logs.&lt;/p&gt;

&lt;p&gt;The lines after that are the important ones for the hostname updating process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# add new hostname; keep old one temporarily&lt;/span&gt;
&lt;span class="c"&gt;# avoids `sudo: unable to resolve host &amp;lt;hostname&amp;gt;: Temporary failure in name resolution`&lt;/span&gt;
&lt;span class="c"&gt;# errors when running `sudo` after changing the hostname&lt;/span&gt;
&lt;span class="nb"&gt;sudo sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bookworm/bookworm bookworm-new/g'&lt;/span&gt; /etc/hosts
&lt;span class="nb"&gt;sudo &lt;/span&gt;hostnamectl set-hostname bookworm-new
&lt;span class="c"&gt;# remove the old hostname&lt;/span&gt;
&lt;span class="nb"&gt;sudo sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/bookworm //g'&lt;/span&gt; /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first non-comment line uses &lt;code&gt;sed&lt;/code&gt; to edit &lt;code&gt;/etc/hosts&lt;/code&gt; in-place (hence the &lt;code&gt;-i&lt;/code&gt; option). The example system used here is &lt;a href="https://www.debian.org/releases/bookworm/" rel="noopener noreferrer"&gt;Debian bookworm&lt;/a&gt;, hence the default hostname is set to &lt;code&gt;bookworm&lt;/code&gt;. I want to set the new hostname to be (unimaginatively) &lt;code&gt;bookworm-new&lt;/code&gt;, so the &lt;code&gt;sed&lt;/code&gt; command replaces &lt;code&gt;bookworm&lt;/code&gt; with the text &lt;code&gt;bookworm bookworm-new&lt;/code&gt;. Now the new hostname is available, and the old hostname is still there, but with a space after it, which will come in handy when removing that entry later.&lt;/p&gt;

&lt;p&gt;Next, I use &lt;code&gt;hostnamectl&lt;/code&gt; to set the hostname. The old-fashioned &lt;code&gt;hostname&lt;/code&gt; command still works, but &lt;code&gt;hostnamectl&lt;/code&gt; seems to be what all the cool kids use.&lt;/p&gt;

&lt;p&gt;Now it’s just a matter of removing the old hostname from &lt;code&gt;/etc/hosts&lt;/code&gt;. Here I use &lt;code&gt;sed&lt;/code&gt; with the &lt;code&gt;-i&lt;/code&gt; option again, and replace the string &lt;code&gt;'bookworm '&lt;/code&gt; (note the space after the name)&lt;sup id="fnref:better-regex"&gt;6&lt;/sup&gt; with the empty string, thus removing the old hostname from &lt;code&gt;/etc/hosts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now the change is complete, and there aren’t any “Temporary failure in name resolution” errors. Yay! 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;For some reason, I still expect the hostname and &lt;code&gt;/etc/hosts&lt;/code&gt; changes to be coupled so that they occur as part of a single command. Oh well. Ya get that, I guess.&lt;/p&gt;

&lt;p&gt;Anyway, if you run across the &lt;code&gt;Temporary failure in name resolution&lt;/code&gt; error when running &lt;code&gt;sudo&lt;/code&gt; in the future, now you know why and can work around it. Enjoy!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;… and probably Linux in general, but I didn’t check. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The reason &lt;code&gt;sudo&lt;/code&gt; looks up the host’s name is &lt;a href="https://superuser.com/a/429890" rel="noopener noreferrer"&gt;that &lt;code&gt;/etc/sudoers&lt;/code&gt; is designed to be distributed across multiple servers&lt;/a&gt;. Hence, &lt;code&gt;sudo&lt;/code&gt; needs to know which host it’s on to apply any host-specific rules. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Although, to be honest, the &lt;a href="https://docs.ansible.com/projects/ansible/latest/collections/ansible/builtin/hostname_module.html" rel="noopener noreferrer"&gt;&lt;code&gt;ansible.builtin.hostname&lt;/code&gt; module docs&lt;/a&gt; do mention that the module &lt;em&gt;doesn’t&lt;/em&gt; update &lt;code&gt;/etc/hosts&lt;/code&gt; and that one has to do this it oneself. Perhaps I haven’t done this in a while and have forgotten the full story. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have a suspicion that my woes could be solved by using &lt;code&gt;privileged: true&lt;/code&gt; and removing &lt;code&gt;sudo&lt;/code&gt; from the script. However, I realised this after having written everything up, and yet still found my explanation useful. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Of course, one could extract the script code into a file and run &lt;em&gt;that&lt;/em&gt; via &lt;code&gt;sudo&lt;/code&gt;. But where’s the fun in that? ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Yes, I could have used a better regex here, e.g. something like &lt;code&gt;bookworm\s\+&lt;/code&gt;, but then I’d need to use extended regular expressions and, well, this did the job. ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>debian</category>
      <category>linux</category>
      <category>bash</category>
      <category>vagrant</category>
    </item>
    <item>
      <title>It’s not DNS; it was DNS</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Wed, 11 Feb 2026 23:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/its-not-dns-it-was-dns-45f</link>
      <guid>https://dev.to/peateasea/its-not-dns-it-was-dns-45f</guid>
      <description>&lt;p&gt;Logging in to a VPN shouldn’t cause DNS to stop working, right? Well, you’d like to think that, wouldn’t ya? And the problem wasn’t PEBKAC this time, either. Finding the right setting to fix the problem did take some time, but I got there in the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  A computer by any other name
&lt;/h2&gt;

&lt;p&gt;While doing some work for a customer&lt;sup id="fnref:hire-me"&gt;1&lt;/sup&gt; recently, I needed to log in to their VPN to check on some stuff. I’d not used their VPN for about a year, so I expected some hiccups along the way. I mean, there’s always &lt;em&gt;something&lt;/em&gt;, right? Network settings are changed, systems get updated, and the slow plod of time always causes some problem or other. But I wasn’t expecting DNS not to work when connected to their VPN.&lt;/p&gt;

&lt;p&gt;Here was the situation. I was happily using the internet (as you do) and needed to access one of the customer’s services that is only available within their network. Thus, I needed to log in to their VPN. I entered my login details into their VPN client and voila! I was in their network. All as expected, right? Wrong. Any address I entered into my web browser gave me the same error: server not found. And yes, I was using the correct address. This situation made it rather difficult to access the services I needed to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bring out the machine that goes ping
&lt;/h2&gt;

&lt;p&gt;One of my first instincts when confronted with such a situation is to try to &lt;code&gt;ping&lt;/code&gt; something. A habit (and probably a bad one at that) is to ping &lt;code&gt;www.heise.de&lt;/code&gt; because, well, it’s always up. That resulted in this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ping &lt;span class="nt"&gt;-4&lt;/span&gt; www.heise.de
ping: www.heise.de: Name or service not known
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, not good. How about an address closer to home? For instance, the customer’s main website? It turned out that pinging that address also wouldn’t resolve a name. Crikey! What to do now?&lt;/p&gt;

&lt;p&gt;The hard part here was debugging the problem as an outside user. What else could I check? The IP address that the VPN client software had given me looked ok:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip addr
&amp;lt;snip&amp;gt;
10: cscotun0: &amp;lt;POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP&amp;gt; mtu 1390 qdisc
pfifo_fast state UNKNOWN group default qlen 500
    &lt;span class="nb"&gt;link&lt;/span&gt;/none
    inet x.x.x.x/22 brd x.x.x.255 scope global cscotun0
       valid_lft forever preferred_lft forever
    inet6 fe80:&amp;lt;la-la-la&amp;gt;/126 scope &lt;span class="nb"&gt;link &lt;/span&gt;noprefixroute
       valid_lft forever preferred_lft forever
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The list of routes also looked good:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ip route list
default via 192.168.2.1 dev wlp2s0 proto dhcp metric 600
x.x.x.x dev cscotun0 proto unspec scope &lt;span class="nb"&gt;link&lt;/span&gt;
&amp;lt;snip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logging out of the VPN, I contacted the IT staff at the customer’s site and told them of my sorrows. Unfortunately, as far as the network engineers on the other side could tell, everything looked good. Nothing in their DNS had changed. After all, the DNS servers were still the same as they’d always been. These servers also appeared in my route list. Hrm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Persistence pays off
&lt;/h2&gt;

&lt;p&gt;Some time passed, and after some more discussion, we (the IT staff and I) still weren’t any closer to resolving the issue. Thus, I decided to dig a bit further on my side to see if there was anything I could do to fix things. After all, it wouldn’t be the first time that I’d set some configuration value on my laptop and then forgotten that I’d set it, and it ended up provoking some weird problem a long time later. Lots of digging ensued, but there wasn’t anything obvious that seemed to be causing the issue. Through stubborn perseverance, I eventually honed in on the &lt;code&gt;NetworkManager&lt;/code&gt; service’s configuration as a possible origin of my woes.&lt;/p&gt;

&lt;p&gt;One thing with DNS on a Linux box is that (historically) this is configured in &lt;code&gt;/etc/resolv.conf&lt;/code&gt;. Having a look at this file with the VPN off showed something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/resolv.conf
&lt;span class="c"&gt;# Generated by NetworkManager&lt;/span&gt;
search internet-provider.com
nameserver 192.168.2.1
nameserver fe80::1%wlp2s0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, when logged in to the VPN, &lt;code&gt;NetworkManager&lt;/code&gt; changed this file’s contents to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/resolv.conf
&lt;span class="c"&gt;# Generated by NetworkManager&lt;/span&gt;
search internet-provider.com customer.com
nameserver 192.168.2.1
nameserver fe80::1%wlp2s0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, so the only change is to add the customer’s domain to the resolver’s search settings. This shouldn’t affect name resolution. In fact, I would expect it to &lt;em&gt;help&lt;/em&gt; with name resolution.&lt;/p&gt;

&lt;p&gt;Using a bit of old-fashioned prompt-engineering (i.e. googling), I stumbled upon &lt;code&gt;NetworkManager&lt;/code&gt;’s &lt;a href="https://networkmanager.pages.freedesktop.org/NetworkManager/NetworkManager/NetworkManager.conf.html" rel="noopener noreferrer"&gt;&lt;code&gt;dns&lt;/code&gt; configuration parameter&lt;/a&gt;. It controls the DNS processing mode and is set in the &lt;code&gt;[main]&lt;/code&gt; configuration section of the &lt;code&gt;/etc/NetworkManager/NetworkManager.conf&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The comment in &lt;code&gt;/etc/resolv.conf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generated by NetworkManager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;somehow gave me the idea that maybe &lt;code&gt;NetworkManager&lt;/code&gt; didn’t need to update this file after all. And that maybe some other software component, which was also trying to update &lt;code&gt;/etc/resolv.conf&lt;/code&gt;, would get the chance to set things properly. Thus, I tried setting &lt;code&gt;dns=none&lt;/code&gt; to stop &lt;code&gt;NetworkManager&lt;/code&gt; modifying &lt;code&gt;resolv.conf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I.e., I changed &lt;code&gt;/etc/NetworkManager/NetworkManager.conf&lt;/code&gt; to look like this in the &lt;code&gt;[main]&lt;/code&gt; section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[main]&lt;/span&gt;
&lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="err"&gt;other&lt;/span&gt; &lt;span class="err"&gt;settings&lt;/span&gt;
&lt;span class="py"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;none&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restarting the service to re-read the config,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service NetworkManager restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and sure enough, something was changing &lt;code&gt;/etc/resolv.conf&lt;/code&gt; when in the VPN and was changing it back after leaving the VPN. My guess, retrospectively, is that this was the VPN client software. Since, in the default configuration, &lt;code&gt;NetworkManager&lt;/code&gt; thinks that it should have full control over this file, it kept changing &lt;code&gt;/etc/resolv.conf&lt;/code&gt; &lt;em&gt;back&lt;/em&gt; to what it thought was the right config, which then screwed up DNS for me.&lt;/p&gt;

&lt;p&gt;Here’s what &lt;code&gt;/etc/resolv.conf&lt;/code&gt; looked like for me now after connecting to the VPN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/resolv.conf
domain customer.com
nameserver &amp;lt;dns-ip-1&amp;gt;
nameserver &amp;lt;dns-ip-2&amp;gt;
search customer.com internet-provider.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Something about this change told me I was onto something. Especially the new &lt;code&gt;nameserver&lt;/code&gt; values signalled an improvement.&lt;/p&gt;

&lt;p&gt;Importantly, I could now ping &lt;code&gt;www.heise.de&lt;/code&gt; while in the VPN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ping &lt;span class="nt"&gt;-4&lt;/span&gt; www.heise.de
PING &lt;span class="o"&gt;(&lt;/span&gt;193.99.144.85&lt;span class="o"&gt;)&lt;/span&gt; 56&lt;span class="o"&gt;(&lt;/span&gt;84&lt;span class="o"&gt;)&lt;/span&gt; bytes of data.
64 bytes from www.heise.de &lt;span class="o"&gt;(&lt;/span&gt;193.99.144.85&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;249 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;9.13 ms
64 bytes from www.heise.de &lt;span class="o"&gt;(&lt;/span&gt;193.99.144.85&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;249 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.1 ms
^C
&lt;span class="nt"&gt;---&lt;/span&gt; ping statistics &lt;span class="nt"&gt;---&lt;/span&gt;
2 packets transmitted, 2 received, 0% packet loss, &lt;span class="nb"&gt;time &lt;/span&gt;1002ms
rtt min/avg/max/mdev &lt;span class="o"&gt;=&lt;/span&gt; 9.134/9.607/10.080/0.473 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Brilliant!&lt;/p&gt;

&lt;p&gt;Now I could access the services I needed to use and continued merrily on my way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Everything works until it doesn’t
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;… until …&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Time did that thing again that it always does: change stuff. &lt;em&gt;sigh&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For other network-related reasons, I needed to update some packages on my (admittedly very outdated) dev system. While watching the progress of an &lt;code&gt;apt upgrade&lt;/code&gt; command whiz past, a package name caught my attention: &lt;code&gt;resolvconf&lt;/code&gt;. Oh dear.&lt;/p&gt;

&lt;p&gt;Guess what? DNS no longer worked. It even turned out that when I wasn’t connected to the VPN that &lt;code&gt;dns=none&lt;/code&gt; needed to be &lt;em&gt;removed&lt;/em&gt; for name resolution to work. But &lt;code&gt;dns=none&lt;/code&gt; needed to be &lt;em&gt;set&lt;/em&gt; (and &lt;code&gt;NetworkManager&lt;/code&gt; restarted) for DNS to work inside the VPN. &lt;a href="https://www.youtube.com/watch?v=ZUNJd06iyWU" rel="noopener noreferrer"&gt;Bugger&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Man, this was &lt;em&gt;so&lt;/em&gt; not a solution. I can’t be changing the &lt;code&gt;NetworkManager&lt;/code&gt; config and restarting it each time I change a network connection!&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the fine manual
&lt;/h2&gt;

&lt;p&gt;Thus, lots more reading ensued, including more of the &lt;code&gt;NetworkManager.conf&lt;/code&gt; man page. One of the big hints in the section about the &lt;code&gt;dns&lt;/code&gt; option is the comment that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the key is unspecified, default is used, unless /etc/resolv.conf is a symlink to /run/systemd/resolve/stub-resolv.conf, /run/systemd/resolve/resolv.conf, /lib/systemd/resolv.conf or /usr/lib/systemd/resolv.conf. In that case, systemd-resolved is chosen automatically.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An idea formed in my mind. What if I used &lt;code&gt;systemd-resolved&lt;/code&gt;? Let’s give it a go! YOLO and all that jazz.&lt;/p&gt;

&lt;p&gt;It turned out that the &lt;code&gt;systemd-resolved&lt;/code&gt; package wasn’t installed on my laptop. No worries, that’s easily fixed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;systemd-resolved
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I changed the &lt;code&gt;dns&lt;/code&gt; setting in &lt;code&gt;NetworkManager.conf&lt;/code&gt; to use &lt;code&gt;systemd-resolved&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[main]&lt;/span&gt;
&lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="err"&gt;other&lt;/span&gt; &lt;span class="err"&gt;settings&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="py"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;systemd-resolved&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After restarting &lt;code&gt;NetworkManager&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service NetworkManager restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;… everything worked! By that I mean I could change the network I was using (i.e. to the VPN and back again) and still have name resolution. Phew!&lt;/p&gt;

&lt;p&gt;So, it turned out that it &lt;em&gt;was&lt;/em&gt; a local setting causing problems. It wasn’t, however, a setting that I’d mucked about with before all these problems appeared, so I couldn’t blame myself (at least, not completely), as is often the case.&lt;/p&gt;

&lt;p&gt;The solution turned out &lt;em&gt;not&lt;/em&gt; to be to set &lt;code&gt;dns=none&lt;/code&gt; and let the VPN software (or whatever) work out what to do with DNS resolution and whatnot in &lt;code&gt;/etc/resolv.conf&lt;/code&gt;. The better, more sustainable solution turned out to be to use &lt;code&gt;systemd-resolved&lt;/code&gt; to handle things for me. Great! Now I can get back to work!&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s not DNS
&lt;/h2&gt;

&lt;p&gt;As it turns out, &lt;a href="https://www.cyberciti.biz/humour/a-haiku-about-dns/" rel="noopener noreferrer"&gt;“it’s not DNS”&lt;/a&gt; is a meme, at least among sysadmins. There are even t-shirts and haikus and stuff!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It’s not DNS&lt;br&gt;&lt;br&gt;
There’s no way it’s DNS&lt;br&gt;&lt;br&gt;
It was DNS&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Things ya learn!&lt;/p&gt;

&lt;h2&gt;
  
  
  Persistence still pays off
&lt;/h2&gt;

&lt;p&gt;So what did we learn? Computers are hard. Networks are also hard. The fact that the internet, with so many computers connected to it, functions at all is something short of a miracle. It’s also a PITA when things that usually “just work”–like DNS–don’t. But, stubbornness, persistence, and liberal use of RTFM saved the day in the end.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you need a software developer who is stubborn, persistent, and thorough, give me a yell! I’m available for freelance Python/Perl backend development and maintenance work. Contact me at &lt;a href="mailto:paul@peateasea.de"&gt;paul@peateasea.de&lt;/a&gt; and let’s discuss how I can help solve your business’s hairiest problems. ↩
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devops</category>
      <category>linux</category>
    </item>
    <item>
      <title>My (current) blog article writing process</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Wed, 04 Feb 2026 23:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/my-current-blog-article-writing-process-176a</link>
      <guid>https://dev.to/peateasea/my-current-blog-article-writing-process-176a</guid>
      <description>&lt;p&gt;As with my work, when I write articles on my blog, I have a focus on quality. Here I describe my current writing process, primarily to document things for my future self.&lt;/p&gt;

&lt;p&gt;I have ideas. &lt;em&gt;Lots&lt;/em&gt; of ideas. Unfortunately, too many to chase all at once. When I follow the thread of a particular idea, I stumble across many interesting problems to solve. This can be as part of my work or simply when I’m trying to get stuff done.&lt;/p&gt;

&lt;p&gt;These ideas and and their solutions provide the inspiration to tell a story about what happened, why, and how to resolve the situation. Often, the impetus to write this stuff up comes from a compulsion to help others: someone else might have had the same problem and is searching for a solution. It’s cool to have a worked solution already written up that can be used directly. Sometimes this “other person” is myself. More than once, I’ve googled for a solution to a problem only to find said solution written up on my blog. After all, as Damian Conway once said: &lt;a href="https://www.azquotes.com/quote/1463174" rel="noopener noreferrer"&gt;documentation is a love letter that you write to your future self&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article describes my current writing process, how I find things to write about, how they turn into articles, and how I polish the text to focus on quality. The process is very much in flux, and I’m still on a learning curve, so I expect things will change in time.&lt;/p&gt;

&lt;p&gt;To be honest, I never liked writing stories at school. This is one reason why I became a scientist, so I didn’t have to keep writing silly stories.&lt;sup id="fnref:school-trips"&gt;1&lt;/sup&gt; It turns out that that’s part and parcel of being a scientist. Bummer!&lt;/p&gt;

&lt;p&gt;It &lt;em&gt;also&lt;/em&gt; turns out that a well-written explanation can be very helpful. And–after many years of trying to avoid such tasks–I finally realised that writing isn’t so bad after all. It’s a hell of a lot of work, but then that’s the case with many worthwhile things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Obstacles are story germination sites
&lt;/h2&gt;

&lt;p&gt;A lot of what I write about stems from some task I was trying to solve or some kind of (usually technical) obstacle I was trying to overcome. Once at the end, I sometimes think “Hrm, this might be useful to someone else”. Thus, a story forms, explaining how the problem arose and how I managed to solve it.&lt;/p&gt;

&lt;p&gt;Solving a technical problem is a lot like puzzle solving. When I solve such puzzles, I make copious notes so that I can explain what happened and why. The reason for my note-taking stems from a desire to write good commit messages and have thorough documentation of the problem. Since this is usually some kind of software-related issue, I dump all that I’ve learned into the project’s issue tracker. This way, others can see what did and didn’t work, transferring knowledge and ensuring anyone following in my footsteps has an easier time in the future.&lt;/p&gt;

&lt;p&gt;My commit messages have come back to haunt me in both positive and negative ways. The negative ones are usually a message like “Fix obkus leak in frobniator”. Gah! Tell me how you fixed it and &lt;em&gt;why&lt;/em&gt;! The positive ones, on the other hand, contain enough detail and explanation for my future self to work out what was going on and how to fix things again, should this be necessary. When I stumble across a good explanation from my past self, I’m frequently stunned at how useful the text is and how much pain and stress it relieves. Damian’s quote rings very true: these really are love letters to your future self.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reworking a solution
&lt;/h2&gt;

&lt;p&gt;The notes themselves, either in commit messages or in issue trackers, aren’t always useful in the form that I initially wrote them. They contain lots of dead ends, extraneous details, failed experiments, and wild goose chases. They lack a “red thread” from problem to solution. This is why I write up an article about some problem and its solution; I work through the puzzle again (sometimes a couple of times) so that the path is clearer and more direct. My thinking here is that someone reading such an article doesn’t want to go down the same dead ends as I did. Dead ends &lt;em&gt;can&lt;/em&gt; be useful, but only if someone puts a signpost in front of them to say, “I tried this out. It didn’t work. Don’t try this at home.” Re-working a solution also helps me shed unnecessary detail and sometimes shows me an even better way to solve the problem. My hope is also that the article’s text flows more logically and that the steps from beginning to end make more sense. Either way, it’s a necessary step to redo things and see that, yes, this &lt;em&gt;was&lt;/em&gt; a good way to solve a particular issue.&lt;/p&gt;

&lt;p&gt;In working through the problem again, I start writing the first draft. Often, each step only requires a few words to tie things together. Install that, edit this file, use that setting, restart that service, and Bob’s your aunty’s live-in lover. In such cases, the article “writes itself” from the initial notes and the example run-through. However, I find that only the basic structure takes shape at this stage. The real hard work starts later, in the editing process.&lt;/p&gt;

&lt;p&gt;A draft article also needs a bit of explanation up front about what the issue is and why it was so important to solve. It also needs most of the details in the examples to be in place, along with any links to relevant documentation or online resources.&lt;/p&gt;

&lt;p&gt;Furthermore, there needs to be some kind of conclusion. I like to round things off by recapping what happened and mentioning any outlook for the future, as necessary. I’ve noticed that some technical book writers tend to avoid a concluding chapter altogether, and the book ends abruptly. This always felt like driving off a cliff to me. As a reader, one has momentum and thinks, “Ok, let’s see what the next thing is the writer wants to tell me”, only to have the book suddenly stop. It’s like Wile E. Coyote standing in mid-air, looking confused and wondering how he got there. Since I don’t like that, I try to round things off, even if the text does seem a bit redundant. It’s like saying “Goodbye” at the end of a phone call. Maybe it’s not technically necessary, but it’d be weird just to hang up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let it simmer for a while
&lt;/h2&gt;

&lt;p&gt;After I’ve written the first draft, it needs to sit for a while so that my subconscious can do its thing. I can’t start editing straight away, because I find that I get sort of “blind” to what I’m saying. If I’ve left a text on its own for a few days and read it again, I see all the holes that I need to plug and much of the fluff I need to remove. This isn’t the first time an article needs to sit and “simmer” for a while. Often, after a manual edit cycle, I leave a text alone once more before returning to it with fresh eyes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Leaning on tools
&lt;/h2&gt;

&lt;p&gt;Editing is &lt;em&gt;hard&lt;/em&gt;. Add to that a lack of writing experience, and it gets even harder. That’s why I lean on a couple of tools to support me in this process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hemingway
&lt;/h3&gt;

&lt;p&gt;After the first edit,&lt;sup id="fnref:multiple-edits"&gt;2&lt;/sup&gt; I use the &lt;a href="https://hemingwayapp.com/" rel="noopener noreferrer"&gt;Hemingway&lt;/a&gt; program to check for certain kinds of style issues and for complex sentences. As my school teachers told me back in the day, I waffle a lot. Waffling makes for complex sentence structures, and Hemingway helpfully flags such things. Using a tool like this allows me to reflect and ask myself, “What is it that I’m trying to say here?” Simply having that extra resistance triggers a rethink. Most of the time, I can see a better formulation, which is shorter and clearer.&lt;/p&gt;

&lt;p&gt;Sometimes I have to ignore some of the suggestions that Hemingway provides. I found that adhering too much to the tool makes the text stilted and wooden. Somehow, my style of explaining things disappears under a layer of bland standardness. It’s been a learning experience working out where Hemingway can help me and where it can’t. And I’m still learning!&lt;/p&gt;

&lt;p&gt;Using Hemingway has helped me to more regularly identify long sentences that need splitting up. I couldn’t see such issues before. Now I spot more of them in the initial edit phase, which is a good thing. It definitely helped me spot when I overuse words like “just”. I’ve found that this can be frequently rewritten as “only”, showing me that I really meant to say something else. Also, it spots things like passive voice, which I try to avoid.&lt;/p&gt;

&lt;p&gt;Importantly, the tool notices words that I can omit, reducing the waffle. Mr Rorholt, my economics teacher at high school, would often write the word “waffle!” in red in the margin of my essays, highlighting my poor, problematic–and probably purple–prose. That experience certainly left its mark, reducing, but not eliminating, my waffliness.&lt;/p&gt;

&lt;p&gt;Hemingway (the program) does seem to harp on about “simpler phrases” and “unnecessary” adjectives. Sometimes these suggestions have to be ignored. A text without variety and different complexity in phrasing ends up plain boring. Also, it’s not like one can avoid adjectives completely. One needs to get a feeling for when it’s a good idea to follow the advice and when it’s a good idea to ignore it.&lt;/p&gt;

&lt;p&gt;A good side-effect of Hemingway highlighting which sentences are complex is that I get an opportunity to cogitate on what it was I was trying to say. The tool isn’t arbitrarily trying to hold me back: it’s providing me with advice. It’s an opportunity to slow down and rethink. Rewriting a sentence or paragraph two or three times can undo any knotted sentence structure that Hemingway spotted. Sometimes, I can remove a sentence completely! After all, deleted code is the easiest to maintain. 😉&lt;/p&gt;

&lt;h3&gt;
  
  
  Grammarly
&lt;/h3&gt;

&lt;p&gt;While I find Hemingway to be useful as an initial automated check, I find &lt;a href="https://app.grammarly.com/" rel="noopener noreferrer"&gt;Grammarly&lt;/a&gt; gives a text much more polish. The tool has four areas of focus: Correctness, Clarity, Engagement, and Delivery. For me, the biggest help is the Correctness area. It spots typos and spelling errors. It sees forgotten articles before nouns. It detects where I’ve placed commas incorrectly or have missed them completely. It also highlights redundancy, tenses, prepositions, and hyphenation issues. The best help, I find, is the comma fixes. Usually, I re-read the text and realise that, yes, I &lt;em&gt;did&lt;/em&gt; intend the pacing to be different and that a comma &lt;em&gt;was&lt;/em&gt; necessary to make a pause that I’d not included.&lt;/p&gt;

&lt;p&gt;The Clarity suggestions are also great. Often, the simple fact that the text his highlighted makes me look at it in a different light, and I can see an improvement directly. I don’t always need to use Grammarly’s suggestion; the fix is obvious. That’s one great thing about using such tools: they help relieve the blindness one gets by reading a text several times. That’s why putting a text aside for a day or two can be so useful. One sees it with fresh eyes, and a tool can help in achieving that “fresh eye” state.&lt;/p&gt;

&lt;p&gt;The suggestions from Grammarly Clarity show how something can be rephrased. This is a great learning opportunity for me. I regularly look at the results and think “Oh wow, yeah, that’s a nice way to say that”. If I see a certain style of suggestion frequently enough, then &lt;em&gt;something&lt;/em&gt; eventually gets through my thick skull, and I stop making such convoluted constructions in the first place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting by without a little help from my friends
&lt;/h3&gt;

&lt;p&gt;Support from tools allows me to grow and improve on my own without needing to annoy friends or family by asking for feedback on a text. My two theses relied &lt;em&gt;a lot&lt;/em&gt; on help from others. Such tools simply didn’t exist back in the day. Thus, my Master’s and PhD theses were not the work of a single person; they were very much a team effort. I can’t imagine the burden I’d put on everyone if I had them review all my blog posts now as well!&lt;/p&gt;

&lt;h2&gt;
  
  
  Let it be
&lt;/h2&gt;

&lt;p&gt;Once I’ve completed the initial human and tool-supported edits, I let the text sit again for a day or two so that I can come back to it with fresh eyes. I then go over the text once more and try to spot any issues that might be left over. Sometimes I spot logical problems, sentences that aren’t clear, and phrases that can be deleted. Occasionally, I discover new ways in which something could be better structured.&lt;/p&gt;

&lt;p&gt;This is also the time for me to pull out Inkscape and make a cover image. I try to make something relevant to the post’s topic, and I use Creative Commons images and/or the appropriate attribution where possible.&lt;/p&gt;

&lt;p&gt;Generally speaking, once a text has gotten to this stage, I’m pretty sick of looking at it, so this is the final edit. I’m rather pleased to move it into my &lt;code&gt;_posts&lt;/code&gt; folder and consider it completed. There will probably still be leftover issues or vagueness in the text, but I’ll have to live with that!&lt;/p&gt;

&lt;h2&gt;
  
  
  Push to publish
&lt;/h2&gt;

&lt;p&gt;And that’s the last step: moving a post from the &lt;code&gt;_drafts&lt;/code&gt; folder into the &lt;code&gt;_posts&lt;/code&gt; folder. Pushing to my upstream Git repository is then the publishing process. There’s a CI job that runs on GitLab, which handles all the hard work, so I don’t have to do that on my local machine. It’s nice to go &lt;code&gt;git push&lt;/code&gt; and think “Ah, that’s finished!”. 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  All done
&lt;/h2&gt;

&lt;p&gt;And that’s it. That’s my blog post creation process. Mainly, this was for my future self to look back on my previous self and maybe realise how far I’ve developed. Or perhaps he just wants to remember part of the process. Either way: gudday future me!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Like those fun school trips out to Lake Rerewhakaaitu only to have them ruined by having to write a story about it once we got back to school. Urgh. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;… or edits. I usually make multiple passes. ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>general</category>
    </item>
    <item>
      <title>An unhinged carriage problem</title>
      <dc:creator>Paul Cochrane 🇪🇺</dc:creator>
      <pubDate>Thu, 08 Jan 2026 23:00:00 +0000</pubDate>
      <link>https://dev.to/peateasea/an-unhinged-carriage-problem-1ol1</link>
      <guid>https://dev.to/peateasea/an-unhinged-carriage-problem-1ol1</guid>
      <description>&lt;p&gt;As part of tutoring high school students in maths and physics, I sometimes run across problems that I find interesting. Here’s a deep dive into one involving an unhinged railway carriage which, at first glance, seems to lack sufficient information.&lt;/p&gt;

&lt;p&gt;I find it interesting that some solutions become almost embarrassingly obvious given the right perspective. I also like that there’s usually more than one way to solve a problem. This is one of those situations. Here’s the problem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A train is moving straight and horizontally at a constant speed. The last carriage is uncoupled from the train and slows with a constant deceleration. The train continues to move at its previous speed. The carriage moves straight and horizontally, eventually coming to a stop after 200 m. Determine the distance the train travelled from the time the carriage was uncoupled to the moment the carriage stopped.&lt;/p&gt;

&lt;p&gt;Write the answer in metres (m)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I first saw this, my instinct was that there wasn’t enough information. The solution requires a very specific answer in metres, yet we’ve not been told the carriage’s deceleration, nor the train’s speed. That struck me as odd.&lt;/p&gt;

&lt;p&gt;It turns out that it &lt;em&gt;is&lt;/em&gt; possible to calculate a definite value for how far the train travelled before the carriage stopped; it just wasn’t obvious to me from the get-go. This leads to one piece of advice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Have a go at solving the problem, even if you’re unsure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There’s another piece of advice that I usually dish out to my students:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Try solving the problem in more than one way. If you get the same answer by a different path, then the answer is more likely to be correct. You might also learn something along the way.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But I’m getting ahead of myself.&lt;/p&gt;

&lt;p&gt;Let’s have a go at solving the problem. We’ll first use a geometric argument by drawing the speed versus time graphs for the train and the unhinged carriage. Later, we’ll look at other paths to a solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visualising speed versus time
&lt;/h2&gt;

&lt;p&gt;I’m a big fan of drawing pictures and diagrams to get a feel for a given situation. Interestingly enough, my gut feeling this time &lt;em&gt;wasn’t&lt;/em&gt; to draw a train moving along a track (which would have been my usual approach) but to draw graphs of speed versus time.&lt;/p&gt;

&lt;p&gt;The question mentions constant speed a couple of times, as well as the uncoupled carriage’s constant deceleration. Thus, my physics-addled mind’s eye straight away saw lines on a speed versus time graph, and I started doodling these on a piece of paper. What follows is a more neatly-drawn&lt;sup id="fnref:drawn-with-tikz"&gt;1&lt;/sup&gt; version interspersed with explanations.&lt;/p&gt;

&lt;p&gt;First, we need some axes and to label them:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe1zuq7k1b6zkc3cuw1ml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe1zuq7k1b6zkc3cuw1ml.png" alt="Graph axes with grid showing only speed and time axes labels"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The carriage’s initial speed is the same as the train’s speed when it is uncoupled. Let’s call this 

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vtv_t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and mention it on the graph, so that we can refer to it again later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyb98r965w8qcgibwuame.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyb98r965w8qcgibwuame.png" alt="Graph axes with grid showing label for train speed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since we’re only interested in elapsed time, the time that the carriage is uncoupled from the train happens at zero seconds. The time that the carriage stops, we’ll call 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t1t_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. We now label the graph with this information:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqciagmlpn6f33qku9of.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqciagmlpn6f33qku9of.png" alt="Graph axes with grid showing labels for start and end times"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We know that the carriage slows with constant deceleration and that deceleration is simply negative acceleration, hence we’ll denote it by 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;−a-a&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;−&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. Deceleration is a line of negative slope 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;(−a)(-a)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;−&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 in the speed versus time graph and connects the time-speed coordinate 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;(0,vt)(0, v_t)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 with 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;(t1,0)(t_1, 0)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. Adding this to the graph, we have:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmee384ajdnux1dckw26w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmee384ajdnux1dckw26w.png" alt="Graph axes with grid showing uncoupled carriage speed over time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also know that the area under a speed versus time graph is the distance travelled. Therefore, we shade this area to highlight it and make a note on the graph that this is equal to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;200 m200\ \mathrm{m}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;200&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord mathrm"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlr56ohuj8o013s5rfxk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlr56ohuj8o013s5rfxk.png" alt="Graph axes with grid showing distance covered by carriage with shaded area under curve"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s cool. We’ve described, in a graphical form, the uncoupled carriage’s behaviour from when it separated from the train up until it stopped moving.&lt;/p&gt;

&lt;p&gt;So what happened to the train over this time? Well, we know that it kept going at the same speed. And we know that constant speed on a speed versus time graph is also a straight line, but with zero slope. In other words, it’s a horizontal line from the time-speed coordinate 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;(0,vt)(0, v_t)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;(t1,vt)(t_1, v_t)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. Let’s add that to our graph:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1b1h64mlc3zi6unjae3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1b1h64mlc3zi6unjae3.png" alt="Graph axes with grid showing train speed curve"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As with the carriage, the area under its curve is how far the train travelled in this time. We can shade in this area as well:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbk0961j0qm3erlw86an.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbk0961j0qm3erlw86an.png" alt="Graph axes with grid showing distance travelled by train as shaded area below train speed curve"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s clear from the graph that the area under the line representing the train’s speed versus time behaviour is enclosed by a rectangle. It’s also clear that the area under the carriage’s curve is enclosed by a triangle, and that the triangle’s hypotenuse &lt;em&gt;bisects&lt;/em&gt; the rectangle. In such a case, the triangle’s area is half the rectangle’s area. Since we know that the triangle’s area is equal to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;200 m200\ \mathrm{m}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;200&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord mathrm"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, we can say that the rectangle’s area must be equal to double that, i.e. 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;400 m400\ \mathrm{m}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;400&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord mathrm"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. Thus, the train travelled 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;400 m400\ \mathrm{m}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;400&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord mathrm"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 in the time it took the uncoupled carriage to come to a halt.&lt;/p&gt;

&lt;p&gt;There we have it! That’s the answer!&lt;/p&gt;

&lt;p&gt;Now we can see that it wasn’t important how fast the carriage decelerated, nor was it important how fast the train was travelling. Thus, my initial feeling about missing information was unfounded. Hence, we see why it was a good idea to attempt to solve the problem to see if we could get anywhere. Also, the answer sort of “pops out” at us as soon as we draw the speed versus time graphs: we only needed a bit of geometry and to know the physical meaning of the area under the curve to find the answer. It’s almost blindingly obvious in the end.&lt;/p&gt;

&lt;p&gt;We now put our fingers in our ears and go “la! la! la!” loudly, to try and ignore the fact that we know the answer. Then, we’ll solve the problem algebraically without using any pictures or graphs.&lt;/p&gt;

&lt;p&gt;Why do this “the hard way”? Why not? Come on, let’s dig in and see what happens!&lt;/p&gt;
&lt;h2&gt;
  
  
  An algebraic approach
&lt;/h2&gt;

&lt;p&gt;As with the graphical approach above, we collect what we know from the problem description and see if we can make some headway by combining things logically.&lt;/p&gt;

&lt;p&gt;We know that the train travels at a constant speed the entire time, so let’s call that 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vtv_t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. We’re told that the last carriage is unhinged (i.e. uncoupled) from the train at some time; thereafter, it decelerates at a constant rate. Since deceleration is negative acceleration, let’s call this quantity 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;−a-a&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;−&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. The carriage starts with the same speed as the train, finally coming to a stop at some later time. Let’s set the initial time to zero and call the time the carriage stops 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t1t_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. With this information, we can write an equation to describe the carriage’s speed between these two times. Let’s call the carriage’s speed 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vcv_c&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, which we can write as:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vc=vt−at,
\begin{equation}
v_c = v_t - a t,
\end{equation}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="eqn-num"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;where 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;tt&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the elapsed time.&lt;/p&gt;

&lt;p&gt;Note that this equation has the same form as the equation for a straight line in the plane:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;y=mx+c,
y = m x + c,
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;y&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;c&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;where 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;y=vcy = v_c&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;y&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;m=−am = -a&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;−&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;x=tx = t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;c=vtc = v_t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;c&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/p&gt;

&lt;p&gt;We can see that (1) behaves the way we want by considering the start and end points.&lt;/p&gt;

&lt;p&gt;At the uncoupling event, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t=0t = 0&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, hence when we substitute this into (1), we find that the speed of the carriage when it gets unhinged is:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vc(0)=vt−a⋅0=vt,
v_c(0) = v_t - a \cdot 0 = v_t,
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;which is the 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;yy&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 intercept. That makes sense, because we know that the carriage’s initial speed is the same as the train’s speed. Cool, that means we’re probably on the right track.&lt;/p&gt;

&lt;p&gt;The 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;−at-a t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;−&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 term in (1) linearly decreases the value of 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vcv_c&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, tracing out a line which then intersects the 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;xx&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
-axis at 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t1t_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. In other words, the speed is equal to zero at 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t1t_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. This is the behaviour we want at the other end of the time interval. Good, we’re &lt;em&gt;still&lt;/em&gt; on the right track.&lt;/p&gt;

&lt;p&gt;We know that the carriage stops at 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t1t_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, thus we have the relationship:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vc(t1)=vt−at1=0.
v_c(t_1) = v_t - a t_1 = 0.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;That might not look that useful, but we can rearrange it to give an expression for the time when the carriage stops, and that could come in handy later:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vt−at1=0,
\begin{equation}
v_t - a t_1 = 0,
\end{equation}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="eqn-num"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;⇒at1=vt,
\begin{equation}
\Rightarrow a t_1 = v_t,
\end{equation}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mrel"&gt;⇒&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="eqn-num"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;⇒t1=vta.
\begin{equation}
\Rightarrow t_1 = \frac{v_t}{a}.
\end{equation}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mrel"&gt;⇒&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="eqn-num"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;What else do we know? Well, we know that the train travels at constant speed between 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t=0t = 0&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t=t1t = t_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. That means we know how far the train went in that time: this is its speed multiplied by the elapsed time. In other words, the distance the train travelled (which we’ll call 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dtd_t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
) is:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dt=vtt1.
d_t = v_t t_1.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Since we have an expression for 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t1t_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (Equation (4)), we can rewrite the expression for 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dtd_t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 to see if it might be useful:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dt=vtt1,
\begin{equation}
d_t = v_t t_1,
\end{equation}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="eqn-num"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=vtvta,
\begin{equation}
= v_t \frac{v_t}{a},
\end{equation}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="eqn-num"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;⇒dt=vt2a.
\begin{equation}
\Rightarrow d_t = \frac{v_t^2}{a}.
\end{equation}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mrel"&gt;⇒&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="tag"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="eqn-num"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Hrm, that doesn’t look like it’s going to be of much help. Oh well. Let’s add it to the growing pile of things that we know anyway and see what else we know and/or can deduce.&lt;/p&gt;

&lt;p&gt;What about the distance the last carriage travels? We know that its value is 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;200 m200\ \mathrm{m}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;200&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord mathrm"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. Can we write an expression for it in terms of the other things we know? Yes, we can! We know that the carriage’s speed is described by:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vc=vt−at.
v_c = v_t - a t.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;We also know that distance is the integral of the speed between two points in time.&lt;sup id="fnref:sly-area-under-curve-reuse"&gt;2&lt;/sup&gt; Thus, to find the distance travelled by the carriage, we integrate Equation (1) with respect to time between the start and end points, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t=0t = 0&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t=t1t = t_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. To be consistent with our other notation, let’s call the distance travelled by the carriage 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dcd_c&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. Putting this all together, we have:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dc=∫0t1vt−at dt,
d_c = \int_{0}^{t_1} v_t - a t\ dt,
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;&lt;span class="mop op-symbol large-op"&gt;∫&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=[vtt−12at2]0t1,
= \left[v_t t - \frac{1}{2} a t^2 \right]_{0}^{t_1},
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size3"&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size3"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;⇒dc=vtt1−12at12.
\Rightarrow d_c = v_t t_1 - \frac{1}{2} a t_1^2.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;⇒&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Squinting at this result, one gets the feeling that it’d be nice to remove at least &lt;em&gt;one&lt;/em&gt; of the variables. Since we already have an expression for 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t1t_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (Equation (4)), we can try substituting that into the equation for 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dcd_c&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 to see what happens:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dc=vtvta−12a(vta)2,
d_c = v_t \frac{v_t}{a} - \frac{1}{2} a \left( \frac{v_t}{a} \right)^2,
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size2"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size2"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=vt2a−12avt2a2,
= \frac{v_t^2}{a} - \frac{1}{2} a \frac{v_t^2}{a^2},
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=vt2a−12vt2a,
= \frac{v_t^2}{a} - \frac{1}{2} \frac{v_t^2}{a},
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=12vt2a.
= \frac{1}{2} \frac{v_t^2}{a}.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Hrm, that 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vt2a\frac{v_t^2}{a}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 bit looks familiar. Hang on! That’s the same as the expression for the distance the train travelled from earlier (Equation (7)). In other words,&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dc=12dt,
d_c = \frac{1}{2} d_t,
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;⇒dt=2dc.
\Rightarrow d_t = 2 d_c.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;⇒&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;This means that the carriage travelled half the distance that the train travelled. Which is the same as saying that the train travelled &lt;em&gt;twice&lt;/em&gt; the distance that the carriage travelled. Wow, that turned out to be a very simple relationship in the end!&lt;/p&gt;

&lt;p&gt;Now, we know that 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dc=200 md_c = 200\ \mathrm{m}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;200&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord mathrm"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, as that was given to us in the question. Thus, the distance the train travelled in the time it took for the carriage to come to a stop is 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dt=400 md_t = 400\ \mathrm{m}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;400&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord mathrm"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/p&gt;

&lt;p&gt;And that’s it! We solved the problem. Yay! &lt;em&gt;And&lt;/em&gt; we got the same result as the graphical approach outlined earlier. Cool! 🎉 I love it when a calculation comes together. 😉&lt;/p&gt;

&lt;p&gt;There’s something else one can learn here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What looks like a dead end in a calculation might come in useful anyway.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After all, calculating the distance travelled by the train in terms of its velocity and the carriage’s deceleration &lt;em&gt;looked&lt;/em&gt; like it wasn’t very helpful. But in the end, it gave us a useful, simplifying hint which led to the answer.&lt;/p&gt;
&lt;h2&gt;
  
  
  An average solution
&lt;/h2&gt;

&lt;p&gt;There’s another way of looking at this problem. We can consider &lt;em&gt;average&lt;/em&gt; speeds.&lt;/p&gt;

&lt;p&gt;The fundamental insight with this approach is that, for a situation involving constant acceleration, the distance travelled is proportional to the average speed.&lt;/p&gt;

&lt;p&gt;Let’s first consider the case for the train. Its speed at both the beginning (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t=0t = 0&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
) and at the end (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t=t1t = t_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
) is equal to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vtv_t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. We know that the distance it travels is its speed multiplied by the elapsed time:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dt=vt(t1−0)=vtt1.
d_t = v_t (t_1 - 0) = v_t t_1.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Because the train doesn’t change speed, that means the train’s average speed, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vˉt\bar{v}_t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, is the same as the train’s speed. I.e.&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vˉt=vt,0+vt,12=vt+vt2=2vt2=vt,
\bar{v}_t = \frac{v_{ t,0} + v_{t,1}}{2} = \frac{v_t + v_t}{2} = \frac{2 v_t}{2} = v_t,
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mtight"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;where 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vt,0v_{t,0}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mtight"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vt,1v_{t,1}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 are the speeds of the train at the beginning and end of the time interval, respectively.&lt;/p&gt;

&lt;p&gt;We can now write the distance the train travelled in terms of its average speed:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dt=vtt1=vˉtt1.
d_t = v_t t_1 = \bar{v}_t t_1.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;This can be formulated more loosely as:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dt∼vˉt.
d_t \sim \bar{v}_t.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;∼&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Because we’re considering the same time interval for both the distance travelled by the train and by the unhinged carriage, the elapsed time (which is equal to 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;t1t_1&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
) ends up being just a scaling constant. Hence, the distance travelled is proportional to the average speed.&lt;/p&gt;

&lt;p&gt;Of course, the carriage &lt;em&gt;does&lt;/em&gt; change speed, and over the same time interval. We also have a constant acceleration&lt;sup id="fnref:decleration-negative-acceleration"&gt;3&lt;/sup&gt; for the unhinged carriage, so we have the same kind of proportionality relationship between the distance and average speed, i.e.:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dc∼vˉc.
d_c \sim \bar{v}_c.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;∼&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;The average speed for the carriage is:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vˉc=vc,0+vc,12,
\bar{v}_c = \frac{v_{c,0} + v_{c,1}}{2},
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mtight"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;where 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vc,0v_{c,0}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mtight"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vc,1v_{c,1}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 are the speeds of the carriage at the beginning and end of the time interval, respectively.&lt;/p&gt;

&lt;p&gt;Because the carriage’s speed at the beginning is equal to the train’s speed, and the carriage’s speed at the end is equal to zero, we have 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vc,0=vtv_{c,0} = v_t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mtight"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vc,1=0v_{c,1} = 0&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. Thus, the carriage’s average speed ends up being:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vˉc=vt+02=vt2.
\bar{v}_c = \frac{v_t + 0}{2} = \frac{v_t}{2}.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;I’m sure you can see where this is going. But let’s continue anyway to nail everything down more firmly.&lt;/p&gt;

&lt;p&gt;Since the distances are proportional to the average speeds, the &lt;em&gt;ratios&lt;/em&gt; of the distances will be equal to the &lt;em&gt;ratios&lt;/em&gt; of the respective average speeds. In other words, we can write:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dtdc=vˉtvˉc.
\frac{d_t}{d_c} = \frac{\bar{v}_t}{\bar{v}_c}.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Since we know what 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dcd_c&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vˉt\bar{v}_t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;vˉc\bar{v}_c&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 are, we can rearrange this to give us our only unknown, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dtd_t&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dt=dcvˉtvˉc,
d_t = d_c \frac{\bar{v}_t}{\bar{v}_c},
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord accent"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="accent-body"&gt;&lt;span class="mord"&gt;ˉ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=dcvtvt2,
= d_c \frac{v_t}{\frac{v_t}{2}},
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=dcvt2vt,
= d_c v_t \frac{2}{v_t},
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=2dc.
= 2 d_c.
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;And since we know that 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dc=200 md_c = 200\ \mathrm{m}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;200&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord mathrm"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, we have the distance the train travels to be&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;dt=2dc=2⋅200 m=400 m,
d_t = 2 d_c = 2 \cdot 200\ \mathrm{m} = 400\ \mathrm{m},
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;200&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord mathrm"&gt;m&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;400&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;span class="mord mathrm"&gt;m&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;which is our result from before. Yay!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;So there we have it. Although the solution wasn’t very mind-blowing, the journey turned out to be much more instructive than the destination. And that’s much more valuable from a problem-solving perspective.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Why, yes, I &lt;em&gt;did&lt;/em&gt; create these graphs with &lt;a href="https://en.wikipedia.org/wiki/PGF/TikZ" rel="noopener noreferrer"&gt;TikZ&lt;/a&gt;. Why do you ask? ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Yes, I’m slyly re-using the idea of the distance being the area under the curve here. ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Well, it’s a deceleration, but that’s just a negative acceleration. I might have mentioned this before. 😉 ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>maths</category>
      <category>physics</category>
      <category>highschool</category>
    </item>
  </channel>
</rss>
