{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Course 2.2: Conditionals\n",
    "======================\n",
    "\n",
    "In the previous course we learned\n",
    "- how to manipulate objects of type `list`\n",
    "- `for` loop\n",
    "- `range`\n",
    "\n",
    "Be sure that these concepts are understood before starting this third worksheet! In this note we will learn:\n",
    " - how to do an operation under a certain condition (`if`, `elif`, `else`)\n",
    " - how to repeat an action until a certain condition is verified (`while` loop)\n",
    " - the operators `or`, `and`, `not`\n",
    " - the functions `all`, `any`\n",
    "  \n",
    "\n",
    "`if`/`elif`/`else`\n",
    "------------------\n",
    "\n",
    "This constructions allows you to perform an instruction only when a certain condition is fullfilled. The syntax is\n",
    "```python\n",
    "if condition:\n",
    "    instruction      # executed if condition is realized\n",
    "```\n",
    "or\n",
    "```python\n",
    "if condition:\n",
    "    instruction1     # executed if condition is realized\n",
    "else:\n",
    "    instruction2     # executed if condition is not realized\n",
    "```\n",
    "or possibly\n",
    "```python\n",
    "if condition1:\n",
    "    instruction1     # executed if condition1 is realized\n",
    "elif condition2:\n",
    "    instruction2     # executed if condition1 is not realized but condition2 is\n",
    "elif instruction3:\n",
    "    instruction3     # executed if condition 1 and 2 are not realized but condition3 is\n",
    "```\n",
    "The possible number of intermediate `elif` is unlimited. The final `else` is optional.\n",
    "\n",
    "This is well illustrated if you want to compute the sign of a real number `x` (that is `-1` if `x` is negative, `0` if x is zero and `1` if x is positive)\n",
    "```python\n",
    "if x > 0:\n",
    "    s = 1\n",
    "elif x == 0:\n",
    "    s = 0\n",
    "else:\n",
    "    s = -1\n",
    "```\n",
    "**Exercise:**\n",
    "- Sets `x` to some value copy the above `if/elif/else` statement to compute its sign and print the value of `s`\n",
    "- Run this code with another value of `x`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Exercise:** This exercise is similar to something we did in the first worksheet (in the section \"Playing with strings\"). We consider the substitution on strings $a \\mapsto ab, b \\mapsto ac, c \\mapsto a$. Starting from $s_0 = a$, applying repeatedly this substitution we obtain $s_1 = ab$, $s_2 = abac$, $s_3 = abacaba$, etc. Print the first 15th terms of this sequence (*hint: you need to write a for loop with a `if/elif/else` statement inside*)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Exercise:** Starting from an integer value $x_0$ its Collatz sequence is define by $x_{n+1} = \\frac{x_n}{2}$ if $x_n$ is even and $x_{n+1} = 3 x_n + 1$ otherwise. Starting from $x_0 = 2^{10} + 1$ what are the first 20 terms of its Collatz sequence? How will it continues?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is also possible to use the `if` construction in list comprehension. For example, the following code\n",
    "```python\n",
    "[x for x in range(20) if x**2 < 30]\n",
    "```\n",
    "builds the list of integer $x$ in $\\{0, 1, \\ldots, 19\\}$ that satisfies the condition $x^2 < 30$. You can see that it is very similar to the notation from set theory $$\\{x \\in \\{0, 1, \\ldots, 19\\}: x^2 < 30\\}.$$\n",
    "\n",
    "**Exercise:** Build the list of Fibonacci numbers $F_n$ with $n$ less than 50 so that $F_n$ is congruent to 1 mod 7."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`while` loop\n",
    "------------\n",
    "\n",
    "We have already seen how to repeat an action a certain amount of times.\n",
    "There is a second and more powerful way of repeating actions: `while` loops. A certain action is repeated while a certain condition is satisfied.\n",
    "\n",
    "**Exercise:**\n",
    "- Can you guess what does the following loop do?\n",
    "```python\n",
    "n = 10\n",
    "while n >= 0:\n",
    "    n -= 3\n",
    "```\n",
    "(*hint: you can add a print statement with the value of `n` inside the `while` loop*)\n",
    "- What is the value of `n` at the end?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Exercise:** To answer this exercise you are not allowed to use a list.\n",
    "- what is the first Fibonacci number larger than $2^{2^{2^{2^2}}}$?\n",
    "- how many digits does it have?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Exercise:** It is a famous conjecture that starting from any positive integer $x_0$ the associated Collatz sequence is ultimately periodic $1 \\mapsto 4 \\mapsto 2 \\mapsto 1 \\mapsto \\ldots$. Check this conjecture for the first 1000th integers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Constructing complex conditions: `or`, `and`, `not`, `any`, `all`\n",
    "-----------------------------------------------------------------\n",
    "\n",
    "In the `if`, `elif` or `while` constructions the condition can be any Python object. For example the following is valid Python syntax\n",
    "```python\n",
    "if \"I am nice\":\n",
    "    print(\"hello\")\n",
    "```\n",
    "What happens is that the Python string `\"I am nice\"` is implictely converted into a boolean (`True` or `False`). You can obtain this boolean with the explicit conversion\n",
    "```python\n",
    "bool(\"I am nice\")\n",
    "```\n",
    "\n",
    "**Exercise:**\n",
    "- execute the following command\n",
    "```python\n",
    "[bool(i) for i in range(-10, 10)]\n",
    "```\n",
    "- what do you think about conversion of integers to booleans?\n",
    "- **without executing the code** tell what is the output of the following list of commands\n",
    "```python\n",
    "i = 5\n",
    "while i:\n",
    "    if i - 3:\n",
    "        print(i)\n",
    "    i = i - 1\n",
    "print(i)\n",
    "```\n",
    "once you have an answer you can check by executing it.\n",
    "- Check on examples that a Python floating point converts to `True` if and only if it is not zero\n",
    "- Check on examples that a Python list (or string) converts to `True` if and only if it is not empty"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With this boolean conversions in mind, we now introduce some operations to build more complex conditions\n",
    "\n",
    "| command   | description                                                     |\n",
    "|-----------|-----------------------------------------------------------------|\n",
    "| `a or b`  | returns `a` if it converts to `True` otherwise returns `b`      |\n",
    "| `a and b` | returns `a` if it converts to `False` otherwise returns `b`     |\n",
    "| `not x`   | returns `True` if `x` converts to `False` and `False` otherwise |\n",
    "\n",
    "**Exercise:**\n",
    "- Based on the definition above what is the result of each command below\n",
    "```python\n",
    "1 or 0\n",
    "0 or 1\n",
    "(0 and 3) == (0 and 2)\n",
    "(1 or []) == (2 and 1)\n",
    "not []\n",
    "```\n",
    "check by copy, paste, execute.\n",
    "- What happens if you remove the paranthesis in the third and fourth examples?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Exercise:** What does the following code do?\n",
    "```python\n",
    "l = [1, 12, 5, 14, -6, 13, 19, -4, 10]\n",
    "l2 = [x for x in l if x > 0 and not x < 10 or x == 14]\n",
    "```\n",
    "Check your answer by copy, paste, execute."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we see two more constructions with the functions `any` and `all`. They allow to check for a whole range of conditions. For example the following\n",
    "```python\n",
    "all(x % 3 == 1 for x in l)\n",
    "```\n",
    "checks if all elements in a list `l` are congruent to 1 modulo 3. While\n",
    "```python\n",
    "any(x > 2 for x in l)\n",
    "```\n",
    "checks that if one of the element in the list `l` is larger than 2. Note that the syntax is very similar to the one used for list comprehension. Note also that these are the very same thing as the quantifier $\\forall$ (for all) and $\\exists$ (exists) in mathematics.\n",
    "\n",
    "**Exercise:**\n",
    "For each of the command below tell what will be the output **without executing it**\n",
    "```python\n",
    "all([1, 2, 3])\n",
    "all(range(10))\n",
    "all(range(-10, 10, 3))\n",
    "any(x % 5 == 0 for x in [6, 7, 8, 9])\n",
    "all([])\n",
    "any([])\n",
    "```\n",
    "Once you have an answer, you can check it by copy, paste, execute."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Exercise:** In this exercise you are asked to understand what is doing the code **without executing it**. What is the value of the list `l` at the end of the execution of\n",
    "```python\n",
    "l = [0, 1]\n",
    "while any(x < 4 for x in l):\n",
    "    l = [2*i + 1 for i in l if i % 5 != 3]\n",
    "    l.append(l[-2] + l[-1])\n",
    "```\n",
    "Once you have an answer you can check with copy, paste and execute."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Extra exercises\n",
    "---------------\n",
    "Below are two more complicated exercises. You have learned enough Python to do them. However, do not worry if you do not succeed since it is delicate to design the algorithm."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Exercise (++):**\n",
    "- Print all possible permutations of the list `[0, 1, 1, 2, 2, 2, 3, 3, 3, 3]`\n",
    "- How many are they?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Exercise (++):**\n",
    "A partition of a positive integer `n` is a weakly decreasing list of positive integers whose sum is `n`. For example the partitions of 4 are in reverse lexicographic order\n",
    "\n",
    "    [4]\n",
    "    [3, 1]\n",
    "    [2, 2]\n",
    "    [2, 1, 1]\n",
    "    [1, 1, 1, 1]\n",
    "\n",
    "- Print all partitions of 10.\n",
    "- how many are they?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Copyright (C) 2016 Vincent Delecroix <vincent.delecroix@u-bordeaux.fr>\n",
    "\n",
    "This work is licensed under a Creative Commons Attribution-NonCommercial 4.0\n",
    "International License (CC BY-NC-SA 4.0). You can either read the\n",
    "[Creative Commons Deed](https://creativecommons.org/licenses/by-nc-sa/4.0/)\n",
    "(Summary) or the [Legal Code](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode)\n",
    "(Full licence)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}