{"id":19838661,"url":"https://github.com/brayvid/frog-problem","last_synced_at":"2025-11-08T06:04:46.264Z","repository":{"id":231398715,"uuid":"213703611","full_name":"brayvid/frog-problem","owner":"brayvid","description":"My solution to Matt Parker's Frog Problem.","archived":false,"fork":false,"pushed_at":"2024-06-23T21:31:36.000Z","size":1820,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-11T11:18:25.019Z","etag":null,"topics":["probability","recreational-mathematics","standupmaths"],"latest_commit_sha":null,"homepage":"https://colab.research.google.com/github/brayvid/frog-problem/blob/master/FrogProblem.ipynb","language":"Jupyter Notebook","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brayvid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-08T17:07:08.000Z","updated_at":"2024-08-04T17:25:42.000Z","dependencies_parsed_at":"2024-04-11T19:28:17.785Z","dependency_job_id":"e4737b26-5fcb-42fe-ad88-da2609db0e97","html_url":"https://github.com/brayvid/frog-problem","commit_stats":null,"previous_names":["brayvid/frogproblem","brayvid/frog-problem"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brayvid%2Ffrog-problem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brayvid%2Ffrog-problem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brayvid%2Ffrog-problem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brayvid%2Ffrog-problem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brayvid","download_url":"https://codeload.github.com/brayvid/frog-problem/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241209528,"owners_count":19927734,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["probability","recreational-mathematics","standupmaths"],"created_at":"2024-11-12T12:18:34.993Z","updated_at":"2025-11-08T06:04:46.223Z","avatar_url":"https://github.com/brayvid.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The Frog Problem\n\u003ca href=\"https://colab.research.google.com/github/brayvid/frog-problem/blob/master/FrogProblem.ipynb\" rel=\"Open in Colab\"\u003e\u003cimg src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open in Colab\" /\u003e\u003c/a\u003e\n\n\u003ch4\u003eBlake Rayvid - \u003ca href=https://github.com/brayvid\u003ehttps://github.com/brayvid\u003c/a\u003e\u003c/h4\u003e\n\n#### Presented by Timandra Harkness and Matt Parker in [*Can you solve The Frog Problem?*](https://www.youtube.com/watch?v=ZLTyX4zL2Fc)\n\n### Statement\n\nImagine some number of lilypads spanning a river in a line, and a frog at one bank. The frog wants to cross the river. To move forward, it selects one of the lilypads with uniform probability (or the far bank, which we include as an option), hops there, selects a new position closer to its destination, and repeats this process until it eventually reaches the far side.\n\n\u003cstrong\u003e*For a given number of lilypads p, what is the expected number of jumps for the frog to make it across the river?*\u003c/strong\u003e\n\n### Solution\n\nThe code in this notebook uses functions from the [``scipy``](https://docs.scipy.org/doc/scipy/reference/), [``itertools``](https://docs.python.org/2/library/itertools.html#itertools.combinations), [``numpy``](https://docs.scipy.org/doc/numpy/) and [``matplotlib``](https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.html#module-matplotlib.pyplot) modules.\n\n\n```python\nfrom scipy.special import comb # \"a choose b,\" aka binomial coefficient\nfrom itertools import combinations # lists the actual combinations\nimport numpy as np # matrix operations\nfrom matplotlib import pyplot as pl # plots points\n```\n\n#### A few definitions\n\n* Let $p$ be the number of lilypads present. Note that the maximum number of jumps is $p+1$.\n* Let $k$ be the number of jumps the frog uses to cross the river, $1\\leq k\\leq p+1$.\n* Let $r={p \\choose k-1}$ count the number of ways the frog can cross the river in exactly $k$ jumps.\n\n#### Example of a route\n\nThe picture below depicts one of the $10$ different ways the frog can cross the river in $3$ steps with $5$ lillypads present.\n\n\u003ccenter\u003e\u003cimg src=\"https://raw.githubusercontent.com/brayvid/FrogProblem/master/FrogExample.png\" width=350px\u003e\u003c/center\u003e\n\nLanding on position $2$ from position $0$ has probability $\\frac{1}{6}$, since six positions are initially available to the frog and each is equally likely. In the same way, getting to position $3$ from position $2$ has probability $\\frac{1}{4}$, and getting to the far shore from position $3$ has probability $\\frac{1}{3}$.\n\nThus, the overall probability of taking that particular route as opposed to any other is $\\frac{1}{6} \\cdot \\frac{1}{4}\\cdot \\frac{1}{3} = \\frac{1}{72} \\approx 0.014$. We can compute the probability of any route in this way. We expect (and can show) that the probabilities of all routes will add up to $1$.\n\n#### List all $r$ possible routes for a given $(p,k)$\n\nThe function ``listRoutes(p,k)`` returns all routes for a given $p$ and $k$ as a ``numpy.array`` of size $(r,k+1)$. Each row represents a unique sequence of positions starting at $0$ and ending at $p+1$.\n\n\n```python\ndef listRoutes(p, k):\n  rows = comb(p, k - 1, 1)\n  cols = k + 1\n\n  M = [[0 for x in range(cols)] for y in range(rows)]\n\n  C = list(combinations(range(1, p + 1), k - 1))\n\n  for l in range(k - 1):\n    for r in range(rows):\n      M[r][l + 1] = C[r][l]\n\n  for r in range(rows):\n      M[r][cols - 1] = p + 1\n\n  return np.array(M)\n```\n\nFollowing the earlier example, here is the matrix for $p=5$ and $k=3$:\n\n\n```python\nlistRoutes(5,3)\n```\n\n\n\n\n    array([[0, 1, 2, 6],\n           [0, 1, 3, 6],\n           [0, 1, 4, 6],\n           [0, 1, 5, 6],\n           [0, 2, 3, 6],\n           [0, 2, 4, 6],\n           [0, 2, 5, 6],\n           [0, 3, 4, 6],\n           [0, 3, 5, 6],\n           [0, 4, 5, 6]])\n\n\n\nThere are indeed ${5 \\choose 2} = 10$ unique ways for the frog to cross the river.\n\n#### Express the probability of taking a particular route for a given $(p,k)$\n\nGiven that at each step along the route all remaining positions have an equal chance of being selected next: if the frog is at position $a$, the probability that the frog will then select the $b^{th}$ position (where $b\u003ea$) equals $(p-a+1)^{-1}$. For example, if there are 3 lillypads and the frog is currently at position $2$, the remaining positions ($3$ and $4$) each have a $\\frac{1}{3-2+1}=\\frac{1}{2}$ chance of being selected.\n\u003cbr\u003e\u003cbr\u003e\nTo find the probability $P(x)$ that a certain route $x\\in\\{1,2,...,r\\}$ is taken, multiply the probabilities of each successive jump in the sequence:\n\u003cbr\u003e\u003cbr\u003e\n$$P(x)=\\prod_{j=1}^{k} (p-m_{x,j}+1)^{-1}.$$\n\u003cbr\u003e\u003cbr\u003e\nwhere $m_{x,j}$ is the element of $M$ in the $x^{th}$ row and $j^{th}$ column, and $M$ is the particular route matrix for the pair $(p,k)$.\n\n#### Express the probability of taking any route of length $k$ for a given $p$\n\nSince each route is unique and the list is exhaustive, the probability $P^{\\prime}(k)$ that the frog will jump exactly $k$ times to reach the far bank is the sum of the probabilities of each route of length $k$ occuring (i.e. sum the above result over all rows):\n\u003cbr\u003e\u003cbr\u003e\n$$P^{\\prime}(k)=\\sum_{i=1}^{r} \\prod_{j=1}^{k} (p-m_{i,j}+1)^{-1},$$\n\nThe function ``pathLengthProbability(p,k,m)`` implements the above formula, returning $P^{\\prime}(k)$ for a given $(p,k)$ and a corresponding matrix $M$:\n\n\n```python\ndef pathLengthProbability(p, k, m):\n  M = m[:,:-1]\n  N = np.full((M.shape[0], k), p + 1)\n  minusNM = np.subtract(N, M)\n  overNsubM = np.divide(np.ones((M.shape[0], k)), minusNM)\n  s = np.sum(np.prod(overNsubM, axis = 1))\n  return s\n```\n\nThe function ``lengthProb(p,k)`` simply wraps ``pathLengthProbability(p,k,m)`` and ``listRoutes(n,k)`` together for ease of use, returning $P^{\\prime}(k)$ for a particular pair $(p,k)$:\n\n\n```python\ndef lengthProb(p, k):\n  if k \u003c= (p + 1) and k \u003e= 1:\n    return pathLengthProbability(p, k, listRoutes(p, k))\n  else:\n    print(\"Bad input\")\n    return 0\n```\n\n#### Express the expected number of steps\n\nThe expectation of a discrete random variable $X$ is defined as the sum over the sample space $\\Omega$:\n\u003cbr\u003e\u003cbr\u003e\n$$E(X)=\\sum_{\\omega\\in\\Omega}x_{\\omega}P(x_{\\omega}).$$\n\u003cbr\u003e\nTherefore the solution to the problem, the number of steps in which we expect the frog to cross the river for a given $p$, is:\n\u003cbr\u003e\u003cbr\u003e\n$$E(steps)=\\sum_{k=1}^{p+1}k P^{\\prime}(k)=\\sum_{k=1}^{p+1}k\\sum_{i=1}^{r} \\prod_{j=1}^{k} (p-m_{i,j}+1)^{-1}.$$\n\u003cbr\u003e\u003cbr\u003e\n\n*Note: $M$ will change for each term in the outer sum. A new one must be computed for each value of $k$.*\n\nThe function ``expectedSteps(p)`` returns the above quantity given some $p$:\n\n\n```python\ndef expectedSteps(p):\n  n = p + 1\n  s = 0\n  for k in range(1, n + 1):\n    s += (k * lengthProb(p, k))\n  return s\n```\n\n### Examples\n\n#### Find the probability that $k=1$ given $p=4$\n\n\n```python\nlengthProb(4,1)\n```\n\n\n\n\n    0.2\n\n\n\n#### Show that the total probability of all routes is $1$ for $p=5$\n\n\n```python\np = 5\nn = p + 1 # max possible jumps\ns = 0\nfor k in range(1, n + 1):\n  s += lengthProb(p, k)\nprint(s)\n```\n\n    1.0\n\n\n#### Find the expected number of steps for $p=1$\n\n\n```python\nexpectedSteps(1)\n```\n\n\n\n\n    1.5\n\n\n\n#### Plot the expected steps for several $p$\n\n\n```python\n# Values of p to check\nlowP = 0\nhighP = 20\n\n# Plot points\nx = range(lowP, highP + 1)\ny = []\nfor p in x:\n  y.append(expectedSteps(p))\npl.plot(x,y,'ko')\npl.xlabel('Number of lillypads')\npl.ylabel('Expected number of jumps')\npl.title('Expected jumps vs. number of lillypads')\npl.xticks(np.arange(min(x), max(x) + 1, 1))\npl.yticks(np.arange(min(y), max(y) + 0.25, 0.25))\npl.show()\n```\n\n\n    \n![png](FrogProblem.png)\n    \n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrayvid%2Ffrog-problem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrayvid%2Ffrog-problem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrayvid%2Ffrog-problem/lists"}